C# opencv多模板匹配实战应用例程

news2024/11/15 12:59:43

C# 多模板匹配例程

最近在做项目的时候为了检测某一种物品的齐套性,以及为了和写c#的软件负责人配合自己研究了一下opnencv C# 版的模板匹配,对基础的例程做了一下改进,留一份例程。


因为工作性质原因不能直接放项目的实际图片我用visio简单绘制了一个图片,最终结果如下。
请添加图片描述
在看代码之前滤清一下需求,目的是寻找到图像中目标的个数,这好像听起来很简单,但是实际上我们需要经过一个对模板匹配算法输出的相似度值进行一个分析的过程。

环境配置

首先就是C# opnecv 的环境配置如何安装opencv库
在这里插入图片描述
很简单只需要右键解决方案的管理解决方案的程序包然后搜索下载即可。

代码实战注释

我们使用如下图片作为模板
请添加图片描述
我们实现的功能是寻找图像中和模板图形相似的图像的数量
为了方便使用我将代码封装成了一个函数
在使用时可以直接调用函数即可吗,具体代码在文末给出,先讲一下不同参数之间的变化

recoganize(String srcImg_path, String tempImg_path, String save_path,double threshold = 0.5,double compressed = 1,string name = "face", int space = 10)
  • srcImg_path要被匹配的图像的图像
  • tempImg_path模板图像
  • save_path存储结果的路径
  • threshold置信度阈值
  • compressed被匹配图像和模板图像在运算时压缩的比例
  • name模板的类别名称
  • space临近抑制长度(绝对值距离)

首先是观察一下阈值改变的效果先设置阈值为0.75

recoganize(String srcImg_path, String tempImg_path, String save_path,double threshold = 0.75,double compressed = 1,string name = "face", int space = 10)

在这里插入图片描述
在这里插入图片描述
然后设置阈值为0.5

recoganize(String srcImg_path, String tempImg_path, String save_path,double threshold = 0.5,double compressed = 1,string name = "face", int space = 10)

在这里插入图片描述
在这里插入图片描述
接下来改变运行时模板和图片的压缩比例观察一下两者的区别,首先是图像变小了那变小有什么用呢

recoganize(String srcImg_path, String tempImg_path, String save_path,double threshold = 0.5,double compressed = 0.5,string name = "face", int space = 10)

在这里插入图片描述
我们可以观察一下两者的运行时间

当compressed为1时,识别时间为236毫秒
在这里插入图片描述
当compressed为0.5时运行时间173毫秒,当图片特别大检测项多时图像压缩是一个非常好的提升效率的方法
在这里插入图片描述
接下来我们研究一下space参数临近抑制我们将space设置为0

recoganize(String srcImg_path, String tempImg_path, String save_path,double threshold = 0.5,double compressed = 1,string name = "face", int space = 0)

结果如下发现数量不对了,那是因为什么,查看图像发现他会在某些图像周围画好几个框因此影响了算法的判断,所以要设置两个框之间的最小间隔所以spece参数起到的就是这个作用
在这里插入图片描述

在这里插入图片描述
face 就是类别名可以通过修改这个变量实现更改上方的提示元素
在这里插入图片描述

实际代码

using OpenCvSharp;
//缩放值减少运算量
String tempImg_path = (@"C:\Users\86176\Desktop\csharp 多模板匹配例程\model.jpg"); //改成自己的
String srcImg_path = (@"C:\Users\86176\Desktop\csharp 多模板匹配例程\picture.jpg"); //改成自己的
String save_path = (@"C:\Users\86176\Desktop\csharp 多模板匹配例程\roi.bmp"); //改成自己的

recoganize(srcImg_path, tempImg_path,save_path,0.5, 1, "face",10);

void recoganize(String srcImg_path, String tempImg_path, String save_path,double threshold = 0.5,double compressed = 0.5,string name = "face", int space = 10)
{
    DateTime beginTime = DateTime.Now;            //获取开始时间  
    // 新建图变量并分配内存
    Mat srcImg = new Mat();
    // 读取要被匹配的图像
    srcImg = Cv2.ImRead(srcImg_path);
    // 更改尺寸
    Cv2.Resize(srcImg, srcImg, new Size((int)srcImg.Cols * compressed, (int)srcImg.Rows * compressed));
    // 初始化保存保存匹配结果的横纵坐标列表
    List<int> Xlist = new List<int> { };
    List<int> Ylist = new List<int> { };
    
    int order = 0;
    Mat tempImg = Cv2.ImRead(tempImg_path);
    Cv2.Resize(tempImg, tempImg, new Size((int)tempImg.Cols * compressed, (int)tempImg.Rows * compressed));
    Mat result = srcImg.Clone();

    int dstImg_rows = srcImg.Rows - tempImg.Rows + 1;
    int dstImg_cols = srcImg.Cols - tempImg.Cols + 1;
    Mat dstImg = new Mat(dstImg_rows, dstImg_cols, MatType.CV_32F, 1);
    Cv2.MatchTemplate(srcImg, tempImg, dstImg, TemplateMatchModes.CCoeffNormed);
    
    //Cv2.ImShow("match", dstImg);

    int count = 0;
    for (int i = 0; i < dstImg_rows; i++)
    {
        for (int j = 0; j < dstImg_cols; j++)
        {
            float matchValue = dstImg.At<float>(i, j);
            if (matchValue >= threshold && Xlist.Count ==0)
            {
                count++;
                Cv2.Rectangle(result, new Rect(j, i, tempImg.Width, tempImg.Height), new Scalar(0, 255, 0), 2);
                Cv2.PutText(result, name, new Point(j, i-(int)20*compressed), HersheyFonts.HersheySimplex, 0.5, new Scalar(0, 0, 0), 1);
                Xlist.Add(j);
                Ylist.Add(i);
            }

            
            if (matchValue >= threshold && Xlist.Count != 0)
            {
                for(int q = 0; q<Xlist.Count; q++)
                {
                    if (Math.Abs(j - Xlist[q]) + Math.Abs(i - Ylist[q]) < space)
                    {
                        order = 1;
                        break;
                    }
                }
                if (order != 1)
                {
                    count++;
                    Cv2.Rectangle(result, new Rect(j, i, tempImg.Width, tempImg.Height), new Scalar(0, 255, 0), 2);
                    Cv2.PutText(result, name, new Point(j, i - (int)20 * compressed), HersheyFonts.HersheySimplex, 0.5, new Scalar(0, 0, 0), 1);
                    Xlist.Add(j);
                    Ylist.Add(i);
                }
                order = 0;
            }
        }
    }
    Console.WriteLine("目标数量:{0}", count);
    Cv2.ImShow("result", result);
    Cv2.ImWrite(save_path,result);
    DateTime endTime = DateTime.Now;              //获取结束时间  
    TimeSpan oTime = endTime.Subtract(beginTime); //求时间差的函数  
    Console.WriteLine("程序的运行时间:{0} 毫秒", oTime.TotalMilliseconds);
    Cv2.WaitKey(0);

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/171957.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我的个人微信也迅速接入了 ChatGPT

本文主要来聊聊如何快速使用个人微信接入 ChatGPT&#xff0c;欢迎 xdm 尝试起来&#xff0c;仅供学习参考&#xff0c;切莫用于做不正当的事情 关于 ChatGPT 我们每个人都可以简单的使用上&#xff0c;不需要你有很强的技术背景&#xff0c;不需要你有公众号&#xff0c;甚至…

Chat GPT 创建APP: 开发人员要被替代了吗?

我们又要被人工智能取代了吗&#xff1f;GitHub Copilot 于 2021 年 10 月发布&#xff0c;整个开发社区都为之疯狂。有些人发表言论说我们很快就会失业&#xff0c;而其他人&#xff08;比如我&#xff09;&#xff0c;认为虽然这个工具很有趣&#xff0c;但距离替代人工还很远…

【Django框架】——25 Django视图 07 状态保持Session

文章目录1.session流程图2.session语法与案例3.session配置cookie不安全&#xff0c;会把所有敏感数据放到浏览器保存。 session是把敏感数据存到自己的服务器中给浏览器一把钥匙就行了&#xff08;是基于cookie完成的&#xff09;。 Django 提供对匿名会话(session)的完全支…

Cisco Packet Tracer 8.2.x Crack

Cisco Packet Tracer 是一个网络模拟器。有了这款功能强大的软件&#xff0c;用户可以在模拟和安全的环境中学习所有网络主题&#xff0c;而无需花费很多钱。它是网络主题模拟和培训领域中最受欢迎的应用程序之一&#xff0c;因为它提供了这样做所需的所有功能。Packet Tricer …

Java方法(函数)

文章目录Java方法(函数)一、方法介绍二、方法的定义和调用格式1. 快速入门2. Debug查看方法的执行流程3. 方法调用内存图解4. 带参数方法的定义和调用1&#xff09;定义和调用格式2&#xff09;形参和实参5. 带返回值方法的定义和调用6. 方法通用定义格式三、方法常见问题四、方…

MIPI 摄像头的原理

1. 摄像头sensor 的原理 定时脉冲生成器会生成clock&#xff0c;用于访问image sensor 阵列中的行&#xff0c;预充电&#xff0c;并且按顺序采样像素阵列中的所有行。在一个行的预充电和采样的时间段里&#xff0c;像素的电荷量会随着曝光时间而逐渐减少。这就是快门结构中的曝…

擎创技术流 | ClickHouse实用工具—ckman教程(10)

一、前言 哈喽~友友们&#xff0c;转眼农历新年就在眼前&#xff0c;ckman系列也终于迎来了最后一期&#xff0c;非常感谢大家的喜欢&#xff0c;让up主有动力做完这个系列&#xff0c;也感谢一路走来&#xff0c;大家给予的反馈&#xff0c;让这个系列越做越好。 接下来&…

4-Spring使用

目录 1.存储Bean对象到Spring容器中 1.1.创建Bean 1.2.将Bean注册到Spring容器中 1.2.1.第一次存储Bean&#xff08;可选&#xff0c;如果是第二次及以后&#xff0c;此步骤忽略&#xff09; 1.2.2.添加Bean标签 2.从Spring容器中获取并使用Bean对象 2.1.创建Spring上下…

剑指 Offer 04. 二维数组中的查找 [C语言]

目录题目思路代码结果该文章只是用于记录考研复试刷题题目 在一个 n * m 的二维数组中&#xff0c;每一行都按照从左到右 非递减 的顺序排序&#xff0c;每一列都按照从上到下 非递减 的顺序排序。请完成一个高效的函数&#xff0c;输入这样的一个二维数组和一个整数&#xff…

[leetcode 1723] 完成所有工作的最短时间

题目 题目&#xff1a;https://leetcode.cn/problems/find-minimum-time-to-finish-all-jobs/description/ 该题和 [leetcode 2305] 公平分发饼干 完全相同。 解法 回溯剪枝 感觉和 [leetcode 198] 划分为k个相等的子集 有点相似&#xff0c;这题更像是划分为k个尽量相等的子…

easypoi 模板导入、导出合并excel单元格功能

easypoi 模板导入、导出合并单元格功能 参考&#xff1a; java使用poi读取跨行跨列excel springboot集成easypoi并使用其模板导出功能和遇到的坑 Easypoi Excel模板功能简要说明 easypoi 模板导出兼容合并单元格功能 ExcelUtil package com.yymt.utils;import cn.aftertu…

linux系统中利用QT实现环境传感器的数据获取方法

大家好&#xff0c;今天主要和大家分享一下&#xff0c;如何使用QT实现对三合一环境传感器的数据的获取和实现。 目录 第一&#xff1a;资源介绍 第二&#xff1a;具体代码的详细实现 第三&#xff1a;源文件“mainwindow.h”实现 第四&#xff1a;Linux应用接口获取数据 第…

大趋势:科技赋能产业

能整合传统产业资源的老板大优势&#xff01; 三大趋势&#xff1a; 科技赋能产业链 乡村振兴 文化复兴 纯技术类企业在产业链方面不占优势 趣讲大白话&#xff1a;时势造英雄 ******** 消费互联网竞争太卷了 竞争向产业升级方向转移 向高质量发展导向 乡村振兴是整合分散的集…

容器虚拟化技术Docker(一)简介、安装、常见命令、数据卷、安装常规软件

容器虚拟化技术Docker&#xff08;一&#xff09;简介、安装、常见命令、数据卷、安装常规软件 1、Docker简介 1、简介 Docker的主要目标是“Build&#xff0c;Ship and Run Any App,Anywhere”&#xff0c;也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理&a…

web3:同态加密

web3相关学习一并收录至该博客&#xff1a;web3学习博客目录大全 目录同态加密概念同态加密具体如何定义&#xff1f;主流同态加密算法原理乘法同态加密算法① RSA算法一些基本的数学知识RSA的具体过程秘钥的产生加密解密验证了 RSA 算法的乘法同态性java代码简单实现python代码…

保时捷狂推NFT,高调喊出打造Web3社区,Web2品牌“天生缺陷”终将折戟沉沙?...

图片来源&#xff1a;由无界 AI 绘画工具生成2023年1月&#xff0c;保时捷中国的公关团队“忙疯”了&#xff0c;一连搞了好几个活动。有展览&#xff0c;媒体连线直播&#xff0c;甚至搞起了一场有圆桌&#xff0c;有嘉宾主题演讲的发布会。目的只有一个&#xff0c;告诉中国用…

6、Ubuntu20的JDKMySQLtomcatRedisNginx安装

安装JDK 这里以安装版本8为例 进入存放jdk目录创建目录 cd /usr/local mkdir jdk cd jdk 把下好的jdk8压缩包拖拽到Ubuntu连接用户下 移动jdk包文件 mv /home/starfish/jdk-8u351-linux-x64.tar.gz . 解压jdk tar -zxvf jdk-8u351-linux-x64.tar.gz cd jdk1.8.0_351/ p…

ubuntu20.04安装搜狗sogou输入法

环境 Ubuntu20.04 Sogou拼音输入法安装过程 Step.1 安装fcitx框架 sudo apt-get update sudo apt-get install fcitx输入winA后&#xff0c;打开Languate Support Keyboard input method system中&#xff0c;选择fcitx 点击Install/RemoveLanguates...&#xff0c;选择Ch…

面向物流行业的文档管理系统

用于运输和物流的 DocuWare 文档管理软件 物流和货运行业的效率激烈战在公路、火车、货船和空中展开。DocuWare 的快速、安全和灵活的文档管理是真正的竞争优势。在您的公司和客户的核心流程中节省新的成本和时间。 一、数字化和文档管理软件改变了物流公司的游戏规则 智能链…

PostgreSQL 技术内幕(五)Greenplum-Interconnect模块

Greenplum是在开源PostgreSQL的基础上&#xff0c;采用MPP架构的关系型分布式数据库。Greenplum被业界认为是最快最具性价比的数据库&#xff0c;具有强大的大规模数据分析任务处理能力。 Greenplum采用Shared-Nothing架构&#xff0c;整个集群由多个数据节点&#xff08;Segm…