原理介绍公式推导请参考下面这篇文章:
https://blog.csdn.net/xiaowei_cqu/article/details/26471527
import cv2
import numpy as np
import matplotlib.pylab as plt
img = cv2.imread('/home/aaron/Pictures/bird.jpeg')
pts1 = np.float32([[940,270],[1158,434],[386,872],[630,1028]])
pts2 = np.float32([[0,0],[300,0],[0,600],[300,600]])
M = cv2.getPerspectiveTransform(pts1,pts2)
plt.subplot(121),plt.imshow(img),plt.title('Input')
cv2.line(img,(988, 398),(1086, 456),(155,155,155),5)
p_key = np.float32([[[988, 398], [1086, 456]]])
p_key1 = cv2.perspectiveTransform(p_key, M)
dst = cv2.warpPerspective(img,M,(300,600))
cv2.line(dst,(p_key1[0][0][0],p_key1[0][0][1]),(p_key1[0][1][0],p_key1[0][1][1]),(155,155,155),5)
print(p_key1)
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
cv2.imwrite('/home/aaron/Pictures/bird1.jpeg', img)
cv2.imwrite('/home/aaron/Pictures/bird2.jpeg', dst)
k1 = [988, 398]
M = np.transpose(M)
x = (k1[0]*M[0][0]+k1[1]*M[1][0]+M[2][0])/(k1[0]*M[0][2]+k1[1]*M[1][2]+M[2][2])
y = (k1[0]*M[0][1]+k1[1]*M[1][1]+M[2][1])/(k1[0]*M[0][2]+k1[1]*M[1][2]+M[2][2])
print(x, y)
首先根据对应的4个点对进行映射矩阵的求取.
M = cv2.getPerspectiveTransform(pts1,pts2)
关于全图的转换:
dst = cv2.warpPerspective(img,M,(300,600))
这里的关键点是选择的鸟的眼睛和嘴巴,下面进行了可视化变换前和变换后的效果.
关于关键点的变换方法有两种:
一种是通过透视变换的公式,代码中最后x,y的计算方法就是了.
一种是用opencv提供的函数:
p_key1 = cv2.perspectiveTransform(p_key, M)
注意这里p_key的形式.是np.float32的np.array坐标,使用方法参考上述代码.
这里在补充一个c++版本的实验代码;
cv::Mat src;
cv::Size size(400,400);
src.create(size, CV_MAKETYPE(0, 3));
Point2f srcTri[4];//源图像点
Point2f dstTri[4];//目标图像点
//源坐标
srcTri[0] = Point2f(0, 0);//左上
srcTri[1] = Point2f(400, 100);//右上
srcTri[2] = Point2f(400, 300);//左下
srcTri[3] = Point2f(0, 400);//右下
//目标坐标
dstTri[0] = Point2f(0, 0);
dstTri[1] = Point2f(400, 0);
dstTri[2] = Point2f(400, 400);
dstTri[3] = Point2f(0, 400);
cv::line(src, srcTri[0], srcTri[1], cv::Scalar(0, 255, 255), 5, 8, 0);
cv::line(src, srcTri[1], srcTri[2], cv::Scalar(0, 255, 255), 5, 8, 0);
cv::line(src, srcTri[2], srcTri[3], cv::Scalar(0, 255, 255), 5, 8, 0);
cv::line(src, srcTri[3], srcTri[0], cv::Scalar(0, 255, 255), 5, 8, 0);
cv::line(src, cv::Point(200,50), cv::Point(200,350), cv::Scalar(0, 255, 255), 5, 8, 0);
cv::Mat dst;
Mat transform = getPerspectiveTransform(srcTri, dstTri);
warpPerspective(src, dst, transform, size);
cv::Mat res;
cv::Size size1(400,800);
res.create(size1, CV_MAKETYPE(0, 3));
cv::Mat img1 = res(cv::Rect(0,0,400,400));
src.copyTo(img1);
cv::Mat img2 = res(cv::Rect(0,400,400,400));
dst.copyTo(img2);
cv::imshow("show", res);
cv::waitKey();
效果如图:上面的梯形变成下面的正方形,注意感觉透视变换的图像密度不均的表现。