# Find components which have intersections with designated lines

I have an image with several disconnected components, and I want to find all the components which have intersections with some designated lines which I generated previously. The image:

And the line is

{{{37.7754, 1001.}, {38.862, 0.}}, {{0., 442.679}, {832., 437.26}}}

The combined image looks like this:

-
DeleteSmallComponents (try 10, then 100, or more) would take care of it here, since the bigger components are connected anyway. –  BoLe Apr 4 '13 at 19:50
If you can polygonalize the image components then it should be straightforward to test for line-intersect-polygon (I think those are called "stabbing queries", but the kind that do not involve police investigations). –  Daniel Lichtblau Apr 4 '13 at 20:04
How do the coordinates of the line correspond to the pixels? –  rm -rf Apr 4 '13 at 21:13
@BoLe Yeah that works! I ended up using ImageMultiple to obtain the desired image with no lines. Thanks! –  Tinza123 Apr 4 '13 at 21:14
@DanielLichtblau In most cases the shape is irregular, so the polygonalization may be quite slow? –  Tinza123 Apr 4 '13 at 21:15

You can get the labels for the individual components using MophologicalComponents and simply multiply by the binarized line plot to get the labels of the components that intersect:

im = Import@"http://i.stack.imgur.com/Pq6JZ.png";
pts = {{{37.7754, 1001.}, {38.862, 0.}}, {{0., 442.679}, {832., 437.26}}};
line = Binarize@Graphics[{White, Line /@ pts}, Background -> Black, ImageSize -> (ImageDimensions@im)];

labels = MorphologicalComponents[im];
intersect = Rest@Union@Flatten[labels ImageData@line]
(* {4, 5} *)


You can plot only the intersecting components and overlay the lines with:

blobs = Colorize[labels, ColorRules -> (Map[# -> ColorData[31]@# &, intersect] ~Join~ {_ -> Black})];


-

This borrows heavily from @rm -rf at least for the start. Also it is not as clean. It might still be of interest in terms of determining and selecting specific image components.

im = Import["http://i.stack.imgur.com/Pq6JZ.png"];
pts = {{{37.7754, 1001.}, {38.862, 0.}}, {{0., 442.679}, {832.,
437.26}}}; line =
Binarize@Graphics[{White, Line /@ pts}, Background -> Black,
ImageSize -> (ImageDimensions@im)];


Now remove filled in areas of the components.

im2 = EdgeDetect[im];


Next create an averaged image of this and the lines (I'm sure there is a Cleaner way to do this part).

im2 = EdgeDetect[im];
data = ImageData[im2];
ldata = ImageData[line];
datasum = (data + ldata)/2;
totalImage = Image[datasum];


The point is that we now have large values exactly at the crossings of those lines with image components. We can extract those as below.

mb = MorphologicalBinarize[totalImage, {.9, .99}];


We now get the components of both the original image and this very sparse one comprised only of the intersection points.

m1 = MorphologicalComponents[im];
m2 = MorphologicalComponents[mb];


We can use the second one to tell us which components from im are of interest (that is, intersect the lines).

intersectedComps =
Union[Select[Flatten[m1*Unitize[m2]], # >= .99 &]]

(* Out[129]= {4, 5} *)


Now we show the image with only these components 9again, there must be a better way...)

Image[Map[KroneckerDelta[4 - #] + KroneckerDelta[5 - #] &, m1, {2}]]


-
You can replace the averaging step and the MorphologicalBinarize step with just ImageMultiply[im2, line] –  rm -rf Apr 5 '13 at 13:50

Also,

The standard setup:

im = Import["http://i.stack.imgur.com/Pq6JZ.png"];
pts = {{{37.7754, 1001.}, {38.862, 0.}}, {{0., 442.679}, {832., 37.26}}};
line = Binarize@Graphics[{White, Line /@ pts}, Background -> Black,
ImageSize -> (ImageDimensions@im)];


and then just:

Rest@Union@Flatten@Pick[MorphologicalComponents@im, ImageData@line, 1]

(*{4, 5}*)

-
Again, short and sweet. That gets my vote. –  Daniel Lichtblau Apr 5 '13 at 14:06

Thanks guys. This is my solution inspired by @BoLe:

m = Import["http://i.stack.imgur.com/Pq6JZ.png"];
lines = {{{37.7754, 1001.}, {38.862, 0.}}, {{0., 442.679}, {832.,437.26}}};
deleted = DeleteSmallComponents[Show[m, Graphics[{White, Thick, Line /@ lines}]]];
m = ImageMultiply[m, deleted]

-
This is not a good or robust solution because you lose control with DeleteSmallComponents. To see what I mean, look at what result you get with this if your line was instead lines = {{{37.7754, 1001.}, {38.862, 0.}}, {{0., 490.679}, {832., 490.26}}}; –  rm -rf Apr 5 '13 at 13:59