Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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. I will now demonstrate:

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

pic = Import[

enter image description here

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}]

enter image description here

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

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

enter image description here

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

enter image description here

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

How can I get improved results from the ImageLines function?

share|improve this question
up vote 14 down vote accepted

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


Mathematica graphics


Mathematica graphics

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

share|improve this answer

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

pic = ColorNegate@Import[""];
p = Closing[Binarize@ImageTake[pic, 480], 1]; (*See nikie's comment*)
Show[p, Graphics[{Thick, Orange, Line /@ ImageLines[p]}]]

Mathematica graphics

share|improve this answer
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]}

enter image description here

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

enter image description here

share|improve this answer
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"}];
   Map[Line, ImageLines[lena, .55, "Segmented" -> True]]}, 
  Background -> Black]  /. 
 Line[pts_] :> {RandomChoice[{Red, Green, Blue, Orange, White}], 


share|improve this answer
+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

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.