opencv透视变换

opencv透视变换

实现透视变换

目标:

在这篇教程中你将学到:

1、如何进行透视变化

2、如何生存透视变换矩阵

理论:

什么是透视变换:

1、透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。

2、换算公式

u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中
变换矩阵可以拆成4部分,表示线性变换,比如scaling,shearing和ratotion。用于平移,产生透视变换。所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况)。

重写之前的变换公式可以得到:

所以,已知变换对应的几个点就可以求取变换公式。反之,特定的变换公式也能新的变换后的图片。简单的看一个正方形到四边形的变换:
变换的4组对应点可以表示成:

根据变换公式得到:

定义几个辅助变量:

都为0时变换平面与原来是平行的,可以得到:

不为0时,得到:

求解出的变换矩阵就可以将一个正方形变换到四边形。反之,四边形变换到正方形也是一样的。于是,我们通过两次变换:四边形变换到正方形+正方形变换到四边形就可以将任意一个四边形变换到另一个四边形。

代码:

#include  "opencv2/highgui.hpp"
#include  "opencv2/imgproc.hpp"
#include  <iostream>
#include  <stdio.h>
using  namespace  cv;
using  namespace  std;
/**  @function  main  */
int  main(  int  argc,  char**  argv  )
{
             cv::Mat src= cv::imread( "test.jpg",0);
                 if (!src.data)
                                 return 0;
                vector<Point> not_a_rect_shape;
                not_a_rect_shape.push_back(Point(122,0));
                not_a_rect_shape.push_back(Point(814,0));
                not_a_rect_shape.push_back(Point(22,540));
                not_a_rect_shape.push_back(Point(910,540));
                 // For debugging purposes, draw green lines connecting those points
                 // and save it on disk
                const Point* point = &not_a_rect_shape[0];
                int n = (int )not_a_rect_shape.size();
                Mat draw = src.clone();
                polylines(draw, &point, &n, 1, true, Scalar(0, 255, 0), 3, CV_AA);
                imwrite( "draw.jpg", draw);
                 //  topLeft, topRight, bottomRight, bottomLeft
                cv::Point2f src_vertices[4];
                src_vertices[0] = not_a_rect_shape[0];
                src_vertices[1] = not_a_rect_shape[1];
                src_vertices[2] = not_a_rect_shape[2];
                src_vertices[3] = not_a_rect_shape[3];

Point2f dst_vertices[4];
                dst_vertices[0] = Point(0, 0);
                dst_vertices[1] = Point(960,0);
                dst_vertices[2] = Point(0,540);
                dst_vertices[3] = Point(960,540);
                Mat warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);
                cv::Mat rotated;
                warpPerspective(src, rotated, warpMatrix, rotated.size(), INTER_LINEAR, BORDER_CONSTANT);
                 // Display the image
                cv::namedWindow( "Original Image");
                cv::imshow( "Original Image",src);
                cv::namedWindow( "warp perspective");
                cv::imshow( "warp perspective",rotated);
                imwrite( "result.jpg",src);
                cv::waitKey();
                 return 0;
}

代码解释:

1、获取图片,如果输入路径为空的话程序直接退出

cv::Mat src= cv::imread( "test.jpg",0);
                 if (!src.data)
                                 return 0;

2、定义边界点,输入到std::vector数据结构中。注意这里的顺序如上图。

vector<Point> not_a_rect_shape;
                not_a_rect_shape.push_back(Point(122,0));
                not_a_rect_shape.push_back(Point(814,0));
                not_a_rect_shape.push_back(Point(22,540));
                not_a_rect_shape.push_back(Point(910,540));

并将这几个点标注出来

const Point* point = &not_a_rect_shape[0];
                int n = (int )not_a_rect_shape.size();
                Mat draw = src.clone();
                polylines(draw, &point, &n, 1, true, Scalar(0, 255, 0), 3, CV_AA);
                imwrite( "draw.jpg", draw);

3、生成透视变换矩阵

cv::Point2f src_vertices[4];
                src_vertices[0] = not_a_rect_shape[0];
                src_vertices[1] = not_a_rect_shape[1];
                src_vertices[2] = not_a_rect_shape[2];
                src_vertices[3] = not_a_rect_shape[3];

Point2f dst_vertices[4];
                dst_vertices[0] = Point(0, 0);
                dst_vertices[1] = Point(960,0);
                dst_vertices[2] = Point(0,540);
                dst_vertices[3] = Point(960,540);
                Mat warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);

4、执行转换

cv::Mat rotated;
                warpPerspective(src, rotated, warpMatrix, rotated.size(), INTER_LINEAR, BORDER_CONSTANT);

5、显示并保存结果

// Display the image
                cv::namedWindow( "Original Image");
                cv::imshow( "Original Image",src);
                cv::namedWindow( "warp perspective");
                cv::imshow( "warp perspective",rotated);
                imwrite( "result.jpg",src);

结果:

原始图片

标注四个边界点

透视变换后的图片

需要注意的是,这里变化后的图像丢失了一些边界细节,这在具体实现的时候是需要注意的。

来自为知笔记(Wiz)

时间: 2024-10-12 15:17:22

opencv透视变换的相关文章

Java基于opencv—透视变换矫正图像

很多时候我们拍摄的照片都会产生一点畸变的,就像下面的这张图 虽然不是很明显,但还是有一点畸变的,而我们要做的就是把它变成下面的这张图 效果看起来并不是很好,主要是四个顶点找的不准确,会有一些偏差,而且矫正后产生的目标图是倒着的,哪位好心人给说说为啥 因为我也没有测试畸变很大的图像,也不能保证方法适用于每个图像,这里仅提供我的思路供大家参考. 思路: 我们最重要的就是找到图像的四个顶点,有利用hough直线,求直线交点确定四个顶点,有采用寻找轮廓确定四个顶点等等:今天我提供的思路,也是采用寻找轮廓

OpenCV 透视变换实例

参考文献: http://www.cnblogs.com/self-control/archive/2013/01/18/2867022.html http://opencv-code.com/tutorials/automatic-perspective-correction-for-quadrilateral-objects/ 透视变换: http://blog.csdn.net/xiaowei_cqu/article/details/26478135 具体流程为: a)载入图像→灰度化→边

opencv透视变换GetPerspectiveTransform的总结

对于透视变换,必须为map_matrix分配一个3x3数组,除了3x3矩阵和三个控点变为四个控点外,透视变化在其他方面与仿射变换完全类似.具体可以参考:点击打开链接 主要用到两个函数WarpPerspective和GetPerspectiveTransform. 1)WarpPerspective 对图像进行透视变换 void cvWarpPerspective( const CvArr* src, CvArr* dst,const CvMat* map_matrix, int flags=CV

网友提问(透视变化)

您好: 我在网上看到您的opencv透视变换的博客,https://www.cnblogs.com/jsxyhelu/p/4219564.html, 我是opencv小菜鸟一个,现在想要得到一个图片变形之后保存,整个图片信息不丢失,即四个角的信息不丢失应该怎么做?原图中某一点在新图中坐标应该怎么计算?万望不吝赐教,不胜感激,万分感谢. 你好: 我按照您的代码和网上找到的python代码(https://blog.csdn.net/fengxueniu/article/details/779643

OpenCV】透视变换 Perspective Transformation(续)

载分 [OpenCV]透视变换 Perspective Transformation(续) 分类: [图像处理] [编程语言] 2014-05-27 09:39 2776人阅读 评论(13) 收藏 举报 透视变换的原理和矩阵求解请参见前一篇<透视变换 Perspective Transformation>.在OpenCV中也实现了透视变换的公式求解和变换函数. 求解变换公式的函数: [cpp] view plaincopyprint? Mat getPerspectiveTransform(c

【OpenCV】透视变换 Perspective Transformation(续)

透视变换的原理和矩阵求解请参见前一篇<透视变换 Perspective Transformation>.在OpenCV中也实现了透视变换的公式求解和变换函数. 求解变换公式的函数: Mat getPerspectiveTransform(const Point2f src[], const Point2f dst[]) 输入原始图像和变换之后的图像的对应4个点,便可以得到变换矩阵.之后用求解得到的矩阵输入perspectiveTransform便可以对一组点进行变换: void perspec

【OpenCV】透视变换矫正

演示结果参考: 功能实现:运行程序,会显示图片的尺寸,按回车键后,依次点击需矫正的图片的左上.右上.左下.右下角,结果弹出矫正后的图片,如图上的PIC2对话框.按下字符'q'后退出. 代码如下:(注:图中的11.jpg图片自己选取放到该程序目录下.) #include <opencv2/opencv.hpp> #include <iostream> #include <vector> using namespace std; using namespace cv; co

OpenCV+Python 文字识别(重点图像透视变换)

1 # Author:Winter Liu is coming! 2 import cv2 as cv 3 import numpy as np 4 import pytesseract 5 6 7 # 预处理,高斯滤波(用处不大),4次开操作 8 # 过滤轮廓唯一 9 def contour_demo(img): 10 gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) 11 gray = cv.GaussianBlur(gray, (5, 5), 1) 12

OpenCV 点集匹配 ransac

本文是转载 + 自己心得 , 参考文献后面写 estimateRigidTransform():计算多个二维点对或者图像之间的最优仿射变换矩阵 (2行x3列),H可以是部分自由度,比如各向一致的切变. getAffineTransform():计算3个二维点对之间的仿射变换矩阵H(2行x3列),自由度为6. warpAffine():对输入图像进行仿射变换 findHomography: 计算多个二维点对之间的最优单映射变换矩阵 H(3行x3列) ,使用最小均方误差或者RANSAC方法 . ge