2
$\begingroup$

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@"https://i.stack.imgur.com/wpszz.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.

$\endgroup$
5
  • $\begingroup$ What exactly would be your desired output? $\endgroup$
    – Öskå
    Aug 4, 2014 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, 2014 at 16:37
  • $\begingroup$ By "select" you mean highlight on the image? $\endgroup$
    – Öskå
    Aug 4, 2014 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, 2014 at 16:41
  • $\begingroup$ That would work perfectly! $\endgroup$
    – Coco
    Aug 4, 2014 at 18:34

2 Answers 2

2
$\begingroup$

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;
Manipulate[
 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.

$\endgroup$
2
$\begingroup$

With SelectComponents you can do it like this:

selectBorder[border_] := SelectComponents[
  m,
  "AdjacentBorders",
  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.

$\endgroup$
3
  • $\begingroup$ Oy oy. Now I feel dumb :) $\endgroup$
    – Öskå
    Aug 4, 2014 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, 2014 at 19:12
  • $\begingroup$ The simpler it is, the smarter ;) :) $\endgroup$
    – Öskå
    Aug 4, 2014 at 19:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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