OpenCVforUnity中的图片轮廓对比——MatchShapesExample案例

OpenCV for Unity(2.32)插件中的MatchShapesExample案例(Unity2018.2.6f1)

位置:OpenCVForUnity\Examples\MainModules\imgproc

目录

一、功能概括

二、场景结构

三、主要功能脚本分析

1 导入标准图形图片

2 导入对比图形图片

3 描边对比图片的轮廓

4 对比两张图片轮廓获取数据


一、功能概括

该案例中实现了图形轮廓描边(红色)、图形轮廓对比(绿色数据)的效果。

 图1.1场景运行效果图

                                      

标准图形 (绿色数据为标准图形与对比图形比较之后获得的数据)

对比图形


二、场景结构

场景中包括四个物体

Cube 立方体主要用来作为展示对比图片的容器,改物体包含实现图形对比的主要脚本。

Main Camera 摄像机

Canvas UI的画布,该案例中主要用来放置Back Button,返回案例列表

EventSystem依附Canvas的必须


三、主要功能脚本分析

场景中只有Cube物体上有Script,其中TouchController脚本是控制鼠标点击控制立方旋转的,MatchShapesExample脚本为主要功能脚本

MatchShapesExmple中轮廓描边、图形对比在Start()中完成

1 导入标准图形图片

//srcMat
            Texture2D srcTexture = Resources.Load ("matchshapestest") as Texture2D;
            Mat srcMat = new Mat (srcTexture.height, srcTexture.width, CvType.CV_8UC1);
            Utils.texture2DToMat (srcTexture, srcMat);
            Debug.Log ("srcMat.ToString() " + srcMat.ToString ());
            Imgproc.threshold (srcMat, srcMat, 127, 255, Imgproc.THRESH_BINARY);

首先定义Texture变量存放图片,Resources.Load导入的图片是放在Resource文件夹下的,且需要修改图片为可读写(write/read)模式,如下图

之后需要将Texture个是转换为Mat格式。

  • Mat (int rows, int cols, int type)

type的值

//【1】CV_8UC1---则可以创建----8位无符号的单通道---灰度图片------grayImg

//【2】CV_8UC3---则可以创建----8位无符号的三通道---RGB彩色图像---colorImg

//【3】CV_8UC4--则可以创建-----8位无符号的四通道---带透明色的RGB图像

参考网址:https://blog.csdn.net/maweifei/article/details/51221259

Imgproc.threshold将图片二值化处理

  • Imgproc.threshold(Mat src,Mat dst,double thresh,double maxval,int type)

type

如果是THRESH_BINARY的话,就是二值化,从thresh为阈值进行判断每个像素点该归maxval还是0。

如果是THRESH_BINARY_INV的话,是反向二值化,从图中也可以看的出来,跟THRESH_BINARY是相反的。

如果是THRESH_TRUNC的话,trunc的意思是裁剪、修剪的意思,那么就是超过thresh的都等于tresh,不超过的等于原图像素点值。只针对超过thresh的像素点。

如果是THRESH_TOZERO的话,大于tresh的像素点维持原图像素值,小于的都为0。

如果是THRESH_TOZERO_INV的话,与4相反。

参考网址:https://blog.csdn.net/getyouwant/article/details/49717411

2 导入对比图形图片

//dstMat
            Texture2D dstTexture = Resources.Load ("matchshapestest") as Texture2D;
            Mat dstMat = new Mat (dstTexture.height, dstTexture.width, CvType.CV_8UC3);
            Utils.texture2DToMat (dstTexture, dstMat);
            Debug.Log ("dstMat.ToString() " + dstMat.ToString ());

3 描边对比图片的轮廓

 List<MatOfPoint> srcContours = new List<MatOfPoint> ();
            Mat srcHierarchy = new Mat ();

            /// Find srcContours
            Imgproc.findContours (srcMat, srcContours, srcHierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_NONE);

            Debug.Log ("srcContours.Count " + srcContours.Count);
            
            for (int i=0; i<srcContours.Count; i++) {
                Imgproc.drawContours (dstMat, srcContours, i, new Scalar (255, 0, 0), 2, 8, srcHierarchy, 0, new Point ());
            }

findContours方法查找图像轮廓drawContours绘制图像轮廓,drawContours方法描边轮廓

  • findContours (Mat image, List<MatOfPoint> contours, Mat hierarchy, int mode, int method)

image:输入图像,图像必须为8-bit单通道图像,图像中的非零像素将被视为1,0像素保留其像素值,故加载图像后会自动转换为二值图像。我们同样可以使用cv::compare,cv::inRange,cv::threshold,cv::adaptiveThreshold,cv::Canny等函数来创建二值图像,,如果第四个参数为cv::RETR_CCOMP或cv::RETR_FLOODFILL,输入图像可以是32-bit整型图像(CV_32SC1)

contours:检测到的轮廓,每个轮廓都是以点向量的形式进行存储即使用point类型的vector表示

hierarchy:可选的输出向量(std::vector),包含了图像的拓扑信息,作为轮廓数量的表示hierarchy包含了很多元素,每个轮廓contours[i]对应hierarchy中hierarchy[i][0]~hierarchy[i][3],分别表示后一个轮廓,前一个轮廓,父轮廓,内嵌轮廓的索引,如果没有对应项,则相应的hierarchy[i]设置为负数。

mode轮廓检索模式,

RETR_EXTERNAL:表示只检测最外层轮廓,对所有轮廓设置hierarchy[i][2]=hierarchy[i][3]=-1

RETR_LIST:提取所有轮廓,并放置在list中,检测的轮廓不建立等级关系

RETR_CCOMP:提取所有轮廓,并将轮廓组织成双层结构(two-level hierarchy),顶层为连通域的外围边界,次层位内层边界

RETR_TREE:提取所有轮廓并重新建立网状轮廓结构

RETR_FLOODFILL:官网没有介绍,应该是洪水填充法

method值:

CHAIN_APPROX_NONE:获取每个轮廓的每个像素,相邻的两个点的像素位置差不超过1

CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,值保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息

CHAIN_APPROX_TC89_L1和CHAIN_APPROX_TC89_KCOS使用Teh-Chinl链逼近算法中的一种

  • drawContours (Mat image, List<MatOfPoint> contours, int contourIdx, Scalar color, int thickness, int lineType, Mat hierarchy, int maxLevel, Point offset)

image:输入输出图像,Mat类型即可

contours:使用findContours检测到的轮廓数据,每个轮廓以点向量的形式存储,point类型的vector

contourIdx:绘制轮廓的只是变量,如果为负值则绘制所有输入轮廓

color:轮廓颜色

thickness:绘制轮廓所用线条粗细度,如果值为负值,则在轮廓内部绘制

lineTpye:线条类型,有默认值LINE_8,有如下可选类型

hierarchy:可选层次结构信息

maxLevel:用于绘制轮廓的最大等级

offset:可选轮廓参数,用制定偏移量offset=(dx, dy)给出绘制轮廓的偏移量

参考网址:https://blog.csdn.net/keith_bb/article/details/70185209

4 对比两张图片轮廓获取数据

for (int i=0; i<srcContours.Count; i++) {
                double returnVal = Imgproc.matchShapes (srcContours [2], srcContours [i], Imgproc.CV_CONTOURS_MATCH_I1, 0);
                Debug.Log ("returnVal " + i + " " + returnVal);

                Point point = new Point ();
                float[] radius = new float[1];
                Imgproc.minEnclosingCircle (new MatOfPoint2f (srcContours [i].toArray ()), point, radius);
                Debug.Log ("point.ToString() " + point.ToString ());
                Debug.Log ("radius.ToString() " + radius [0]);
                
                Imgproc.circle (dstMat, point, 5, new Scalar (0, 0, 255), -1);
                Imgproc.putText (dstMat, " " + returnVal, point, Core.FONT_HERSHEY_SIMPLEX, 0.4, new Scalar (0, 255, 0), 1, Imgproc.LINE_AA, false);
            }

遍历srcContours列表中的轮廓与srcContours[1]进行比较

srcContours数组index对应轮廓  

  • matchShapes (Mat contour1, Mat contour2, int method, double parameter)

contour1 第一个轮廓或者灰度图像

contour2第二个轮廓或者灰度图像

method 比较的方法CV_CONTOURS_MATCH_I1 , CV_CONTOURS_MATCH_I2 or CV_CONTOURS_MATCH_I3 (see the details below).

Parameter 方法的具体参数(暂不支持)

参考网址:

https://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=matchshapes#cv2.matchShapes

  • minEnclosingCircle (MatOfPoint2f points, Point center, float[] radius)

计算完全包围已有轮廓最小圆.

Points输入的二维点集

Point center表示输出的圆形的中心坐标,是float型

float[] radius 输出的最小圆半径,是float型

参考网址:

https://blog.csdn.net/qq_18343569/article/details/48000071?utm_source=blogxgwz1

https://blog.csdn.net/huanghuangjin/article/details/80896543

  • circle (Mat img, Point center, int radius, Scalar color, int thickness)

在图像上绘制一个圆形

img Mat对象,表示要在其上绘制圆的图像

Center 代表圆中心的Point对象

Radius 表示圆的半径的整型变量。

color 表示圆的颜色的标量对象(BGR)。

thickness 表示圆的厚度的整数; 默认情况下,厚度值为1。

参考网址:https://www.yiibai.com/opencv/opencv_drawing_circle.html

  • putText (Mat img, string text, Point org, int fontFace, double fontScale, Scalar color, int thickness, int lineType, bool bottomLeftOrigin)

在图像上绘制一个文字

Img Mat对象,表示要在其上绘制文字的图像

Text 文字(不支持中文)

Org 文字的位置

fontFace 字体 OpenCV支持的文字类型

fontScale 缩放

color 颜色

thickness 线宽度

lineType 限类型

bottomLeftOrigin (true)图像数据原点在左下角否则(false)在左上角

参考网址:

https://blog.csdn.net/guduruyu/article/details/68491211

https://blog.csdn.net/ubunfans/article/details/24421981

5 将图片内容赋给cube物体

Texture2D texture = new Texture2D (dstMat.cols (), dstMat.rows (), TextureFormat.RGBA32, false);           
Utils.matToTexture2D (dstMat, texture);         
gameObject.GetComponent<Renderer> ().material.mainTexture = texture;

将mat格式转换成Texture格式赋给cube的mianTexture


                                                                                                                                                                                               (๑′ᴗ‵๑)

 

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值