R bitmap, draw a circle and draw pixels outside the circle

The code below displays an image, and then displays a circle on that image. I want to make all the pixels that go beyond the black circle. How can i do this?

library(raster) library(plotrix) r1 <- brick(system.file("external/rlogo.grd", package="raster")) width=50 height=40 x <- crop(r1, extent(0,width,0,height)) plotRGB(x) circlex=20 circley=15 radius=10 draw.circle(circlex,circley,radius,border="blue") 
+4
source share
2 answers

Look at the "x" object with str (), and you will see the following:

 ..@ data :Formal class '.MultipleRasterData' [package "raster"] with 14 slots .. .. ..@ values : num [1:2500, 1:3] 255 248 221 199 198 210 221 190 104 79 ... .. .. .. ..- attr(*, "dimnames")=List of 2 .. .. .. .. ..$ : NULL .. .. .. .. ..$ : chr [1:3] "red" "green" "blue" 

.... so the 1:50 by 1:50 values ​​are mapped to three columns. X values ​​are probably 0:2500 %% 50 , and y values ​​are probably 0:2500 %/% 50

Thus, remembering that the β€œbeginning” is if the upper left corner is for raster objects, but the lower left corner is for plot functions, and therefore the value of y 20 becomes equal to 50-20 or 30, this allows you to get closer to what you are asking ( apologies for putting the y-sequence first):

 x@data @values[( ((1:2500 %/% 50 )- 30)^2 + ((1:2500 %% 50) - 20)^2 ) >=100, 1] <- 0 x@data @values[( ((1:2500 %/% 50 )- 30)^2 + ((1:2500 %% 50) - 20)^2 ) >=100, 2] <- 0 x@data @values[( ((1:2500 %/% 50 )- 30)^2 + ((1:2500 %% 50) - 20)^2 ) >=100, 3] <- 0 plotRGB(x) draw.circle(20,20,10,border="blue") 

enter image description here

The logic is that the criteria are of the form (x-dx) ^ 2 + (y-dy) ^ 2> r ^ 2, where dx and dy are the center coordinates of the circle and r is the radius == 10.

EDITORS after changing the question:

For each color layer, the code with named parameters will be similar to the one that makes the darkest "red". This gives a roughly circular mask, although getting the centers for alignment is not handled correctly:

 x@data @values[( ((1:(height*width) %/% (height*5/4) )- (height-circley*5/4) )^2 + ((1:(height*width) %% width) - circlex )^2 ) >= radius^2, 1] <- 0 

Further experimentation delivers this, which seems pretty close:

 x@data @values[( ((1:(height*width) %/% (height) )- (height-circley) *5/4)^2 + ((1:(height*width) %% width) - circlex )^2 ) >= radius^2, 1] <- 0 plotRGB(x, asp=5/4, addfun=function() draw.circle(circlex,circley,radius,border="blue") ) 

Obviously, you could replace the width/height scale factor for the new image format wherever 5/4 appears.

enter image description here

+4
source

Here it is a more general solution, which also works for rasters with different coordinate systems.

The rasterToPoints() function converts a raster to points. Following your example, head(rasterToPoints(x)) returns the following:

 > head(rasterToPoints(x)) xy red green blue [1,] 0.5 39.5 255 255 251 [2,] 1.5 39.5 204 205 199 [3,] 2.5 39.5 171 172 164 [4,] 3.5 39.5 157 159 148 [5,] 4.5 39.5 162 164 151 [6,] 5.5 39.5 187 189 176 

Then we need to find which points fall outside the circle and set their values ​​to zero:

 is_outside_circ = (rasterToPoints(x)[,1] - circlex)^2 + (rasterToPoints(x)[,2] - circley)^2 >= radius^2 x@data @values[ is_outside_circ,] <- 0 plotRGB(x) draw.circle(circlex,circley,radius,border="blue") 

Result: black dots outside the circle

0
source

All Articles