eye-tracking/notebooks/Example, find corners via c...

282 lines
8.9 MiB
Plaintext
Raw Permalink Normal View History

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Locate corners by paperprograms.js-like markers\n",
"\n",
"Uses the opencv blobdetector, distance-based neighbor based clustering and cosine similarity to respectively find the markers, the markers beloning to the same corner and the markers in corner belonging to the same edge."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"sys.path.append('..')\n",
"from pagelocalizer import find_corner_circles, cluster_circles_per_corner, intersection_per_corner, separate_lines, find_line_coefficients_per_corner\n",
"import numpy\n",
"import glob\n",
"import cv2\n",
"\n",
"%matplotlib inline\n",
"from matplotlib import pyplot, rcParams\n",
"\n",
"rcParams['figure.figsize'] = (9, 7)\n",
"rcParams['figure.dpi'] = '100'"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"im = cv2.imread(\"../images/img4.jpg\", cv2.IMREAD_COLOR)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<matplotlib.figure.Figure at 0x7f8912ce8dd8>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pyplot.imshow(im)\n",
"pyplot.axis('off')\n",
"None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Keypoints\n",
"\n",
"Use the opencv blob detector to find the circles around the corners, with possible false positives but hopefully no false negatives."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"keypoints = find_corner_circles(im,\n",
" area=(5000 / 4, 5000 * 4),\n",
" color=None,\n",
" convexity=0.9,\n",
" circularity=0.7,\n",
" inertia=None,\n",
" thresholdstep=1\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<matplotlib.figure.Figure at 0x7f8912b6ca58>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pyplot.imshow(im)\n",
"pyplot.plot(*zip(*[kp.pt for kp in keypoints]), 'or', markersize=12, fillstyle='none', markeredgewidth=2)\n",
"pyplot.axis('off')\n",
"pyplot.tight_layout()\n",
"None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Cluster by corner\n",
"\n",
"Group together points that are closeby, closer than 1.5 times the sum of the radi of both circles."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"keypoints, corner_circles = cluster_circles_per_corner(keypoints, distance_factor=1.5)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<matplotlib.figure.Figure at 0x7f8912c49710>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pyplot.imshow(im)\n",
"pyplot.axis('off')\n",
"\n",
"for corner in corner_circles:\n",
" pyplot.plot(*zip(*[keypoints[i].pt for i in corner]), 'o', markersize=12, fillstyle='none', markeredgewidth=2)\n",
"None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Fit lines\n",
"\n",
"Within each corner, find preferrably two lines.\n",
"\n",
"Lines are seperated by calculating cosine similarities. For each three points $P$, $Q$ and $R$ the cosine similarity between vectors $Q - P$ and $R - Q$ is calculated as a (#points, #points, #points) tensor.\n",
"\n",
"If the similarity is close to -1 or 1 (angle of 0° or 180° between both vectors), this means the three points lie on approximtely a line. They are then grouped together.\n",
"\n",
"**TODO**: use scikit-learn to find connected compontents in a connectivity matrix, instead of the default-dicts solution which I think might have a bug if due to numerical instability or assymetry of the cosine not all permutations of (i, j, k) are below the cosine threshold if one is and hence `j in groups[i]` does not imply `i in groups[j]`.\n",
"\n",
"**TODO**: the method finds a relation (i, j, k) of points lying on one line. What you want is to group those pairs (i, j, k) that have at least overlap of two elements, this way a point can belong to two seperate clusters, like a point exactly at the corner."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"lines_per_corner = find_line_coefficients_per_corner(keypoints, corner_circles, cosine_threshold=0.00137046524)\n"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f890c18d080>"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABlQAAAS7CAYAAADng1fGAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAIABJREFUeJzsvUmsJVl63/f7zjkRce997+XLqSqz5qpu9shiq1tskWpYtmTLC8HDwgtBgNfe2YAN7+yNh428sWDAAgTYC8PaeWN4Z5CiLUGyZTa7SXZTXT2yi11TVmZWTm+8NyLO4MV3TkTcl0U3SFlgCzx/IJGZ792IG3GGb/h/w5GUEhUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRV/PMyf9QNUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFT8oqMGVCoqKioqKioqKioqKioqKioqKioqKioqKn4OakCloqKioqKioqKioqKioqKioqKioqKioqLi56AGVCoqKioqKioqKioqKioqKioqKioqKioqKn4OakCloqKioqKioqKioqKioqKioqKioqKioqLi56AGVCoqKioqKioqKioqKioqKioqKioqKioqKn4OakCloqKioqKioqKioqKioqKioqKioqKioqLi56AGVCoqKioqKioqKioqKioqKioqKioqKioqKn4OakCloqKioqKioqKioqKioqKioqKioqKioqLi56AGVCoqKioqKioqKioqKioqKioqKioqKioqKn4OfqEDKiLyH4rIz0RkJyLfFJFf+7N+poqKioqKioqKioqKioqKioqKioqKioqKP3/4hQ2oiMjfAv4O8F8BfxH4LvAbIvLin+mDVVRUVFRUVFRUVFRUVFRUVFRUVFRUVFT8uYOklP6sn+FTISLfBL6VUvqP8v8N8AHw36eU/ps/04erqKioqKioqKioqKioqKioqKioqKioqPhzBfdn/QCfBhFpgV8F/nb5WUopishvAd/4Y67pgO7Kj28CT/5FPWdFRUVFRUVFRUVFRUVFRUVFRUVFRUVFxb9UOALupT9FtckvZEAFuA1Y4MGVnz8AvvjHXPOfAf/Fv8iHqqioqKioqKioqKioqKioqKioqKioqKj4lx6vAh/9SS/6RQ2o/Gnwt9EzVwqOgA//1n/3v9J26+mHPkZCCDjnMMZAjIgIKSUwhpj/LyIEH/UzkhARjFj9fUrEGLHWMo4j1s3XWeMIIYAxpJT0vjIHuiQlrLWklIgh4Zxj8B4Ac+X7Y4zY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
"text/plain": [
"<matplotlib.figure.Figure at 0x7f890c18d748>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"xx = numpy.arange(0, im.shape[1]-1,0.25)\n",
"for (a, b), (c, d) in lines_per_corner:\n",
" pyplot.plot(xx, a*xx + b, linewidth=4)\n",
" pyplot.plot(xx, c*xx + d, linewidth=4)\n",
"\n",
"pyplot.imshow(im)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Find corners by intersection\n",
"\n",
"Each corner should contain two lines, intersect them and find a 4-sized polygon."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f8912bf71d0>"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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
"text/plain": [
"<matplotlib.figure.Figure at 0x7f8912bf7518>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"corners, order = intersection_per_corner(lines_per_corner)\n",
"polygon_corners = numpy.array([corners[i] for i in order] + [corners[order[0]]])\n",
"\n",
"pyplot.plot(*polygon_corners.T, 'r-', linewidth=4)\n",
"pyplot.imshow(im)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}