OpencvForUnity 对图像中A4纸的提取

2023-10-08 15:10

本文主要是介绍OpencvForUnity 对图像中A4纸的提取,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近在撸一个unity小程序,要用到自动识别纸张,然后就找了一些相关资料,刚开始准备用C# Aforge类库来做图像处理,然而并不适合我,也许是我掌握不到精髓,最后选择用OpencvForUnity来做。
废话一大堆,直接进入正题…
先贴几个可能用得到API原型:

void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false)
//InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
//OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。
//double类型的threshold1,第一个滞后性阈值【低阈值】。值越大,找到的边缘越少     
//double类型的threshold2,第二个滞后性阈值【高阈值】。
//int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3。
//bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。
//低于阈值1的像素点会被认为不是边缘;
//高于阈值2的像素点会被认为是边缘;void convexHull(InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true)
//第一个参数,InputArray类型的Points,输入的二维点集,可以填Mat类型或者std::vector
//第二个参数,OutputArray类型的Hull,输出参数,函数调用后找到的凸包
//第三个参数,bool类型的clockwise,操作方向标识符。当此标志符为真时,输出的凸包为顺时针方向,否则就为逆时针方向。并且是假定坐标系的x轴指向右,y轴指向上方void findContours(InputOutArray image,OutputArrayOfArrays contours,outputArray hierarchy,int method,Point offset = Point())
//第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类对象即可,且需为8位单通道图像
//第二个参数,OutputArrayOfArrays类型的contours,检测到的轮廓、函数调用后的运算结果存在这里。每一个轮廓存储为一个点向量,即用point类型的vector表示
//第三个参数,outputArray类型的hierarchy,可选的输出量,包含图像的拓扑信息
//第四个参数,int类型的mode,轮廓检索模式,取值有RETR_EXTERNAL、RETR_LIST、RETR_CCOMP、RETR_TREE
//第五个参数,int类型的method,为轮廓的近似办法,取值有CHAIN_APPROX_NONE、CHAIN_APPROX_SIMPLE、CHAIN_APPROX_TC89_L1、CHAIN_APPROX_TC89_KCOSvoid drawContours(InputOutputArray image,InputArrayOfArrays contours,int contourIdx,const Scalar& color,int thickness = 1,int lineType = 8,inputArray hierarchy = noArray(),int maxLevel = INT_MAX,Point offset = Point())
//第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类对象即可
//第二个参数,OutputArrayOfArrays类型的contours,所有的输入轮廓。每一个轮廓存储为一个点向量,即用point类型的vector表示
//第三个参数,int类型的contourIdx,轮廓绘制的指示变量。如果其为负值,则绘制所有轮廓
//第四个参数,constScalar&类型的color,轮廓的颜色
//第五个参数,int thickness,轮廓线条的粗细,有默认值1
//第六个参数,int类型的lineType,线条的类型,有默认值8
//第七个参数,InputArray类型的hierarchy,可选的层次结构信息,有默认值noArray()
//第八个参数,int类型的maxLevel,表示用于绘制轮廓的最大等级,有默认值INT_MAX

基本思路:

  1. 图像的预处理

  2. 边缘检测Canny提取轮廓,dilate膨算法(不使用可能导致有些轮廓无法闭合)

  3. 找到轮廓中面积最大的轮廓

  4. 然后得到轮廓的Rect,再从原图中提取出来(对于不是正放的轮廓可以用透视校正,透视变换来提取)

     Mat inputMat = new Mat(inputTexture.height, inputTexture.width, CvType.CV_8UC3);Mat outputMat = new Mat(inputTexture.height, inputTexture.width, CvType.CV_8UC3);Utils.texture2DToMat(inputTexture, inputMat);//灰度化Imgproc.cvtColor(inputMat, outputMat, Imgproc.COLOR_BGR2GRAY);//图片高斯模糊处理Imgproc.GaussianBlur(outputMat, outputMat, new Size(5, 5), 0);//图片二值化处理Imgproc.threshold(outputMat, outputMat, 20, 255, Imgproc.THRESH_BINARY);
    

然后开始对图片进行边缘检测,OpenCV中,和边缘检测相关的算子有索贝尔,拉普拉斯滤波,Canny,Scharr等,这里使用的是Canny算子。

    //边缘检测Imgproc.Canny(outputMat, outputMat, 50, 100);//膨胀算法(尽量使边缘闭合)int ksize = 7;Mat kernel = new Mat(ksize, ksize, CvType.CV_32F);Imgproc.dilate(outputMat, outputMat, kernel);

处理图像之后会得到这种线框图
在这里插入图片描述
现在就要开始对图片的轮廓做处理了

	//寻找轮廓,并找出轮廓中面积最大的(我要提取的是A4纸,基本就是图像中最大的一个闭合轮廓)Imgproc.findContours(outputMat, srcCorners, srcHierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_NONE);for (int i = 0; i < srcCorners.Count; i++){var currentArea = Imgproc.contourArea(srcCorners[i]);if (currentArea > maxArea){maxArea = currentArea;index = i;}}然后可以将轮廓画出来,看看是不是正确的Imgproc.drawContours(inputMat, srcCorners, index, new Scalar(255, 0, 0), 2, 8, srcHierarchy, 0, new Point());

最后就要开始把这个轮廓提取出来了,开始找了很多资料,要用到透视校正,透视变换,然而当我做到这里的时候

    //获得轮廓的凸包//MatOfInt hull = new MatOfInt();//List<Point> points = new List<Point>();//Imgproc.convexHull(srcCorners[index], hull, false);

本来应该提取凸包后 hull.toList().Count这个应该是我要的矩形框的4个点,但是实际情况这个数值远大于4,得不到矩形框的4个角点就无法进行之后的矩阵变换等操作,希望有了解的老铁可以给我点提示,然后相互交流交流。

于是乎在我的不懈努力下找到另外一种方式,就是通过轮廓拟合,然后得到轮廓的Rect(及轮廓在原图中的Rect)来实现

    MatOfPoint2f approx = new MatOfPoint2f();MatOfPoint2f mp2f = new MatOfPoint2f(srcCorners[index].toArray());double prei = Imgproc.arcLength(mp2f, true);//计算轮廓的周长Imgproc.approxPolyDP(mp2f, approx, prei * 0.04, true);//对图像轮廓点进行多边形拟合print(approx.toArray().Length);OpenCVForUnity.CoreModule.Rect rect = Imgproc.boundingRect(srcCorners[index]);

最后输出提取的图基本就是我想得到的效果

	 Mat finalMat = new Mat(inputMat, rect);Texture2D tmpTex = new Texture2D(finalMat.width(), finalMat.height(), TextureFormat.RGBA32, false);Utils.matToTexture2D(finalMat, tmpTex);rawImage.texture = tmpTex;

这次取巧实现了功能,还有很多可以完善的地方,后续会整理一下透视校正,透视变换,把功能更改进一点。

这篇关于OpencvForUnity 对图像中A4纸的提取的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python中提取文件名扩展名的多种方法实现

《Python中提取文件名扩展名的多种方法实现》在Python编程中,经常会遇到需要从文件名中提取扩展名的场景,Python提供了多种方法来实现这一功能,不同方法适用于不同的场景和需求,包括os.pa... 目录技术背景实现步骤方法一:使用os.path.splitext方法二:使用pathlib模块方法三

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

Python对PDF书签进行添加,修改提取和删除操作

《Python对PDF书签进行添加,修改提取和删除操作》PDF书签是PDF文件中的导航工具,通常包含一个标题和一个跳转位置,本教程将详细介绍如何使用Python对PDF文件中的书签进行操作... 目录简介使用工具python 向 PDF 添加书签添加书签添加嵌套书签Python 修改 PDF 书签Pytho

Python+wxPython构建图像编辑器

《Python+wxPython构建图像编辑器》图像编辑应用是学习GUI编程和图像处理的绝佳项目,本教程中,我们将使用wxPython,一个跨平台的PythonGUI工具包,构建一个简单的... 目录引言环境设置创建主窗口加载和显示图像实现绘制工具矩形绘制箭头绘制文字绘制临时绘制处理缩放和旋转缩放旋转保存编

python+OpenCV反投影图像的实现示例详解

《python+OpenCV反投影图像的实现示例详解》:本文主要介绍python+OpenCV反投影图像的实现示例详解,本文通过实例代码图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前言二、什么是反投影图像三、反投影图像的概念四、反向投影的工作原理一、利用反向投影backproj

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB