#include <iostream>
#include <fstream>
#include <sstream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <string>
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
Mat img = imread("C:\\Users\\Administrator\\Desktop\\图片 001.jpg");
Mat img_gray;
cvtColor(img,img_gray,CV_RGB2GRAY);
namedWindow("gray");
imshow("gray",img_gray);
int rows = img.rows;
int cols = img.cols;
Point2f src[4]; //源图像中的四个点
Point2f dst[4]; //目标图像中的四个点
src[0].x = 1;
src[0].y = 121;
src[1].x = 639;
src[1].y = 130;
src[2].x = 1;
src[2].y = 417;
src[3].x = 639;
src[3].y = 417;
dst[0].x = 1;
dst[0].y = 1;
dst[1].x = 639;
dst[1].y = 1;
dst[2].x = 1;
dst[2].y = 288;
dst[3].x = 639;
dst[3].y = 288;
Mat t; //变换矩阵
t = getPerspectiveTransform(src,dst);
printf("transform matrix\n");
for(int i =0;i<3;i++) //打印透视变换矩阵
{
printf("% .6f ",t.at<double>(0,i));
printf("% .6f ",t.at<double>(1,i));
printf("% .6f \n",t.at<double>(2,i));
}
Mat pers_res(288,640,CV_8UC1); //保存透视变换后的矩阵
for (int i=121;i<=417;i++) //原图像目标图变换
{
for (int j=1;j<640;j++)
{
Mat sample = (Mat_<double>(3,1)<<j,i,1);
Mat r = t*sample;
double s = r.at<double>(2,0);
int x = cvRound(r.at<double>(0,0)/s); %除以s 归一化为齐次坐标
int y = cvRound(r.at<double>(1,0)/s);
if ( (x>=0&&x<640)&&(y>=0&&y<288))
{
pers_res.at<uchar>(y,x) = img_gray.at<uchar>(i,j);
}
}
}
namedWindow("result");
imshow("result",pers_res);
}
目的是将原图中一个梯形转为标准的矩形,所以用透视变换来做,原图和变换后的图如下。不过因为透视变换,变换后的图可能出现白道道,这是因为变换过程中有拉扯现象,最好做一个插值处理。
变换后的标准矩形图(我只取了原图的下边三条黑线最上边黑线的上边部分进行变换):