图片旋转

对图像提取特征首先需要使用某种方法提取图片兴趣点,因为兴趣点仅仅是一个像素点,因此很难使用某种方法表示它使其具备差别性及鲁棒性,因此一般我们对兴趣点领域进行处理,将结果作为兴趣点的特征表示。

在提取特征前,会对兴趣点领域估计一个主方向,然后根据主方向对领域进行旋转,获得最终领域。获得主方向的方法有很多种方法:

  1、max 法,计算兴趣点的dx,dy,求max(dx,dy)

  2、类sift法,计算领域中每个像素的方向然后进行投票,取最大值方法作为领域的主方向

  3、灰度重心法,分别计算x,y方向的图像不变矩m10,m01,theta = atan(m01,m10)

 

接下来主要介绍如何对patch块进行旋转。

(x,y)旋转theta角度,结果为(rotate_x,rotate_y)

旋转矩阵M = [ cosin(theta) -sin(theta)

      sin(theta) cosin(theta) ]

那么 (rotate_x , rotate_y ) = M*(x,y);

即rotate_x = x*cosin(theta) - y*sin(theta)

rotate_y = x*sin(theta)+y*cosin(theta)

 

根据以上方法,我们遍历原patch块中的所有像素,计算其旋转后的坐标,即得旋转图片。

 1 inline void rotatedImage(double descriptor_dir,
 2     const cv::KeyPoint& kpt,
 3     const cv::Mat& img,
 4     const int& patch_size,
 5     const cv::Mat &rotateImg
 6     )
 7 {
 8 
 9 
10     descriptor_dir *= (float)(CV_PI/180);
11     float sin_dir = sin(descriptor_dir);
12     float cos_dir = cos(descriptor_dir);
13     float win_offset = (int)(patch_size/2);
14     
15     for(int i = 0; i < patch_size; i++){
16     
17         for(int j = 0; j < patch_size; j++){
18             float pixel_x = j*cos_dir - i*sin_dir;
19             float pixel_y = j*sin_dir + i*cos_dir;
20             int x = (int)(pixel_x + 0.5);
21             int y = (int)(pixel_y + 0.5);
22             rotateImg.at<unsigned char>(i, j) = img.at<unsigned char>(y, x);
23         }
24     }
25 }

可以看出根据以上算法计算旋转图片比较耗时,每个像素都需要使用4次乘法操作以四次加减法操作。每个图片的兴趣一般超过100个,因此对效率影响非常大。

我们对图片从左到右从上到下一一进行遍历,因此前一个处理的像素坐标与后一个像素坐标相关,那么旋转后的坐标也与前一个像素旋转后的坐标也相关。

(x+1 , y )*M = (rotate_x+1, rotatey_y)

rotate_x+1 = (x+1) cosin(theta) - y*sin(theta) = x*cosin(theta) -y*sin(theta) + cosin(theta)

rotate_y  =(x+1 ) sin(theta) + y*cosin(theta ) = x*sin(theta) + y*cosin(theta) +sin(theta)

即 (x+1 , y )*M = (x,y)*M +(cosin(theta), sin(theta) )

同理(x,y+1)*M =(x,y)*M +(-sin(theta) ,cosin(theta));

 

 1 inline void rotatedImage(double descriptor_dir,//旋转角度
 2     const cv::KeyPoint& kpt,//兴趣点
 3     const cv::Mat& img,//图片
 4     const int& patch_size,//领域patch块大小
 5     cv::Mat & rotateImg//旋转后的patch块
 6     )
 7 {
 8 
 9     
10     descriptor_dir *= (float)(CV_PI/180);
11     float sin_dir = sin(descriptor_dir);
12     float cos_dir = cos(descriptor_dir);
13     float win_offset = (int)(patch_size/2);
14     
15     
16     float start_x = kpt.pt.x - win_offset*cos_dir + win_offset*sin_dir;
17     float start_y = kpt.pt.y - win_offset*sin_dir - win_offset*cos_dir;
18 
19     for(int i = 0; i < patch_size; i++, start_x -= sin_dir, start_y += cos_dir){
20         float pixel_x = start_x;
21         float pixel_y = start_y;
22         for(int j = 0; j < patch_size; j++, pixel_x += cos_dir, pixel_y += sin_dir){
23             int x = (int)(pixel_x + 0.5);
24             int y = (int)(pixel_y + 0.5);
25             rotateImg.at<unsigned char>(i, j) = img.at<unsigned char>(y, x);
26         }
27     }
28 }
posted @ 2014-07-18 20:56  dupuleng  阅读(271)  评论(0)    收藏  举报