OpenCvSharp-轮廓匹配/模板查找1.0(附源码)

目录

前言:

 一、函数讲解:

图像阈值处理:Cv2.Threshold()

查找轮廓 Cv2.FindContours()

最小外接矩形 Cv2.BoundingRect();

绘制轮廓 Cv2.DrawContours()

 计算轮廓相似度 Cv2.MatchShapes()

二、代码(教学注释详细,仔细阅读)

三、代码过程总结:


前言:

轮廓匹配是一种计算机视觉技术,用于在图像中查找和比较目标轮廓与待匹配轮廓之间的相似度

 一、函数讲解:

图像阈值处理:Cv2.Threshold()

用于将图像中的像素值根据阈值分成两个不同的区域,可以用来实现图像的分割、边缘检测等任务。

Cv2.Threahold(Mat src, Mat dst ,double thresh, double maxval, ThresholdTypes type)
  • src: 输入的源图像,通常是一个单通道灰度图像。
  • dst: 输出的目标图像,与源图像具有相同的尺寸和类型。
  • thresh: 阈值,用于将图像中的像素值进行分类。
  • maxval: 阈值之后的像素值要设置的新值。
  • type: 阈值处理的类型,有不同的处理方式,比如二进制阈值、反二进制阈值、截断阈值等。

常见的阈值处理类型包括:

  • ThresholdTypes.Binary: 如果像素值大于等于阈值,则设置为 maxval,否则为 0。
  • ThresholdTypes.BinaryInv: 如果像素值小于阈值,则设置为 maxval,否则为 0。
  • ThresholdTypes.Trunc: 如果像素值大于等于阈值,则保持原值,否则截断为阈值。
  • ThresholdTypes.ToZero: 如果像素值大于等于阈值,则保持原值,否则设置为 0。
  • ThresholdTypes.ToZeroInv: 如果像素值小于阈值,则保持原值,否则设置为 0。
  • ThresholdTypes.Otsu大津法,是一种自动确定图像二值化阈值的方法,它能够将图像的像素分成两个类别,使得类别内方差最小、类别间方差最大。这个方法非常适用于背景与前景之间对比明显的图像。
  • ThresholdTypes.Triangle:三角法,基于图像直方图的阈值选择方法,通过寻找直方图中的一条直线,将直方图分成两个部分,使得两个部分之间的面积最小,从而得到阈值。

Point[][] contours:二维数组表示多个轮廓,每个轮廓由一组点坐标组成,因此 contours变量 存储了多个轮廓。

HierarchyIndex[] hierarchy :用hierarchy变量存储轮廓之间拓扑关系的数据结构

查找轮廓 Cv2.FindContours()

返回一组轮廓数组 contours和轮廓的拓扑结构hierarchy

Point[][] contours; // 存储轮廓的点坐标数组
HierarchyIndex[] hierarchy; // 存储轮廓之间的拓扑关系

Cv2.FindContours(
    input: binaryImage, // 二值化图像,白色像素表示物体,黑色像素表示背景
    contours: out contours, // 存储找到的轮廓点坐标
    hierarchy: out hierarchy, // 存储轮廓之间的拓扑关系
    mode: RetrievalModes.External, // 轮廓检索模式,这里表示只检索外部轮廓
    method: ContourApproximationModes.ApproxNone // 轮廓逼近方法,这里表示不逼近轮廓
);
  • input: 二值化图像,即图像中的物体被标记为白色,背景被标记为黑色。
  • contours: 用于存储找到的轮廓的点坐标数组。每个轮廓由一组点构成。
  • hierarchy: 用于存储轮廓之间的拓扑关系,例如父子关系、前后关系等。
  • mode: 轮廓检索模式,可以是 RetrievalModes.List(检索所有轮廓)或 RetrievalModes.External(只检索外部轮廓)等。
  • method: 轮廓逼近方法,可以是 ContourApproximationModes.ApproxNone(不逼近轮廓)、ContourApproximationModes.ApproxSimple(简化轮廓)等。

最小外接矩形 Cv2.BoundingRect();

Rect 变量名 = Cv2.BoundingRect(InputArray points);

 points 是输入的轮廓点集,可以是一个 Point[]Mat

  返回一个 Rect 对象,表示计算得到的最小外接矩形。矩形由左上角坐标 (x, y) 和矩形的宽度和  高度 (width, height) 组成。

绘制轮廓 Cv2.DrawContours()

void Cv2.DrawContours(Mat image, IEnumerable<IEnumerable<Point>> contours, int contourIdx, Scalar color, int thickness = 1, LineTypes lineType = LineTypes.Link8, Mat? hierarchy = null, int maxLevel = int.MaxValue, Point? offset = null);
  • image:目标图像,轮廓将绘制在这个图像上。
  • contours:要绘制的轮廓列表,可以是一个包含 Point 数组的集合。
  • contourIdx:要绘制的轮廓的索引。如果为负数,则绘制所有轮廓。
  • color:绘制轮廓的颜色。
  • thickness:轮廓线的宽度。 其余参数为默认

 计算轮廓相似度 Cv2.MatchShapes()

double Cv2.MatchShapes(InputArray contour1, InputArray contour2, ContourMatchModes method, double parameter = 0);
  • contour1:第一个轮廓的点集,可以是一个 Point[]Mat
  • contour2:第二个轮廓的点集,可以是一个 Point[]Mat
  • method:计算相似性的方法,可以是 ContourMatchModes 枚举中的一个选项。
  • parameter:计算方法所需的参数。

返回值:该方法返回一个 double 类型的相似性度量值,用于表示两个轮廓之间的相似性。值越小,表示形状越相似。

二、代码(教学注释详细,仔细阅读)

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace 轮廓匹配查找模板
{
    class Program
    {
        static void Main(string[] args)
        {
            //读取图像
            Mat template = Cv2.ImRead("C:/Users/CGW/source/repos/轮廓匹配查找模板_Color Space/轮廓匹配查找模板_Color Space/imgs/0.bmp"); //读取模板图像
            Mat imgTest = Cv2.ImRead("C:/Users/CGW/source/repos/轮廓匹配查找模板_Color Space/轮廓匹配查找模板_Color Space/imgs/4.bmp"); //读取测试图像

            Mat grayTemp = new Mat(); // 模板图像
            Mat grayTest = new Mat(); // 测试图像

            //转换为灰度图
            Cv2.CvtColor(template, grayTemp, ColorConversionCodes.BGR2GRAY);
            Cv2.CvtColor(imgTest, grayTest, ColorConversionCodes.BGR2GRAY);

            //二值化--分割轮廓区域
            Cv2.Threshold(grayTemp, grayTemp, 90, 255, ThresholdTypes.Binary);
            Cv2.Threshold(grayTest, grayTest, 90, 255, ThresholdTypes.Binary);

            Point[][] contours; // 存储轮廓的变量
            HierarchyIndex[] hierarchy; // 存储轮廓拓扑结构的变量

            // 使用 FindContours 函数查找图像中的轮廓,返回一组轮廓数组 contours,同时还可以获得轮廓的拓扑结构。
            Cv2.FindContours(grayTemp, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone);

            int index = 0; // 模板中十字轮廓的轮廓序号
            //遍历每个轮廓
            for (int i = 0; i < contours.Length; i++)
            {
                // 获取轮廓的外接矩形
                Rect rect = Cv2.BoundingRect(contours[i]);

                // 判断轮廓是否满足条件,比如宽度和高度都大于80像素
                if (rect.Width > 80 && rect.Height > 80)
                {
                    index = i; // 记录找到的目标轮廓的索引
                    // 在模板图像上绘制找到的目标轮廓,标记为红色
                    Cv2.DrawContours(template, contours, i, new Scalar(0, 0, 255), -1);
                    break; // 找到目标轮廓后跳出循环
                }
            }
            Cv2.ImShow("template", template);

            //遍历测试图像中的轮廓做轮廓匹配
            Point[][] contours2; //轮廓查找结果变量
            HierarchyIndex[] hierarchy2; //轮廓拓扑结构变量

            Cv2.FindContours(grayTest, out contours2, out hierarchy2, RetrievalModes.External,
                                            ContourApproximationModes.ApproxNone);

            //Console.WriteLine("contour2_size = {0}", contours2.Length); //输出轮廓个数
            for (int i = 0; i < contours2.Length; i++)
            {
                Rect rect = Cv2.BoundingRect(contours2[i]);

                //宽高与模板轮廓宽高相符的才做轮廓匹配,剔除干扰轮廓
                if (rect.Width >= 80 && rect.Width <= 100 && rect.Height > 80 && rect.Height <= 100) //找到目标轮廓,跳出循环
                {
                    // 计算轮廓匹配值
                    double matchValue = Cv2.MatchShapes(contours[index], contours2[i], ShapeMatchModes.I3);
                    // 输出匹配值
                    Console.WriteLine("matchRate = {0}", matchValue);
                    // 如果匹配值在一定阈值内,绘制匹配的轮廓
                    if (matchValue <= 2)
                        Cv2.DrawContours(imgTest, contours2, i, new Scalar(0, 255, 0), -1);
                }
            }
            Cv2.ImShow("match-result", imgTest);
            Cv2.WaitKey(0);
        }
    }
}

三、代码过程总结:

  • 读取模板图像和测试图像。
  • 创建存储灰度模板和测试图像的变量 grayTempgrayTest
  • 将图像转换为灰度图像。
  • 对模板图像和测试图像进行二值化处理,将图像中的轮廓区域分割出来。
  • 定义存储轮廓结果和拓扑结构的变量 contourshierarchy
  • 使用 Cv2.FindContours 在模板图像中查找轮廓,存储在 contours 中,同时也获取轮廓的拓扑结构。
  • 遍历 contours 数组,找到满足条件的目标轮廓(这里是宽度和高度都大于80像素),在模板图像上绘制目标轮廓。
  • 使用 Cv2.ImShow 显示带有标记的模板图像。

猜你喜欢

转载自blog.csdn.net/m0_55074196/article/details/132492555
今日推荐