仿射变换

来源:互联网 发布:淘宝巴黎心店卖假货 编辑:程序博客网 时间:2024/05/21 07:07

设原图像为f(x,y),畸变后的图像为F(X',Y'),要将F(X',Y')恢复为f(x,y),就是要找到(X',Y')坐标与(x,y)坐标的转换关系,这个转换关系称为仿射变换,表示为(x,y)=T(X',Y')。

要对图像进行仿射,首先要计算出坐标变换的系数,仿射变换的表达式为:R(x)=Px+Q, x=(x,y)是像素的平面位置,P是2*2的旋转矩阵,Q是2*1的平移向量,P、Q即为仿射变换参数,即:

                               x= AX' + BY' + C

                               y= DX' + EY' + F

因此,几何畸变的校正归根结底为坐标转换系数A,B,C,D,E,F的求解。

对于仿射变换矩阵系数的求解,首先要求出两幅图像对应的特征点,然后根据特征点对进行计算,这里的特征点对至少要有3对,并且3点不共线。

可以采用特征点提取算法进行特征点提取。

在求出特征点对之后,通过最小二乘法计算出仿射变换矩阵。

#include "stdafx.h"#include <opencv2/video/video.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/core/core.hpp>#include <fstream>  #include <iostream>#include <cstdio>#include "features2d/features2d.hpp"using namespace std;using namespace cv;vector<Point2f> points[2];// point0为特征点的原来位置,point1为特征点的新位置vector<Point2f> features;// 检测的特征int maxCount = 500;// 检测的最大特征数double qLevel = 0.01;// 特征检测的等级double minDist = 10.0;// 两特征点之间的最小距离vector<uchar> status;// 跟踪特征的状态,特征的流发现为1,否则为0vector<float> err;void on_mouse( int event, int x, int y, int flags, void* ustc);bool acceptTrackedPoint(int i);void main(){Mat warp_dst,output,origin;Mat image=imread("G:\\2.jpg",0);Mat image2=imread("G:\\2_2.jpg",0);origin=imread("G:\\2.jpg",1);output=imread("G:\\2_2.jpg",1);Mat result,result1;Mat warp_mat( 2, 3, CV_32FC1 );//检测第一帧特征点goodFeaturesToTrack(image, features, maxCount, qLevel, minDist);//检测gray的特征点cornerSubPix( image, features,cvSize(10,10),  cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03) );//检测gray亚像素特征点points[0].insert(points[0].end(), features.begin(), features.end());//将gray特征点存到points[0]中//检测第二帧对应特征点calcOpticalFlowPyrLK(image, image2, points[0], points[1], status, err);//根据两帧之间特征点矢量长度去掉一些不好的特征点int k = 0;for (size_t i=0; i<points[1].size(); i++){if (acceptTrackedPoint(i)){points[0][k]=points[0][i];points[1][k++] = points[1][i];}}points[1].resize(k);points[0].resize(k);for (size_t i=0; i<points[1].size(); i++){line(output, points[0][i], points[1][i], Scalar(0, 0, 255));circle(output, points[0][i], 3, Scalar(0, 0, 255), -1);circle(output, points[1][i], 3, Scalar(255, 0, 0), -1);}for (size_t i=0; i<points[0].size(); i++){circle(origin, points[0][i], 3, Scalar(0, 0, 255), -1);}imshow("origin",origin);imshow("output",output);cvSetMouseCallback( "output", on_mouse, 0 );   cvSetMouseCallback( "origin", on_mouse, 0 );   warp_mat=estimateRigidTransform(points[1],points[0],1);warpAffine( image2, warp_dst, warp_mat, warp_dst.size() );//进行仿射变换imshow("仿射变换",warp_dst);;  absdiff(image,warp_dst,result);//进行差分运算  absdiff(image,image2,result1);//进行差分运算 imshow("仿射帧间差",result);  imshow("直接帧间差1",result1);waitKey(0);//}bool acceptTrackedPoint(int i){return status[i] && ((abs(points[0][i].x - points[1][i].x) + abs(points[0][i].y - points[1][i].y)) <30)&& ((abs(points[0][i].x - points[1][i].x) + abs(points[0][i].y - points[1][i].y)) > 5);}void on_mouse( int event, int x, int y, int flags, void* ustc)    {        CvFont font;        cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);                    if( event == CV_EVENT_LBUTTONDOWN )        {            CvPoint pt = cvPoint(x,y);            char temp[16];            sprintf(temp,"(%d,%d)",pt.x,pt.y);            cout<<temp<<endl;      }     } 



0 0
原创粉丝点击