为点 R 生成圆形边界

时间:2021-02-25 19:32:56

标签: r indexing distance

我正在努力在图像中围绕 4 个不同的感兴趣区域设置边界 - 图像和数据位于 0-1 归一化空间中,具有四个相同大小的象限。设置正方形边界很容易:

df.all$ROI <- ifelse(df.all$x_pred_normalised > 0 & df.all$x_pred_normalised <= .5 &
                     df.all$y_pred_normalised > 0 & df.all$y_pred_normalised <= .5, c("lower_left"), 
              ifelse(df.all$x_pred_normalised > 0 & df.all$x_pred_normalised <= .5 &
                     df.all$y_pred_normalised > .5 & df.all$y_pred_normalised <= 1, c("upper_left"),
              ifelse(df.all$x_pred_normalised > .5 & df.all$x_pred_normalised <= 1 &
                     df.all$y_pred_normalised > 0 & df.all$y_pred_normalised <= .5, c("lower_right"), 
              ifelse(df.all$x_pred_normalised > .5 & df.all$x_pred_normalised <= 1 &
                     df.all$y_pred_normalised > .5 & df.all$y_pred_normalised <= 1, c("upper_right"),
                     c("other")))))

但是,我想在每个象限 (.25, .25; .25, .75; .75, .25; .75, .75) 提供相同的输出。

样本数据:

x_pred_normalized <- rnorm(1000, mean=.5, sd=.5)
y_pred_normalized <- rnorm(1000, mean=.5, sd=.5)
df.all <- as.data.frame(cbind(x_pred_normalized, y_pred_normalized))

df.all$ROI_square <- ifelse(df.all$x_pred_normalised > 0 & df.all$x_pred_normalised <= .5 &
                     df.all$y_pred_normalised > 0 & df.all$y_pred_normalised <= .5, c("lower_left"), 
              ifelse(df.all$x_pred_normalised > 0 & df.all$x_pred_normalised <= .5 &
                     df.all$y_pred_normalised > .5 & df.all$y_pred_normalised <= 1, c("upper_left"),
              ifelse(df.all$x_pred_normalised > .5 & df.all$x_pred_normalised <= 1 &
                     df.all$y_pred_normalised > 0 & df.all$y_pred_normalised <= .5, c("lower_right"), 
              ifelse(df.all$x_pred_normalised > .5 & df.all$x_pred_normalised <= 1 &
                     df.all$y_pred_normalised > .5 & df.all$y_pred_normalised <= 1, c("upper_right"),
                     c("other")))))

期望输出:

x_pred_normalized y_pred_normalized ROI_square  ROI_circle
.99               .99               upper_right other
.51               .51               upper_right other
.25               .25               lower_left  lower_left

1 个答案:

答案 0 :(得分:0)

您的示例不会产生您描述的数据。并且您永远不应该在对 cbind 的调用中使用 data.frame ,除非有一个数据帧对象作为参数之一。这是一个符合您描述的数据框结构(并且足够小,不会在测试时用无用的输出填满您的控制台):

df.all <- data.frame(
             x_pred_normalized = pmax( 0, pmin( rnorm(10, mean=.5, sd=.5), 0.99999)), 
             y_pred_normalized = pmax( 0, pmin( rnorm(10, mean=.5, sd=.5), 0.99999)) )
# all values between 0 and .99999

我发现嵌套很深的 ifelse 结构对调试非常混乱并且浪费空间,而使用两列矩阵从字符矩阵中选择项目很容易理解。索引数字矩阵中的列是使用 findInterval 构造的,因此它将被向量化并且在时间和空间上都更加高效。

 df.all$quad <- matrix(c("First", "Third","Second","Fourth"), ncol=2)[ cbind(
                    findInterval(df.all$x_pred_normalized,c(  0, .5, 1,Inf) ),
                    findInterval(df.all$y_pred_normalized,c(  0, .5,1,Inf) ) )]
#--------------
> df.all
   x_pred_normalized y_pred_normalized   quad
1         0.78886879         0.3063979  Third
2         0.48122193         0.5440334 Second
3         0.85496224         0.4849327  Third
4         0.01457113         0.5116597 Second
5         0.76936612         0.7424495 Fourth
6         0.99999000         0.4544564  Third
7         0.55473184         0.0000000  Third
8         0.99967092         0.7843946 Fourth
9         0.72561140         0.3985747  Third
10        0.17755530         0.1337408  First

对于圆包含列,我将使用乘以索引值的逻辑测试,该索引值可用于通过布尔运算从向量中提取值:

dist= function(x,y) 
df.all$circle <- with( df.all, c("other", "First", "Second", "Third", "Fourth")[
      1 +  # value when all subsequent tests are FALSE
      1*(sqrt( (x_pred_normalized-0.25)^2+(y_pred_normalized-0.25)^2) <=0.25) + 
       # above should be should be 1 (TRUE) for lower-rt;  else 0
      2*(sqrt( (x_pred_normalized-0.25)^2+ (y_pred_normalized-0.75)^2) <=0.25)+
      3*(sqrt( (x_pred_normalized-0.75)^2+(y_pred_normalized-0.25)^2) <=0.25)+
      4*(sqrt( (x_pred_normalized-0.75)^2+(y_pred_normalized-0.75)^2)<=0.25) ] )
#--------------
> df.all
   x_pred_normalized y_pred_normalized   quad circle
1         0.78886879         0.3063979  Third  Third
2         0.48122193         0.5440334 Second  other
3         0.85496224         0.4849327  Third  other
4         0.01457113         0.5116597 Second  other
5         0.76936612         0.7424495 Fourth Fourth
6         0.99999000         0.4544564  Third  other
7         0.55473184         0.0000000  Third  other
8         0.99967092         0.7843946 Fourth  other
9         0.72561140         0.3985747  Third  Third
10        0.17755530         0.1337408  First  First

我看到我使用了 0.25 的圆半径,而您要求的是 0.15。必要的更改应该易于实施。