图片旋转
对图像提取特征首先需要使用某种方法提取图片兴趣点,因为兴趣点仅仅是一个像素点,因此很难使用某种方法表示它使其具备差别性及鲁棒性,因此一般我们对兴趣点领域进行处理,将结果作为兴趣点的特征表示。
在提取特征前,会对兴趣点领域估计一个主方向,然后根据主方向对领域进行旋转,获得最终领域。获得主方向的方法有很多种方法:
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 }

浙公网安备 33010602011771号