# How to show multiple images with a for loop

I wrote a simple application(I put the code in the end) to detect the parallel line pairs in the following picture:

It returned three pairs of parallel line:

{{{{584., 222.175}, {39.6747, 0.}}, {{0., 377.639}, {390.613, 472.}}},
{{{0., 403.894}, {306.413, 0.}}, {{0., 336.953}, {238.095, 0.}}},
{{{584., 186.489}, {127.104, 0.}}, {{0., 377.639}, {390.613, 472.}}}}


And then I want to show every result individually. Here's the way I output the result, where img is the test picture and parLines is the detected parallel line pairs.

For[i = 1, i <= Length[parLines], i++,
Show[img, Graphics[{Thick, Orange, Line /@ parLines[[i]]}]]]


I expected it to output several images and a pair of parallel lines on each. The number of images depend on the number of pairs of parallel line. However, it didn't draw anything. But if I printed them one by one, it worked fine.

Show[img, Graphics[{Thick, Orange, Line /@ parLines[[1]]}]]


Show[img, Graphics[{Thick, Orange, Line /@ parLines[[2]]}]]


Show[img, Graphics[{Thick, Orange, Line /@ parLines[[3]]}]]


I can't understand where the problem is. Thanks for any help.

Here's the code:

img = Import["http://www.zechini.it/webtv/upload/book.jpg"];
edge = DeleteBorderComponents[EdgeDetect[img]];
lines = ImageLines[edge, 0.1];

NumofLines = Length[lines];
flag = False;
parLines = {};
For[i = 1, i <= NumofLines, i++,
For[j = i + 1, j <= NumofLines, j++,
line1 = lines[[i]];
line2 = lines[[j]];
vec1 = line1[[1]] - line1[[2]];
vec2 = line2[[1]] - line2[[2]];
para = 1 - ArcCos[Abs[(vec1.vec2)/Norm[vec1]/Norm[vec2]]]/(Pi/2);
If[para > 0.9, flag = True; AppendTo[parLines, {line1, line2}];];
];
];

If[flag == True,
For[i = 1, i <= Length[parLines], i++,
Show[img, Graphics[{Thick, Orange, Line /@ parLines[[i]]}]]],
Print["Cannot detect parallel line"]]

-

Or perhaps:

Show[img, Graphics[{Thick, Orange, Line[#]}]] & /@ parLines
// GraphicsRow


-

This is probably what you want (whenever you're using For loops to generate a static result like a combined Graphics, you have to be suspicious that you're doing it wrong):

Show[img,
Table[Graphics[{Thick, Orange, Line /@ parLines[[i]]}], {i, 1, 3}]]


In words: replace the For loop by a Table inside the Show if you want all lines to be shown in the same Graphics.

In case I misunderstood: if you want to really use a For loop despite all this, you can force output of the Show result at every step by replacing Show by Print@Show. This is needed because Graphics is only shown when it's the last statement in a compound expression (and not followed by a ; which stands for CompoundExpression). But in the For loop, the Show is not the last command that gets executed.

-
Actually I would like to use for loop to output every result individually, no in the same picture. Therefore I think Print@Show will suit my purpose – AlbertK Aug 16 '13 at 10:20

Though this isn't an extension to the other answers you've received it might give you some insight into the Mathematica/Functional style of problem solving.

img = Import["http://www.zechini.it/webtv/upload/book.jpg"];
lines = ImageLines[DeleteBorderComponents[EdgeDetect[img]], 0.1];


By removing many of the redundant intermediate variables and concentrating on manipulating the data as a sequence of transformations the main body of code can be reduced to one line, plus one function definition.

Define a function that returns true or false if a pair of vectors are parallel:

parallel[{vec1_, vec2_}] := (1-ArcCos[Abs[(vec1.vec2)/Norm[vec1]/Norm[vec2]]]/(Pi/2)) > 0.9


Then by creating a set of all the pairs of parallel lines we can then apply that to the result of building vectors from the pairs of lines:

parLines = With[{l=Subsets[lines, {2}]}, Pick[l, parallel/@Apply[Subtract, l, {2}] & /@ l)]];


Then display the results as per cormullion's answer:

Show[img, Graphics[{Thick, Orange, Line[#]}]] & /@ parLines // GraphicsRow

-
(+1) Is VectorAngle any use here? – cormullion Aug 16 '13 at 14:36
I think you could use Apply[Subtract, l, {2}] in place of ((Subtract @@ # & /@ #) & /@ l). Perhaps it is even clearer to use Select instead of Pick: Select[l, parallel[Subtract @@@ #] &] – Simon Woods Aug 16 '13 at 15:39
Impressive! That is very conise. I'm a beginner to Mathematica, and since I'm more familiar with C++ programming, my code looks C++-style. However, as a beginner, it is difficult for me to understand the parLines line you write. I can't imagine the output of every operation performed. I have to take that line apart and output every segments to understand how it works. Sometimes I even don't know how to decompose it! I would like to know what the core spirit it is to write the code so concise, and how? Well, I admit that my code up there is ugly :) – AlbertK Aug 18 '13 at 15:46
Well...I don't know if worth a new thread, if so I'll post it as a new question later. – AlbertK Aug 18 '13 at 15:52

Another approach is to use Manipulate to choose which lines to display:

Manipulate[Show[img, Graphics[{Thick, Orange, Line /@ parLines[[i]]}]], {i, 1, 3, 1}]


By moving the slider you can see each of the pairs of parallel lines in succession.

-
Or ListAnimate or FlipView ... – Jens Aug 16 '13 at 21:31