(尽管动机一直保持不变,但我已经对整个问题进行了大幅度的修改。)

修订后的问题

我想将笛卡尔像素的栅格转换为极性像素。有这样做的明智算法吗?例如,在给定重叠的三个(笛卡尔)像素值的情况下,如何计算下图中阴影(极性)像素的值?



原始问题

是否有合理的方法来计算正方形和环形截面的交点面积,如下面的橙色部分所示?



动机:我有一个正方形像素的栅格,并将其转换为“极性像素”-我想找出每个笛卡尔像素对每个极性像素的贡献。

评论

环形切片的左边界与矩形轴的对齐完全是巧合吗?

这是承保范围计算吗?您为什么选择实施效率非常低的盒式过滤器?

@joojaa同意,但如果使它更容易,则可以从一些覆盖率计算中构建出一个近似的高斯函数。

@trichoplax:点好!我将讨论Maths.SE的问题-谢谢您的指导。

这样的事情。一般而言,箱式过滤是您可以选择的最差的过滤器。像素不是真正的正方形,而是点样本(读取的像素不是正方形x 3)。通过使用标准函数重建,您可以对有限采样进行相同的处理,这比框式过滤器可以产生更好的图像,因为您的工作量较少盒过滤算法是如此令人费解且昂贵。

#1 楼

我已经实现了笛卡尔到极点的转换,并使用了不同的插值方法:

1)最近邻

2)二次采样方法,平均81个子像素位置

3)双线性插值

下图中的第二行显示了三种方法的输出的详细放大倍数:



这是方法1和方法3的GLSL着色器代码:

precision mediump float;
varying vec2 tc; // texture coordinate of current output pixel
uniform sampler2D inputImg; // input image
const float PI = 3.141592653589793238462643383;
void main() {
  float phi = tc.x; // phi is x-direction in output
  float r = tc.y;   // radius is y-direction in output
  float xx = r * cos(2.0 * PI * phi);  // unit circle in range [-1.0, 1.0]
  float yy = r * sin(2.0 * PI * phi);
  float x = xx * 0.5 + 0.5; // input texture coordinate in range [0.0, 1.0];
  float y = yy * 0.5 + 0.5;
  gl_FragColor = texture2D(inputImg, vec2(x,y));
}


这是方法2的GLSL着色器代码:

precision mediump float;
varying vec2 tc; // texture coordinate of current output pixel
uniform sampler2D inputImg; // input image
uniform int outputWidth; // width of output image
uniform int outputHeight; // height of output image
const float PI = 3.141592653589793238462643383;
const int samplesPerSide = 4;
void main() {
  int samplesPerDirection = samplesPerSide * 2 + 1;
  // compute size of subsample step in texture coordinates
  float sampleStepX = 1.0 / float(outputWidth * samplesPerDirection); 
  float sampleStepY = 1.0 / float(outputHeight * samplesPerDirection);
  vec4 sampleSum = vec4(0); // init sum to zero
  for(int i = -samplesPerSide; i <= samplesPerSide; i++) {
    for(int j = -samplesPerSide; j <= samplesPerSide; j++) {
      float phi = tc.x + float(i) * sampleStepX; // phi is x-direction in output
      float r = tc.y + float(j) * sampleStepY;   // radius is y-direction in output
      float xx = r * cos(2.0 * PI * phi);  // unit circle in range [-1.0, 1.0]
      float yy = r * sin(2.0 * PI * phi);
      float x = xx * 0.5 + 0.5; // input texture coordinate in range [0.0, 1.0];
      float y = yy * 0.5 + 0.5;
      sampleSum += texture2D(inputImg, vec2(x,y));
    }
  }
  gl_FragColor += sampleSum / float(samplesPerDirection * samplesPerDirection);
}


方法2,约为因子81比1和3慢,可能是您正在寻找的因子,但我也喜欢双线性插值结果。

使用具有WebGL功能的浏览器,您可以在此处尝试以下实现:

https://www.gsn-lib.org/index.html#projectName=CartesianToPolar&graphName=CartesianToPolar

评论


$ \ begingroup $
漂亮回答。并渲染。谢谢。
$ \ endgroup $
–fearless_fool
16年7月1日在23:24

$ \ begingroup $
请以后使用缩进的代码块。好答案
$ \ endgroup $
– joojaa
16年7月2日在7:14



#2 楼

我打电话给一位老同事和CG专家,问了几个问题后,他提供了一个简单的解决方案。我可能已经整理了一些细节,但是基本思想如下:

以所需的精确度对极坐标进行二次采样,将每个二次采样视为一个点。然后找到包含每个点的笛卡尔像素很简单。总结每个极点像素的子采样点以获得最终值。

正确设置权重有一些微妙之处-指导见解是,如果整个笛卡尔栅格为纯灰色,则每个极性像素应具有相同的灰度值。您还可以添加许多其他细微差别,但是基本技术是直观且计算简单的。