仿射变换
来源:互联网 发布:淘宝巴黎心店卖假货 编辑:程序博客网 时间: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
- 仿射变换&透视变换
- 几何变换 -- 仿射变换
- 【翻译】仿射变换
- 仿射变换
- 仿射变换
- 仿射变换
- 仿射变换
- 仿射变换
- 仿射变换
- 仿射变换
- 仿射变换
- cvWarpAffine:仿射变换
- 仿射变换
- 关于仿射变换
- 仿射变换
- 仿射变换
- 仿射变换
- 仿射变换
- hdu 1241 Oil Deposits
- 赛门铁克250-316大脑转储
- wince 获取项目当前路径
- oracle 可传输表空间
- java多线程(三)线程之间的通信
- 仿射变换
- android的listview中setselection()不起作用的解决方案
- map的遍历 以及 集合向数组的转换
- 关于cvCreateFileCapture()读取视频文件失败的解决方案
- Going Home(最小费用流)
- 职场分享--如何能够让自己更会赚钱
- 对removeNode方法的详细解释(附案例)
- redis(五)redis与Mybatis的无缝整合让MyBatis透明的管理缓存二
- POJ2155——Matrix