【问题标题】:R raster plotting an image, draw a circle and mask pixels outside circleR光栅绘制图像,绘制一个圆圈并在圆圈外屏蔽像素
【发布时间】:2015-10-20 23:55:57
【问题描述】:

下面的代码绘制一个图像,然后在该图像上绘制圆圈。我想让所有落在那个圆圈之外的像素都变黑。我怎么能这样做?

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")

【问题讨论】:

    标签: r image mask raster


    【解决方案1】:

    用 str() 查看 'x' 对象,你会看到:

    ..@ 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"
    

    ....所以 1:50 x 1:50 的值被映射到三列。 X 值可能是0:2500 %% 50,y 值可能是0:2500 %/% 50

    所以请记住“原点”是光栅对象的左上角,而绘图函数的左下角,因此 20 的 y 值变为 50-20 或 30,这可以让您接近您的要求(抱歉将 y 序列放在首位):

    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")
    

    逻辑是标准的形式为 (x-dx)^2+(y-dy)^2 > r^2 其中 dx 和 dy 是圆的中心坐标,r 是半径 == 10.

    问题更改后的编辑:

    对于每个颜色层,具有命名参数的代码将类似于使最暗的“红色”的代码。这给出了一个大致圆形的掩码,尽管没有正确处理使中心对齐:

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

    进一步的实验提供了这似乎非常接近:

    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") )
    

    显然,您可以用 width/height 缩放因子替换 5/4 出现的任何地方的新纵横比。

    【讨论】:

    • 我更新了作物的大小以及圆心的坐标。是否可以更改您的代码以反映新的作物大小和坐标?如果不使用实际数字(2500、50、30、100 等),而是使用图像宽度、高度、中心的 x 坐标等功能,这也会很有帮助......这样代码将在任何图像上运行。谢谢
    • 你是提出一个没有命名参数的问题的人。
    • 我试过你的代码......但我没有得到一个圆形区域:(蓝色圆圈和黑色区域相交很多:(
    • 可能需要加入缩放因子,因为“像素”的纵横比不再是 1.0
    • 不知何故,您设法获得了一个空逻辑矩阵作为@data@values。这是如何发生的,这是一个你需要解决的难题。您可能需要在另一个问题中发布str(r1) 的完整输出。我真的认为我已经完全回答了这个问题。
    【解决方案2】:

    这是一个更通用的解决方案,也适用于具有不同坐标系的栅格。

    函数rasterToPoints() 将栅格转换为点。按照您的示例,head(rasterToPoints(x)) 返回以下内容:

    > head(rasterToPoints(x))
           x    y 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
    

    然后我们需要找出哪些点落在圆外并将它们的值设置为零:

    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 points outside circle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-11
      • 2012-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多