旋转算法不产生预期结果

时间:2013-07-02 20:05:37

标签: c algorithm image-rotation idl-programming-language

我正在尝试将一些代码从IDL移植到C,我发现自己必须复制ROT功能。目标是将1024x1024无符号短路阵列旋转一个角度(以度为单位)。就本项目而言,角度非常小,小于1度。该函数使用双线性插值。

我尝试了向后的方法。对于输出数组中的每个像素,我进行了反向旋转以确定它将属于的输入数组中的坐标,然后使用插值来确定该值是什么。如果输入网格偏斜,我不知道如何进行双线性插值;我见过的每个例子都假设它是正交的。

对于轮换,我提到了这个:

x' = x * cos(a) + y * sin(a)
y' = y * cos(a) - x * sin(a)

来自:Image scaling and rotating in C/C++

对于插值,我提到了这个:http://en.wikipedia.org/wiki/Bilinear_interpolation

无论如何,这是我的代码:

#define DTOR 0.0174532925

void rotatearray(unsigned short int *inarray, unsigned short int *outarray, int xsize,
                 int ysize, double angle)
{
  //allocate temparray, set to 0                                                        
  unsigned short int *temparray;
  temparray = calloc(xsize*ysize, sizeof(unsigned short int));

  int xf, yf;
  int xi1, xi2, yi1, yi2;
  double xi, yi;
  double x, y;
  double minusangle = (360 - angle)*DTOR;
  unsigned short int v11, v12, v21, v22;

  int goodpixels=0;
  int badpixels=0;

  for(yf=0;yf<ysize;yf++)
    {
      for(xf=0;xf<xsize;xf++)
        {
          //what point in the input grid would map to this output pixel?                
          //(inverse of rotation)                                                       
          xi = (xf+0.5)*cos(minusangle) + (yf+0.5)*sin(minusangle);
          yi = (yf+0.5)*cos(minusangle) - (xf+0.5)*sin(minusangle);

          //Is it within bounds?                                                        
          if ((xi>(0+0.5))&&(xi<xsize-0.5)&&
              (yi>(0+0.5))&&(yi<ysize-0.5))
            {
              //what are the indices of the bounding input pixels?                  
              xi1 = (int)(xi - 0.5);                          
              xi2 = (int)(xi + 0.5);                        
              yi1 = (int)(yi - 0.5);
              yi2 = (int)(yi + 0.5);

              //What position is (x,y) in the bound unit square?
              x = xi - xi1;           
              y = yi - yi1;

              //what are the values of the bounding input pixels?                  
              v11 = inarray[yi1*xsize + xi1];//What are the values of                   
              v12 = inarray[yi2*xsize + xi1];//the bounding input pixels?               
              v21 = inarray[yi1*xsize + xi2];
              v22 = inarray[yi2*xsize + xi2];

              //Do bilinear interpolation                                               
              temparray[yf*xsize + xf] = (unsigned short int)
                (v11*(1-x)*(1-y) + v21*x*(1-y) + v12*(1-x)*y + v22*x*y);
              goodpixels++;
            }
          else{temparray[yf*xsize + xf]=0; badpixels++;}
        }
    }

  //copy to outarray                                                                    
  for(yf=0;yf<ysize;yf++)
    {
      for(xf=0;xf<xsize;xf++)
        {
          outarray[yf*xsize + xf] = temparray[yf*xsize+xf];
        }
    }

  free(temparray);
  return;
}

我通过打印几十个数字来测试它,并将它与IDL代码的相同ind进行比较,结果完全不同。我不确定我能提供哪些更多信息,因为我目前无法生成阵列的工作图像。你看到我的实施中有任何错误吗?我的理由是算法背后的声音吗?

编辑:这是输入数组中的一些选定数字;它们在C和IDL程序中是相同的。打印的是x索引,后跟y索引,后跟该点的值。

   0       0      24.0000
 256       0      17.0000
 512       0      23.0000
 768       0      21.0000
1023       0      0.00000
   0     256      19.0000
 256     256      459.000
 512     256      379.000
 768     256      191.000
1023     256      0.00000
   0     512      447.000
 256     512      388.000
 512     512      231.000
 768     512      231.000
1023     512      0.00000
   0     768      286.000
 256     768      378.000
 512     768      249.000
 768     768      205.000
1023     768      0.00000
   0    1023      6.00000
 256    1023      10.0000
 512    1023      11.0000
 768    1023      12.0000
1023    1023      0.00000

这是IDL程序在轮换后输出的内容:

   0       0      31.0000
 256       0      20.4179
 512       0      20.3183
 768       0      20.0000
1023       0      0.00000
   0     256      63.0000
 256     256      457.689
 512     256      392.406
 768     256      354.140
1023     256      0.00000
   0     512      511.116
 256     512      402.241
 512     512      230.939
 768     512      240.861
1023     512      0.00000
   0     768      296.826
 256     768      377.217
 512     768      218.039
 768     768      277.194
1023     768      0.00000
   0    1023      14.0000
 256    1023      8.00000
 512    1023      9.34906
 768    1023      23.7820
1023    1023      0.00000

以下是使用我的函数旋转后的数据:

[0,0]: 0
[256,0]: 44
[512,0]: 276
[768,0]: 299
[1023,0]: 0
[0,256]: 0
[256,256]: 461
[512,256]: 439
[768,256]: 253
[1023,256]: 0
[0,512]: 0
[256,512]: 377
[512,512]: 262
[768,512]: 379
[1023,512]: 0
[0,768]: 0
[256,768]: 340
[512,768]: 340
[768,768]: 198
[1023,768]: 18
[0,1023]: 0
[256,1023]: 0
[512,1023]: 0
[768,1023]: 0
[1023,1023]: 0

我没有看到一个立即有用的模式出现在这里,以表明发生了什么,这就是我最初没有包含它的原因。

编辑编辑编辑:我相信我的思绪突然偶然发现了问题!我注意到0,0像素似乎永远不会改变,并且1023,1023像素的变化最大。当然这意味着算法被设计为围绕原点旋转,而我假设我试图模仿的功能被设计为围绕图像的中心旋转。答案仍然不一样,但它更接近。我所做的就是改变这条线

      xi = (xf+0.5)*cos(minusangle) + (yf+0.5)*sin(minusangle);
      yi = (yf+0.5)*cos(minusangle) - (xf+0.5)*sin(minusangle);

      xi = (xf-512+0.5)*cos(minusangle) + (yf-512+0.5)*sin(minusangle) + 512;
      yi = (yf-512+0.5)*cos(minusangle) + (xf-512+0.5)*sin(minusangle) + 512;

0 个答案:

没有答案