c# OpenCvSharp透视矫正六步实现透视矫正(八)

2023-12-26 07:04

本文主要是介绍c# OpenCvSharp透视矫正六步实现透视矫正(八),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

透视矫正,引用文档拍照扫描,相片矫正这块。

  1. 读取图像Cv2.ImRead();
  2. 预处理(灰度化,高斯滤波、边缘检测)
  3. 轮廓检测(获取到最大轮廓)
  4. 获取最大面积轮廓的四个顶点
  5. 标识最小矩形坐标
  6. 透视矫正显示

完整代码

 // 1、读取图像Mat image = Cv2.ImRead("2.jpg", ImreadModes.Color);//2、预处理(灰度化,高斯滤波、边缘检测)Mat src_gray = new Mat();Cv2.CvtColor(image, src_gray, ColorConversionCodes.BGR2GRAY); // 转换为灰度图像Cv2.GaussianBlur(src_gray, src_gray, new Size(5, 5), 0, 0); // 进行高斯模糊Mat canny_Image = new Mat();Cv2.Canny(src_gray, canny_Image, 75, 200);//3、轮廓检测Point[][] contours;HierarchyIndex[] hierarchy;Cv2.FindContours(canny_Image, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);// 计算轮廓的面积double maxArea = 0;int maxAreaIndex = -1;for (int i = 0; i < contours.Length; i++){double area = Cv2.ContourArea(contours[i]);if (area > maxArea){maxArea = area;maxAreaIndex = i;}}// 获取最大面积的轮廓Point[] largestContour = contours[maxAreaIndex];//4、获取最大面积轮廓的四个顶点。Point[] approx = Cv2.ApproxPolyDP(contours[maxAreaIndex], 0.02 * Cv2.ArcLength(contours[maxAreaIndex], true), true);Cv2.DrawContours(image, new Point[][] { approx }, -1, Scalar.Blue, 2);//可以注释掉for (int i = 0; i < 4; i++){// 设置目标图像的四个顶点坐标//Cv2.PutText(image, "H"+i, new Point(approx[i].X, approx[i].Y), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 255), 2, LineTypes.Link4);}//5、透视转换OpenCvSharp.Point2f[] srcPt = new OpenCvSharp.Point2f[4];srcPt[0] = approx[0];srcPt[1] = approx[3];srcPt[2] = approx[2];srcPt[3] = approx[1];RotatedRect rect = Cv2.MinAreaRect(srcPt);Rect box = rect.BoundingRect();OpenCvSharp.Point2f[] dstPt = new OpenCvSharp.Point2f[4];//可以注释掉用于观察坐标点是否对齐dstPt[0].X = 0;dstPt[0].Y = 0;dstPt[1].X = 0 + box.Width;dstPt[1].Y = 0;dstPt[2].X = 0 + box.Width;dstPt[2].Y = 0 + box.Height;dstPt[3].X = 0;dstPt[3].Y = 0 + box.Height;Mat final = new Mat(box.Height, box.Width, MatType.CV_8UC3);Mat warpmatrix = Cv2.GetPerspectiveTransform(srcPt, dstPt);//获得变换矩阵Cv2.WarpPerspective(image, final, warpmatrix, final.Size());//投射变换,将结果赋给finalCv2.ImShow("获取新正四边形", final);Cv2.WaitKey(0);Rect roi = new Rect(box.X, box.Y, box.Width, box.Height);//坐标 x,y 尺寸 长宽Mat croppedImage = new Mat(final, roi);for (int i = 0; i < 4; i++){// 设置目标图像的四个顶点坐标Cv2.PutText(image, "A" + i, new Point(dstPt[i].X, dstPt[i].Y), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 255), 2, LineTypes.Link4);}// 显示结果Cv2.ImShow("透视矫正图像", image);Cv2.WaitKey(0);

一 、读取图像Cv2.ImRead()

// 1、读取图像
Mat image = Cv2.ImRead("2.jpg", ImreadModes.Color);

二、预处理(灰度化,高斯滤波、边缘检测) 

灰度化:Cv2.CvtColor();

高斯滤波:Cv2.GaussianBlur();

边缘检测:Cv2.Canny();

//2、预处理(灰度化,高斯滤波、边缘检测)Mat src_gray = new Mat();
Cv2.CvtColor(image, src_gray, ColorConversionCodes.BGR2GRAY); // 转换为灰度图像
Cv2.GaussianBlur(src_gray, src_gray, new Size(5, 5), 0, 0); // 进行高斯模糊
Mat canny_Image = new Mat();
Cv2.Canny(src_gray, canny_Image, 75, 200);

 

三、轮廓检测(获取到最大轮廓) 

通过Cv2.ContourArea()计算轮廓的面积,选出最大轮廓

//3、轮廓检测
Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(canny_Image, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);// 计算轮廓的面积
double maxArea = 0;
int maxAreaIndex = -1;
for (int i = 0; i < contours.Length; i++)
{double area = Cv2.ContourArea(contours[i]);if (area > maxArea){maxArea = area;maxAreaIndex = i;}
}// 获取最大面积的轮廓
Point[] largestContour = contours[maxAreaIndex];

 

四、 获取最大面积轮廓的四个顶点。

Cv2.ApproxPolyDP() 获取4个顶点坐标

//4、获取最大面积轮廓的四个顶点。
Point[] approx = Cv2.ApproxPolyDP(contours[maxAreaIndex], 0.02 * Cv2.ArcLength(contours[maxAreaIndex], true), true);

 标识四个顶点

 //可以注释掉for (int i = 0; i < 4; i++){// 设置目标图像的四个顶点坐标Cv2.PutText(image, "H"+i, new Point(approx[i].X, approx[i].Y), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 255), 2, LineTypes.Link4);}

五、标识最小矩形坐标

获取顶点内最小矩形Cv2.MinAreaRect(srcPt);

//获取四个顶点坐标最小矩形顶点
RotatedRect rect = Cv2.MinAreaRect(srcPt);
Rect box = rect.BoundingRect();
OpenCvSharp.Point2f[] dstPt = new OpenCvSharp.Point2f[4];
stPt[0].X = box.X;dstPt[0].Y = box.Y;dstPt[1].X = box.X + box.Width;dstPt[1].Y = box.Y;dstPt[2].X = box.X + box.Width;dstPt[2].Y = box.Y + box.Height;dstPt[3].X = box.X;dstPt[3].Y = box.Y + box.Height;Mat final = new Mat();Mat warpmatrix = Cv2.GetPerspectiveTransform(srcPt, dstPt);//获得变换矩阵Cv2.WarpPerspective(image, final, warpmatrix, image.Size());//投射变换,将结果赋给finalRect roi = new Rect(box.X, box.Y, box.Width, box.Height);//坐标 x,y 尺寸 长宽Mat croppedImage = new Mat(final, roi);for (int i = 0; i < 4; i++){// 设置目标图像的四个顶点坐标Cv2.PutText(image, "A" + i, new Point(dstPt[i].X, dstPt[i].Y), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 255), 2, LineTypes.Link4);}

 

两个坐标点顺序不一样,对齐坐标顺序,进行透视坐标转换

 

 //5、透视转换OpenCvSharp.Point2f[] srcPt = new OpenCvSharp.Point2f[4];srcPt[0] = approx[0];srcPt[1] = approx[3];srcPt[2] = approx[2];srcPt[3] = approx[1];RotatedRect rect = Cv2.MinAreaRect(srcPt);Rect box = rect.BoundingRect();OpenCvSharp.Point2f[] dstPt = new OpenCvSharp.Point2f[4];dstPt[0].X = box.X;dstPt[0].Y = box.Y;dstPt[1].X = box.X + box.Width;dstPt[1].Y = box.Y;dstPt[2].X = box.X + box.Width;dstPt[2].Y = box.Y + box.Height;dstPt[3].X = box.X;dstPt[3].Y = box.Y + box.Height;Mat final = new Mat();

六、透视变换显示

Mat warpmatrix = Cv2.GetPerspectiveTransform(srcPt, dstPt);//获得变换矩阵
Cv2.WarpPerspective(image, final, warpmatrix, final.Size());//投射变换,将结果赋给final
Cv2.ImShow("透视矫正图像", final);

 通过掌握这六个步骤,你可以在C#中使用OpenCvSharp实现透视矫正。祝你成功!

这篇关于c# OpenCvSharp透视矫正六步实现透视矫正(八)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/538501

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

C# 中变量未赋值能用吗,各种类型的初始值是什么

对于一个局部变量,如果未赋值,是不能使用的 对于属性,未赋值,也能使用有系统默认值,默认值如下: 对于 int 类型,默认值是 0;对于 int? 类型,默认值是 null;对于 bool 类型,默认值是 false;对于 bool? 类型,默认值是 null;对于 string 类型,默认值是 null;对于 string? 类型,哈哈,没有这种写法,会出错;对于 DateTime 类型,默

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议

C#中,decimal类型使用

在Microsoft SQL Server中numeric类型,在C#中使用的时候,需要用decimal类型与其对应,不能使用int等类型。 SQL:numeric C#:decimal

python实现最简单循环神经网络(RNNs)

Recurrent Neural Networks(RNNs) 的模型: 上图中红色部分是输入向量。文本、单词、数据都是输入,在网络里都以向量的形式进行表示。 绿色部分是隐藏向量。是加工处理过程。 蓝色部分是输出向量。 python代码表示如下: rnn = RNN()y = rnn.step(x) # x为输入向量,y为输出向量 RNNs神经网络由神经元组成, python