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

相关文章

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

C#读写文本文件的多种方式详解

《C#读写文本文件的多种方式详解》这篇文章主要为大家详细介绍了C#中各种常用的文件读写方式,包括文本文件,二进制文件、CSV文件、JSON文件等,有需要的小伙伴可以参考一下... 目录一、文本文件读写1. 使用 File 类的静态方法2. 使用 StreamReader 和 StreamWriter二、二进

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu