# Poor results with ImageLines function

I'm trying to get my mind wrapped around Mathematica's image feature recognition functions. I'm intrigued by the ImageLines function for a couple future ideas I have but generally get very poor performance from it.

...as I will now demonstrate:

Let's import some very basic gridlines, surely this will be easy.

pic = Import[
"http://www.samplewords.com/docthumbs/home-graphpaper-thumb.jpg"]


Straight out of the box, here's how Mathematica recognizes the lines at different thresholds (parallelized because of my impatience):

Row@ParallelTable[Graphics@Line@ImageLines[pic, i], {i, .1, 1, .1}]


Interesting... not what I would've expected.

Even if I dilate and binarize the image, I still get pretty bad results:

Playing with the distictness parameter, it gets a little better but still pretty weird.

So, Wolfram shows some pretty neat examples, and it seems to work well there.

How can I get improved results from the ImageLines function?

-

Mathematica's ImageLines function is looking for white lines on black background, try this:

ColorNegate@pic


Graphics@Line@ImageLines@ColorNegate@pic


Much more successful, not sure why it missed one, though.

-

Here you may see that with a little preconditioning, the match is perfect:

pic = ColorNegate@Import["http://www.samplewords.com/docthumbs/home-graphpaper-thumb.jpg"];
p = Closing[Binarize@ImageTake[pic, 480], 1]; (*See nikie's comment*)
Show[p, Graphics[{Thick, Orange, Line /@ ImageLines[p]}]]


-
You come in with a doozy as soon as I accept another answer... – kale Sep 12 '12 at 3:08
@kale It's OK. If you really need it (for other occasion, poor @s0urce!), the accepting is reversible :) – Dr. belisarius Sep 12 '12 at 3:10
@belsarius, Ha. I know, but what cold, heartless, ingrate would rip away the satisfaction of an accepted answer? :) – kale Sep 12 '12 at 3:12
@kale Now seriously: You should allow more time between issuing a question and accepting one answer. That way you will get more and better answers. Also remember that many users live in the antipodes, so they will not see your question until tomorrow. Let's say that two days is a good measure until accepting. – Dr. belisarius Sep 12 '12 at 3:32
Just nitpicking: Erosion[Dilation[...] is the same as Closing[...]. I'm not sure if there's a performance difference, but it's more readable. – nikie Sep 12 '12 at 8:42

In image processing, 1 is white and 0 is black (in binary). This is opposite of what is normal in functions like ArrayPlot. For example:

Row@{Image[IdentityMatrix@10, ImageSize -> 200],
ArrayPlot[IdentityMatrix@10, ImageSize -> 200]}


Thus, your lines need to be white on black for the algorithm to recognize it as a line. Otherwise, it tries to detect lines among the voids...

ParallelTable[Graphics@Line@ImageLines[Binarize@ColorNegate@pic, i],
{i, .1, 1, .1}]~Partition~4 // Grid


-
I beat you by 20 seconds! I'm excited. – s0rce Sep 12 '12 at 2:06
@s0rce I'm slipping! ;) I did add more info though :) – R. M. Sep 12 '12 at 2:15
@s0rce and R.M, is this documented anywhere? Common knowledge among image-o-philes? – kale Sep 12 '12 at 2:18
@kale Well, 1 is always on (pixel on) and 0 is always off (pixel off)... so the algorithms really only look for that. What is different is our perception of what white and black mean. The color scheme in ArrayPlot and also the ubiquitous use of black ink on white paper might have warped our way of looking at a black and white image, but really, all you need to consider are the 0s and 1s. – R. M. Sep 12 '12 at 2:22
@R.M, Thanks for the info. I actually did this the other day, but thought I was crazy for inverting the image. I'll +1 you and accept s0rce's answer simply because 20 seconds is 20 seconds and you have enough reputation to last until eternity. :) – kale Sep 12 '12 at 2:58

It's a minor point, but when I was exploring the potential of ImageLines, I found the Segmented->True option quite useful. I was fascinated at the lines that ImageLines was finding...

lena = ExampleData[{"TestImage", "Lena"}];
Graphics[{AbsoluteThickness[0.4],
Map[Line, ImageLines[lena, .55, "Segmented" -> True]]},
Background -> Black]  /.
Line[pts_] :> {RandomChoice[{Red, Green, Blue, Orange, White}],
Line[pts]}


-
+1 for beautiful art works! – Silvia Sep 12 '12 at 15:09
I wonder what could result with the full Lena ...+1 – Dr. belisarius Sep 12 '12 at 18:13
@belisarius Szabolcs is probably the one for that... :) – cormullion Sep 13 '12 at 6:09
@cormullion That was his swan song – Dr. belisarius Sep 13 '12 at 6:15