Opencv透视变换综合实例详解

本文实例为大家分享了Opencv透视变换综合实例的具体代码,供大家参考,具体内容如下

案例背景:对下面发生畸变的图像进行校正

方案思路:灰度二值化分割,闭操作,寻找轮廓,霍夫直线检测,直线排序,直线方程,直线交点,透视矩阵,透视变换。

#include<opencv2\opencv.hpp>
using namespace cv;
using namespace std;
int main(int arc, char** argv) {
 Mat src = imread("1.jpg");
 namedWindow("input", CV_WINDOW_AUTOSIZE);
 imshow("input", src);
 //灰度化
 Mat grayImg;
 cvtColor(src, grayImg, CV_BGR2GRAY);

 //二值化
 Mat binaryImg;
 threshold(grayImg, binaryImg, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);

 //闭操作
 Mat kernel = getStructuringElement(MORPH_RECT,Size(3,3));
 morphologyEx(binaryImg, binaryImg, MORPH_CLOSE,kernel,Point(-1,-1) ,3);
 imshow("output", binaryImg);

 //寻找轮廓
 Mat draw = Mat::zeros(src.size(), CV_8UC3);
 vector<vector<Point>>contours;
 findContours(binaryImg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
 for (int i = 0; i < contours.size(); i++) {
 Rect rect = boundingRect(contours[i]);
 if (rect.width < src.cols / 2 && rect.height < src.rows / 2)continue;
 drawContours(draw, contours, i, Scalar(0, 0, 255), 2);
 }
 imshow("output2", draw);

 //霍夫直线检测
 vector<Vec4i> lines;
 cvtColor(draw, draw, CV_BGR2GRAY);
 HoughLinesP(draw, lines, 1, CV_PI / 180, src.rows/2,src.rows/2,0);
 Mat draw2 = Mat::zeros(src.size(), CV_8UC3);
 for (int j = 0; j < lines.size(); j++) {
 Vec4i ln = lines[j];
 line(draw2, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 255, 0), 2);
 }
 printf("number of line:%d\n", lines.size());
 imshow("output3", draw2);

 //寻找与定位直线
 Vec4i topLine,bottomLine,leftLine,rightLine;
 for (int j = 0; j < lines.size(); j++) {
 Vec4i ln = lines[j];
 if (ln[1] < src.rows / 2 && ln[3] < src.rows / 2) {
  topLine = ln;
 }
 if (ln[1] > src.rows / 2 && ln[3] > src.rows / 2) {
  bottomLine = ln;
 }
 if (ln[0] < src.cols / 2 && ln[2] < src.cols / 2) {
  leftLine = ln;
 }
 if (ln[0] > src.cols / 2 && ln[2] > src.cols / 2) {
  rightLine = ln;
 }
 }
 cout << "topLine:p1(x,y)=" << topLine[0] << "," << topLine[1]<<" " << "p2(x,y)=" << topLine[2] << "," << topLine[3] << endl;
 cout << "bottomLine:p1(x,y)=" << bottomLine[0] << "," << bottomLine[1] << " " << "p2(x,y)=" << bottomLine[2] << "," << bottomLine[3] << endl;
 cout << "leftLine:p1(x,y)=" << leftLine[0] << "," << leftLine[1] << " " << "p2(x,y)=" << leftLine[2] << "," << leftLine[3] << endl;
 cout << "rightLine:p1(x,y)=" << rightLine[0] << "," << rightLine[1] << " " << "p2(x,y)=" << rightLine[2] << "," << rightLine[3] << endl;

 //求解直线方程
 float k1, c1;
 k1 = float((topLine[3] - topLine[1])) / float(topLine[2] - topLine[0]);
 c1 = topLine[1] - k1*topLine[0];
 float k2, c2;
 k2 = float((bottomLine[3] - bottomLine[1])) / float(bottomLine[2] - bottomLine[0]);
 c2 = bottomLine[1] - k2*bottomLine[0];
 float k3, c3;
 k3 = float((leftLine[3] - leftLine[1])) / float(leftLine[2] - leftLine[0]);
 c3 = leftLine[1] - k3*leftLine[0];
 float k4, c4;
 k4 = float((rightLine[3] - rightLine[1])) / float(rightLine[2] - rightLine[0]);
 c4 = rightLine[1] - k4*rightLine[0];

 //求解直线交点
 Point p1;
 p1.x = (int)((c1 - c3) / (k3 - k1));
 p1.y = (int)(k1*p1.x + c1);
 Point p2;
 p2.x = (int)((c1 - c4) / (k4 - k1));
 p2.y = (int)(k1*p2.x + c1);
 Point p3;
 p3.x = (int)((c2 - c4) / (k4 - k2));
 p3.y = (int)(k2*p3.x + c2);
 Point p4;
 p4.x = (int)((c2 - c3) / (k3 - k2));
 p4.y = (int)(k2*p4.x + c2);
 cout << "左上角:" << p1.x << "," << p1.y << endl;
 cout << "右上角:" << p2.x << "," << p2.y << endl;
 cout << "右下角:" << p3.x << "," << p3.y << endl;
 cout << "左下角:" << p4.x << "," << p4.y << endl;

 //画出交点
 circle(draw2, p1, 2, Scalar(0, 0, 255));
 circle(draw2, p2, 2, Scalar(0, 0, 255));
 circle(draw2, p3, 2, Scalar(0, 0, 255));
 circle(draw2, p4, 2, Scalar(0, 0, 255));
 imshow("output4", draw2);

 //透视变换
 vector<Point2f> srcCorners(4);
 srcCorners[0] = p1;
 srcCorners[1] = p2;
 srcCorners[2] = p3;
 srcCorners[3] = p4;
 vector<Point2f> dstCorners(4);
 dstCorners[0] = Point(0, 0);
 dstCorners[1] = Point(src.cols, 0);
 dstCorners[2] = Point(src.cols, src.rows);
 dstCorners[3] = Point(0, src.rows);
 Mat warpMartrix = getPerspectiveTransform(srcCorners, dstCorners);//Mat warpMartrix = findHomography(srcCorners, dstCorners);
 Mat result = Mat::zeros(src.size(), -1);
 warpPerspective(src, result, warpMartrix, result.size(),INTER_LINEAR);
 imshow("output5", result);
 waitKey(0);
 return 0;
}

原图像

二值化闭操作

寻找轮廓

霍夫直线

直线及其交点

效果图

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • python opencv实现任意角度的透视变换实例代码

    本文主要分享的是一则python+opencv实现任意角度的透视变换的实例,具体如下: # -*- coding:utf-8 -*- import cv2 import numpy as np def rad(x): return x * np.pi / 180 img = cv2.imread("6.jfif") cv2.imshow("original", img) # 扩展图像,保证内容不超出可视范围 img = cv2.copyMakeBorder(img,

  • Opencv-Python图像透视变换cv2.warpPerspective的示例

    Opencv-Python图像透视变换cv2.warpPerspective 代码如下: # -*- coding:utf-8 -*- import cv2 import numpy as np import sys img = cv2.imread('test.jpg') # cv2.imshow("original", img) # 可选,扩展图像,保证内容不超出可视范围 img = cv2.copyMakeBorder(img, 200, 200, 200, 200, cv2.B

  • Opencv透视变换综合实例详解

    本文实例为大家分享了Opencv透视变换综合实例的具体代码,供大家参考,具体内容如下 案例背景:对下面发生畸变的图像进行校正 方案思路:灰度二值化分割,闭操作,寻找轮廓,霍夫直线检测,直线排序,直线方程,直线交点,透视矩阵,透视变换. #include<opencv2\opencv.hpp> using namespace cv; using namespace std; int main(int arc, char** argv) { Mat src = imread("1.jpg

  • C语言实现opencv提取直线、轮廓及ROI实例详解

    一.Canny检测轮廓 在上一篇文章中有提到sobel边缘检测,并重写了soble的C++代码让其与matlab中算法效果一致,而soble边缘检测是基于单一阈值的,我们不能兼顾到低阈值的丰富边缘和高阈值时的边缘缺失这两个问题.而canny算子则很好的弥补了这一不足,从目前看来,canny边缘检测在做图像轮廓提取方面是最优秀的边缘检测算法. canny边缘检测采用双阈值值法,高阈值用来检测图像中重要的.显著的线条.轮廓等,而低阈值用来保证不丢失细节部分,低阈值检测出来的边缘更丰富,但是很多边缘并

  • 对Python+opencv将图片生成视频的实例详解

    如下所示: import cv2 fps = 16 size = (width,height) videowriter = cv2.VideoWriter("a.avi",cv2.VideoWriter_fourcc('M','J','P','G'),fps,size) for i in range(1,200): img = cv2.imread('%d'.jpg % i) videowriter.write(img) 以上这篇对Python+opencv将图片生成视频的实例详解就是

  • opencv python图像梯度实例详解

    这篇文章主要介绍了opencv python图像梯度实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一阶导数与Soble算子 二阶导数与拉普拉斯算子 图像边缘: Soble算子: 二阶导数: 拉普拉斯算子: import cv2 as cv import numpy as np # 图像梯度(由x,y方向上的偏导数和偏移构成),有一阶导数(sobel算子)和二阶导数(Laplace算子) # 用于求解图像边缘,一阶的极大值,二阶的零点

  • 基于Android studio3.6的JNI教程之opencv实例详解

    基本环境: Android studio3.6 NDK:r14b(尽量使用该版本) Opencv3.4.1 android sdk (1)新建工程OpenCVDemo,选择,一定要选择Native c++类型,最后要选c++14支持. (2)File->Project Structure->SDK Location,设置这3个路径,NDK选择r14b. (3)任意找一张图片,复制到res/drawable. (4)修改布局文件res/layout/ activity_main.xml <

  • opencv调用yolov3模型深度学习目标检测实例详解

    目录 引言 建立相关目录 代码详解 附源代码 引言 opencv调用yolov3模型进行深度学习目标检测,以实例进行代码详解 对于yolo v3已经训练好的模型,opencv提供了加载相关文件,进行图片检测的类dnn. 下面对怎么通过opencv调用yolov3模型进行目标检测方法进行详解,付源代码 建立相关目录 在训练结果backup文件夹下,找到模型权重文件,拷到win的工程文件夹下 在cfg文件夹下,找到模型配置文件,yolov3-voc.cfg拷到win的工程文件夹下 在data文件夹下

  • Python 通过URL打开图片实例详解

    Python 通过URL打开图片实例详解 不论是用OpenCV还是PIL,skimage等库,在之前做图像处理的时候,几乎都是读取本地的图片.最近尝试爬虫爬取图片,在保存之前,我希望能先快速浏览一遍图片,然后有选择性的保存.这里就需要从url读取图片了.查了很多资料,发现有这么几种方法,这里做个记录. 本文用到的图片URL如下: img_src = 'http://wx2.sinaimg.cn/mw690/ac38503ely1fesz8m0ov6j20qo140dix.jpg' 1.用Open

  • spring对JDBC和orm的支持实例详解

    简介 Spring提供的DAO(数据访问对象)支持主要的目的是便于以标准的方式使用不同的数据访问技术,如JDBC,Hibernate或者JDO等.它不仅可以让你方便地在这些持久化技术间切换, 而且让你在编码的时候不用考虑处理各种技术中特定的异常. 一致的异常层次 Spring提供了一种方便的方法,把特定于某种技术的异常,如SQLException, 转化为自己的异常,这种异常属于以 DataAccessException 为根的异常层次.这些异常封装了原始异常对象,这样就不会有丢失任何错误信息的

  • Vue项目webpack打包部署到服务器的实例详解

    Vue项目webpack打包部署到服务器 这篇博文主要说的就是我今天遇到的问题,而且在经过我的询问,好多人在打包部署的时候都遇到了一些问题,下面就来说下,如何将Vue项目放置在服务器上,这里以Tomcat为例. 必须要配置的就是/config/index.js 在vue-cli webpack的模板下的/config/index.js,我们可以看到assetsPublicPath这个键,并且这个东西还出现了两次,我第一次打包的时候,只是修改了最下面的assetsPublicPath,将它从'/'

  • AngularJS封装$http.post()实例详解

      AngularJS封装$http.post()实例详解 用了不是很长的时间跟了一个移动APP项目,用的是ionic + AngularJS + cordova框架,其间遇到过挺多问题,其中一个就是对Ajax的封装问题. 其实针对封装问题一直以来就没停止过谈论,不同的项目也有不同的需求,举个典型的例子,我在做这个项目的时候因为一开始没有考虑封装问题所以被批评了,而我的一个朋友却因为封装了受到了批评--很尴尬不是么. 那么对于是否要封装这个问题,究竟该怎么界定?其实这不是一个很复杂的问题,归根到

随机推荐