11
$\begingroup$

I'll start by saying that I don't know anything about image processing. I have an image and I need to extract its outermost shape for use in a WordCloud. The image only has two colours and the outermost shape is a boundary between the two colours. A representative image follows (but the colours are not black and white in the actual image).

enter image description here

With this image I would expect the region calculated to be the union of the disk and rounded corner rectangle. Again, this only representative and the actual image is not made of an union of basic shapes.

I believe that if I call the image processing equivalent of DiscretizeGraphics and get many points then I could take the convex hull of this set of points and use this region in a WordCloud. DiscretizeGraphics doesn't work on JPEG and EdgeDetect does not return an object compatible with DiscretizeGraphics.

May someone point me in the correct direct to do this on an image? If this is not the best approach please offer alternatives.

$\endgroup$
2
  • $\begingroup$ The intersection? Are you sure? It will be very difficult to calculate the intersection of two shapes that aren't completely specified (in the general case, I mean) $\endgroup$ Nov 27, 2015 at 1:03
  • $\begingroup$ @belisariushassettled Sorry, the union. Late night in the office. I'll update. $\endgroup$
    – Edmund
    Nov 27, 2015 at 1:08

2 Answers 2

4
$\begingroup$

You only want the interior black areas filled? Then you just need a FillingTransform:

img = Import["https://i.stack.imgur.com/qUfE7.jpg"];
FillingTransform[img]

enter image description here

Or, if you want a binary result for a color image: FillingTransform[Binarize[img]] (which looks the same in this case, because the source image already is black and white)

$\endgroup$
13
$\begingroup$
i  = Binarize@Import["https://i.stack.imgur.com/qUfE7.jpg"];
m  = SelectComponents[i, "EmbeddedComponents", Length[#] === 0 &];
i1 = FillingTransform[i, Dilation[m, 1]];
m1 = SelectComponents[ColorNegate@i1, "EmbeddedComponents", Length[#] === 0 &];
i2 = FillingTransform[i1, Dilation[m1, 1]];
{{i, m, i1, m1, i2}} // Grid

Mathematica graphics


Edit

The following supports more general images:

f[x_Image] := FixedPoint[Module[{m, i1, m1},
    m = SelectComponents[#, "EmbeddedComponents", Length[#] === 0 &];
    i1 = FillingTransform[#, Dilation[m, 1]];
    m1 = SelectComponents[ColorNegate@i1, "EmbeddedComponents", Length[#] === 0 &];
    FillingTransform[i1, Dilation[m1, 1]]
    ] &, Binarize@x]

i = Import["https://i.stack.imgur.com/eu7yt.png"];
{{i, f@i}} // Grid

Mathematica graphics


Edit

Here is another non-recursive way:

i = Import["https://i.stack.imgur.com/eu7yt.png"];
i1 = ImageMultiply[i, ColorNegate@
       Image[Plus @@ (ComponentMeasurements[i, {"EnclosingComponents", "Mask"}, 
                                            # != {} &][[All, 2, 2]])]];
m = SelectComponents[i1, "EmbeddedComponents", Length[#] === 0 &];
i1 = FillingTransform[i1, Dilation[m, 1]];

{{i, f@i}} // Grid

Mathematica graphics

$\endgroup$
2
  • $\begingroup$ There are some very informative approaches presented. (+1) However, @nikie one-liner is easier to explain to others and manage. $\endgroup$
    – Edmund
    Nov 27, 2015 at 14:01
  • $\begingroup$ @Edmund Of course. I made up that because I found corner cases where FilliTransform wasn't enough. Trying to remember what were those :) $\endgroup$ Nov 27, 2015 at 14:17

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.