I've been doing some image processing and have been having trouble with the AdjacentBorder command. I've got an image in which I have several elements that are on the borders, and I was able to use ComponentMeasurements[image,"AdjacentBorders"] to obtain the list of what borders these elements touch. However, when I go to use SelectComponents, I'm unable to select the elements that are just on one border.

Is this possible, or can I only select the components that are bordering a certain amount of borders?

This is the image I started with this image

and the code I've used since.

j := Import@"http://i.imgur.com/AC0bvkG.png"
k := Binarize[j, FindThreshold[j]]
l := SelectComponents[k, "FilledCircularity", -7]
m := ImageCrop[l]
ComponentMeasurements[m, "AdjacentBorders"]
{1 -> {Top}, 2 -> {Right}, 3 -> {Left}, 4 -> {Left}, 5 -> {Right},
 6 -> {Bottom, Right}, 7 -> {Left, Bottom}}

I used ComponentMeasurements to ensure that I did have points on the borders, which I did.

  • $\begingroup$ What exactly would be your desired output? $\endgroup$ – Öskå Aug 4 '14 at 16:31
  • $\begingroup$ @Öskå I would like to set up my code so that I could select only the components on one side of the image. I would think that I could use the SelectComponents command for this, but wasn't able to figure out if I was getting the syntax wrong or if those two commands would not work together. $\endgroup$ – Coco Aug 4 '14 at 16:37
  • $\begingroup$ By "select" you mean highlight on the image? $\endgroup$ – Öskå Aug 4 '14 at 16:39
  • $\begingroup$ Ideally, I'd love to have something similar to the SelectComponents output, where the output would be the same image with just the selected components. However, if they were highlighted on the image, that would also work. $\endgroup$ – Coco Aug 4 '14 at 16:41
  • $\begingroup$ That would work perfectly! $\endgroup$ – Coco Aug 4 '14 at 18:34

You can use for example ImageSubtract as follow:

j = Import@"http://i.imgur.com/AC0bvkG.png";
k = Binarize[j, FindThreshold[j]];
l = SelectComponents[k, "FilledCircularity", -7];
m = ImageCrop[l];
comp = ComponentMeasurements[m, {"AdjacentBorders", "BoundingBox"}] /. 
       {{_, Right} | {Right, _} -> {Right}, {_, Left} | {Left, _} -> {Left}};
imgdim = ImageDimensions@m;
 ImageSubtract[Show[m, ImageSize -> 300], 
  Graphics[{Red, Rectangle[Sequence @@ #] & /@ Cases[comp, Rule[x_, {{i}, y_}] :> y]}, 
   PlotRange -> {{0, First@imgdim + 1}, {-1, Last@imgdim}}, 
   ImageSize -> 300]], {i, {Top, Left, Right}}]

enter image description here

Or ImageMultiply to highlight the different parts:

Mathematica graphics

But there are unfortunately some unselected pixels.


With SelectComponents you can do it like this:

selectBorder[border_] := SelectComponents[
  MemberQ[#, border] &

So that selectBorder /@ {Left, Right, Top, Bottom} gives

selectBorder example

But there's a problem, as you can see. AdjacentBorder doesn't count elements that don't touch their borders. So a harder question is not how you can use AdjacentBorder with SelectComponents but how you can find out what the adjacent border of a component is even if it's not touching it. For this particular example I would recommend cropping the image just a bit more so that all elements touch their respective borders.

  • $\begingroup$ Oy oy. Now I feel dumb :) $\endgroup$ – Öskå Aug 4 '14 at 19:05
  • $\begingroup$ @Öskå It takes more brains to write the code in your answer, but yeah, this is simpler :) $\endgroup$ – C. E. Aug 4 '14 at 19:12
  • $\begingroup$ The simpler it is, the smarter ;) :) $\endgroup$ – Öskå Aug 4 '14 at 19:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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