Optional Reading
Recommended Jupyter Theme for presenting this notebook:
jt -t grade3 -cellw=90% -fs=20 -tfs=20 -ofs=20
Explanation
$$ \frac{n \cdot (n-1)}{2} = \frac{n^2}{2} - \frac{n}{2} \approx \frac{n^2}{2} $$
In practice, two big issues will likely pop up when we go to code our algorithm:
1. Slow AF. As we figured out earlier, our "try all the lines" algorithm scales as $\frac{n^2}{2}$. The images above are 256x256, and have, on average 250-500 edge pixels. This makes for between 30k and 125k lines we need to test. Further, these images are quite small by modern standards, and very low noise (<1% of pixels are edges). If we had a noisy Full HD image for example, where 10% of our pixels were detected as edges, this would make for $((1920 \cdot 1080 \cdot 0.1)^2)/2 \approx 21B $ lines to test! This would be slow on a modern computer, and incomputable in the 1950s when Hough worked on this problem.
2. Susceptible to Noise. The edge points that show up in our images above are not exactly co-linear. This means that testing each of our lines is a bit more complex. We could measure the distance of points to our line, as use some kind of thresholding label points as "approximately co-linear". This may work well, but the point here is that noise complicated our "try all the lines" approach.
#Little trick to progress through slides within the notebook
from IPython.display import Image, display
from ipywidgets import interact
#Quick method to let me step through "slides"
def slide_show(slide_num=1):
display(Image('../graphics/hough_idea_kernel/' + str(slide_num).zfill(2) + '.png'))
interact(slide_show, slide_num = (1, 5));
Explanation
$$ v_1 = y_i u_1 + x_i \\ y_i u_1 = v_1-x_i \\ y_i = -\frac{1}{u_1} x_i + \frac{v_1}{u_1} $$
This equation is equivalent to (1), given that $m = - \frac{1}{u_i}$ and $b=\frac{v_1}{u_1}$. QED.
Finally, we can use this result to solve our second problem, finding our intersection point. We just need to solve for $u_1$ and $v_1$: $u_i = -\frac{1}{m}$, and $v_1 = b \cdot u_1 = -\frac{b}{m}$.
#(Optional) Download data + videos if you don't have them.
import os, sys
sys.path.append('..')
from util.get_and_unpack import get_and_unpack
if not os.path.isdir('../data/'):
url = 'http://www.welchlabs.io/unccv/the_original_problem/data/data.zip'
get_and_unpack(url, location='..')
if not os.path.isdir('../videos/'):
url = 'http://www.welchlabs.io/unccv/the_original_problem/videos.zip'
get_and_unpack(url, location='..')