4
$\begingroup$

I have an image where I would like to do 2 things:

a) Put a disk of radius r on an specific $\{x,y\}$ position on the image such as the result is the original image within the disk and black color outside.

My attempt was this, but the resulting image within the disk looks different

 i = Import["http://exampledata.wolfram.com/coneflower.jpg"]
 DiskRec[x_, y_, rr_] := Graphics@Disk[{x, y}, rr];
 HighlightImage[i, DiskRec[45, 40, 30], Method -> "Brightness"];
 ImageSubtract[i,HighlightImage[i, DiskRec[45, 40, 30], Method -> "Brightness"]]

b)Then, I would like to draw a black circle within the previous one, with a smaller.

Thanks in advance, Juan.

$\endgroup$
2
  • $\begingroup$ I'm not sure I fully understand what you're asking, but does this do what you're after? HighlightImage[i, {DiskRec[45, 40, 30], {Black, EdgeForm[Thick], Opacity[1], DiskRec[45, 40, 30]}}, {"Darken", .5}] $\endgroup$
    – Greg Hurst
    Apr 25, 2018 at 21:36
  • $\begingroup$ In the first part, it seems you want to create a circular mask, doesn’t it? However, reading the second one, it seems rather you want an annular mask. Look around here to find similar questions... $\endgroup$ Apr 25, 2018 at 21:47

3 Answers 3

6
$\begingroup$

Get the image:

i = Import["http://exampledata.wolfram.com/coneflower.jpg"];

Define regions for: the whole image, the window disk, the black dot disk:

imRegion = Rectangle[{0, 0}, ImageDimensions[i]]
disk1 = Disk[{80, 60}, 40];
disk2 = Disk[{80, 60}, 10];

Window by changing everything in imRegion but not in disk1 Black:

windowed = ImageApply[{0, 0, 0} &, i, Masking -> RegionDifference[imRegion, disk1]]

Windowed Image

Dot by changing everything in disk2 to Black:

dotted = ImageApply[{0, 0, 0} &, windowed, Masking -> disk2]

Dotted image

Done knowing what result you want before starting, we can just skip to defining your region of interest as an Annulus:

roi = Annulus[{80, 60}, {10, 40}];
viewRoI = ImageApply[{0, 0, 0} &, i, Masking -> RegionDifference[imRegion, roi]]

This returns the same as the dotted version of windowed, so I won't add another image.

EDIT:

There was a request to move away from using Region, because so much of Region support is new (and not implemented in old versions).

We can use ImageApplyIndexed to achieve this effect as long as we keep the "Regions" of interest simple enough that it is easy to test if a coordinate pair lies in the region.

Our Version 10 - robust method looks like this:

Define an image:

i = RandomImage[1, {150, 113}, ColorSpace -> "RGB"];

Define some parameters to characterize the disks:

{d1Center, d1Radius} = {{50, 80}, 40};
{d2Center, d2Radius} = {{50, 80}, 10};

- Note that because of how ImageApplyIndexed feeds pixel coordinates, the center here is specified as {"row from top", "column from left"}.

Now we turn all pixels not in disk 1 Black:

windowed = ImageApplyIndexed[If[EuclideanDistance[#2, d1Center] > d1Radius, {0, 0, 0}, #1] &, i]

And then turn just the pixels in disk2 Black:

dotted = ImageApplyIndexed[If[EuclideanDistance[#2, d2Center] > d2Radius, #1, {0, 0, 0}] &, windowed]
$\endgroup$
3
  • $\begingroup$ Well, I am working on a 10 version, and it does not recognize ´RegionDifference´ as an option for Masking. $\endgroup$ Apr 26, 2018 at 12:41
  • $\begingroup$ I have edited to accommodate back to version 10. The second answer is a bit narrower in applicability because you've got to have a way to test if a pixel lies in your RoI, but that is easy for disks. $\endgroup$
    – kjosborne
    Apr 26, 2018 at 15:46
  • $\begingroup$ Thanks, it looks exactly what I was looking for, now for an old version. $\endgroup$ Apr 26, 2018 at 16:04
3
$\begingroup$

We can define a general mask based on Annulus[]. Then Rasterize the Graphics, resize it, padd it, and locate in any position in the image to be masked:

mask[img_, pos_, rin_, size_] := ImagePad[ImageResize[
ColorNegate@
Rasterize@
 Graphics[Annulus[{0, 0}, {rin, 1}], 
  PlotRangePadding -> 0], {size}], {{pos[[2]] - size/2, 
img[[1]] - (pos[[2]] + size/2)}, {img[[2]] - (pos[[1]] + size/2), 
pos[[1]] - size/2}}]

As an example the mask resulting is:

m = mask[ImageDimensions[i], {50, 50}, 0.2, 50]

enter image description here

and applied to the image provided:

ImageMultiply[i, m]

enter image description here

Another example:

i = Import[
"C:\\Users\\Public\\Pictures\\Sample Pictures\\Penguins.jpg"]

enter image description here

m = mask[ImageDimensions[i], {500, 500}, 0.5, 500];
ImageMultiply[i, m]

enter image description here

Further improvement would consist in taking into account that the annulus will always be inside the image dimensions.

EDIT

When Annulus is not available, this also works:

mask[img_, pos_, rin_, size_] := ImagePad[ImageResize[
ColorNegate@Rasterize@
 Graphics[{Disk[], White, Disk[{0, 0}, rin]}, 
  PlotRangePadding -> 0], {size}], {{pos[[2]] - size/2, 
img[[1]] - (pos[[2]] + size/2)}, {img[[2]] - (pos[[1]] + size/2), 
pos[[1]] - size/2}}]
$\endgroup$
3
  • $\begingroup$ Version 10 does not have the Annulus command. Is it possible to do the same without Annulus? I tried this, but is not possible to be employed in place of Annulus DiscretizeRegion[ RegionDifference[Disk[{0, 0}, 200], Disk[{0, 40}, 100]]] $\endgroup$ Apr 26, 2018 at 12:47
  • $\begingroup$ @JuanManuelGomba see my edit. No need to use RegionPlot... $\endgroup$ Apr 26, 2018 at 16:26
  • $\begingroup$ Thanks José, the use of Disk seems to work well when the radius of the inner disk is smaller than the outer one. I observe some distortion of the mask. $\endgroup$ Apr 26, 2018 at 16:32
-1
$\begingroup$

thanks to your input I was able to find an answer for my old version.

 i = Import["http://exampledata.wolfram.com/coneflower.jpg"];

 dim = ImageDimensions[i];

 R[x_, y_, rin_] := RegionPlot[RegionDifference[Disk[{0, 0}, Max[dim]],Disk[{x, y}, rin]], Frame -> False, PlotStyle -> {Black, Opacity[1]}]

 mask[img_, pos_, size_, x_, y_, rin_] :=ImagePad[ImageResize[ColorNegate@Rasterize@Graphics[R[x, y, rin],  PlotRangePadding -> 0], {size}], {{pos[[2]] - size/2,img[[1]] - (pos[[2]] + size/2)}, {img[[2]] - (pos[[1]] + size/2),pos[[1]] - size/2}}]

 Manipulate[{R[xx, yy, rre],m = mask[dim, {dim[[2]] - a, b}, rre, xx, yy, rr],multi = ImageMultiply[i, m]},{a, 1, dim[[2]], 1}, {b, 1, dim[[1]], 1}, {rre, 1, dim[[1]], 1}, {xx,1,dim[[2]], 1}, {yy, 1, dim[[1]], 1}, {rr, 1, dim[[1]], 1}]

enter image description here

$\endgroup$

Your Answer

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

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