织梦CMS - 轻松建站从此开始!

罗索

双线性插值(Bilinear interpolation)的图像旋转在mobile上面的C+

落鹤生 发布于 2012-06-13 09:23 点击:次 
这个图像公式大家在高中数学课都是会算滴。 然后我们要扩展一下因为我们不是在原点做旋转,我们要围绕原来的图片中心做旋转, 那么我们假定原来的图像中心是 oldCenterX, oldCenterY.旋转完成以后, 我们要对图像位置坐调整,调整到新的坐标中心
TAG:

在图像拉伸了以后, 很自然地我们想把图像的旋转也做进来。我们找来了图像旋转的公式:

X' =  X cosθ -  Y sinθ;

Y' =  X sinθ  + Y cosθ;

这个图像公式大家在高中数学课都是会算滴。 然后我们要扩展一下因为我们不是在原点做旋转,我们要围绕原来的图片中心做旋转, 那么我们假定原来的图像中心是 oldCenterX, oldCenterY.旋转完成以后, 我们要对图像位置坐调整,调整到新的坐标中心, 那么我们需要有个新的newCenterX, newCenterY;新的坐标就是新的图片的中心。那么我们的公式就可以转化成了:

X' =  (X-oldCenterX) cosθ -  (Y-oldCenterY) sinθ  + newCenterX;

Y' =  (X-oldCenterX) sinθ  + (Y-oldCenterY) cosθ + newCenterY;

当然啦, 关键我们的问题不是旋转后的位置,而是旋转以后位置对于到原来的位置关系,也就是说我们更需要的是一个X,Y关于X'和Y'的表达式。很简单的,我们把问题变成了2元一次方程!

X = Y'sinθ + X'cosθ + oldCenterY - newCenterX cosθ - newCenterY sinθ;

Y = Y'cosθ - X'sinθ + oldCenterY - newCenterY cosθ + newCenterX sinθ;

这样要写个合适的代码就变得简单了。 但是另一个显著的问题就是没有三角函数怎么办呢? 就像我们插值的时候用大数一样, 我们用左移13位的大数来描述一下先,就像下面这样的:

  1. //test interface for math 
  2. const int K_CosineTable[24] =  
  3.     8192, 
  4.     8172, 
  5.     8112, 
  6.     8012, 
  7.     7874, 
  8.     7697, 
  9.     7483, 
  10.     7233, 
  11.     6947, 
  12.     6627, 
  13.     6275, 
  14.     5892, 
  15.     5481, 
  16.     5043, 
  17.     4580, 
  18.     4096, 
  19.     3591, 
  20.     3068, 
  21.     2531, 
  22.     1981, 
  23.     1422, 
  24.     856, 
  25.     285, 
  26.     -285  
  27. }; 
  28. int ShiftCos(int y) 
  29.     if (y<0) y*=-1; 
  30.     y %= 360; 
  31.     if ( y > 270 )  
  32.     { 
  33.         return ShiftCos((360 - y)); 
  34.     } 
  35.     else if ( y > 180 )  
  36.     { 
  37.         return - ShiftCos((y - 180)); 
  38.     } 
  39.     else if ( y > 90 )  
  40.     {  
  41.         return - ShiftCos((180 - y)); 
  42.     } 
  43.     int index  = (y >> 2); 
  44.     int offset = (y % 4); 
  45.     // on the borderline of overflowing if use JInt16 
  46.     int cosVal = (4 - offset) * K_CosineTable[index] 
  47.     + offset * K_CosineTable[index + 1]; 
  48.     return cosVal >> 2; 
  49. int ShiftSin(int y) 
  50.     return ShiftCos(y + 270); 

有了这个三角函数的辅助:我们的最后的代码就是这个样子:

  1. /** 
  2. ** method to remove sharp the raw image with unsharp mask 
  3. * @param src input grayscale binary array  
  4. * @param srcWidth width of the input grayscale image 
  5. * @param srcHeight height of the input grayscale image 
  6. * @param [output] dst output gray-scale image. 
  7. * @param [output] dstWidth width of the output grayscale image 
  8. * @param [output] dstHeight height of the output grayscale image 
  9. * @param angle, rotate angle. 
  10. */ 
  11. void rotateImage (const unsigned char* src, int srcWidth, int srcHeight
  12. , unsigned char*& dst, int& dstWidth, int& dstHeight, int angle) 
  13.      
  14.     // first calculate the new width and height; 
  15.     const int SHIFT = 13;    
  16.     dstWidth  = ( abs (srcWidth*ShiftCos(angle))
  17.  + abs (srcHeight*ShiftSin(angle))) >> SHIFT;            
  18.     dstHeight = ( abs (srcWidth*ShiftSin(angle))
  19.  + abs (srcHeight*ShiftCos(angle))) >> SHIFT;            
  20.     dst = new unsigned char [dstWidth*dstHeight]; 
  21.     int xcenter = srcWidth >> 1; 
  22.     int ycenter = srcHeight >> 1; 
  23.     int xnew = dstWidth >> 1; 
  24.     int ynew = dstHeight >> 1; 
  25.     const int xFix = ( xcenter <<8 ) - ((ynew * ShiftSin (angle)) >> 5 )
  26.  - ((xnew * ShiftCos (angle)) >> 5) ;  
  27.     const int yFix = ( ycenter <<8 ) + ((xnew * ShiftSin (angle)) >> 5 )
  28.  - ((ynew * ShiftCos (angle)) >> 5) ; 
  29.      
  30.     int ox; 
  31.     int oy; 
  32.     int x; 
  33.     int y; 
  34.     int kx; 
  35.     int ky; 
  36.     int color [2][2]; 
  37.     for (int j=0;j<dstHeight;j++) 
  38.     { 
  39.         for (int i=0;i<dstWidth;i++) 
  40.         { 
  41.             ox = ((i * ShiftCos (angle) + j * ShiftSin (angle)) >> 5) + xFix; 
  42.             oy = (((-1) * i * ShiftSin(angle) + j * ShiftCos (angle)) >> 5) + yFix;  
  43.             if ( (ox >> 8) <= srcWidth && (ox >> 8) >=0 && (oy >> 8)
  44.  <= srcHeight && (oy >> 8) >= 0) 
  45.             { 
  46.                 kx = ox >> 8; 
  47.                 ky = oy >> 8; 
  48.                 x = ox & 0xFF; 
  49.                 y = oy & 0xFF; 
  50.                 color[0][0] = src[ ky*srcWidth + kx ];  
  51.                 color[1][0] = src[ ky*srcWidth + kx +1 ];  
  52.                 color[0][1] = src[ (ky+1)*srcWidth + kx ];  
  53.                 color[1][1] = src[ (ky+1)*srcWidth + kx+1 ]; 
  54.                 int final = (0x100 - x)*(0x100 - y)*color[0][0] 
  55. + x*(0x100 - y)*color[1][0] + (0x100-x)*y*color[0][1] + x*y*color[1][1]; 
  56.                 final = final >> 16; 
  57.                 if (final>255) 
  58.                     final = 255; 
  59.                 if (final<0) 
  60.                     final = 0; 
  61.                 dst [ j*dstWidth + i] = (unsigned char)final; 
  62.             } 
  63.             else 
  64.             { 
  65.                 dst [j*dstWidth + i] = 0xff; 
  66.             } 
  67.         } 
  68.     } 

这里说明一下的是接口的定义,这里的和目标灰度图相关的参数都是引用类型的。表示都是输出的参数,因为图像旋转以后的大小会发生变化,函数外不是很方便事 先分配好内存,所以这里采用了就地分配的模式。内存分配在函数内部完成。虽然没有用ticks去最后测速,但是想来没有浮点数的计算,这里的效率还是比较 高的,当然这里一些细节的记录上还有可以再优化一下的,比如说这个常数5!!!Majic Number呵呵, 其实就是原来的那些数字都希望是左移8的, 所以三角函数中出来的数字需要左移5位!!除此以外就完全是公式的套用了 呵呵。

(hhygcy)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201206/16085.html]
本文出处:CSDN博客 作者:hhygcy 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容