【原理解密】多角度、多尺度、多目标的边缘模板匹配

学习《OpenCV应用开发:入门、进阶与工程化实践》一书

做真正的OpenCV开发者,从入门到入职,一步到位!

边缘模板匹配的基本原理

OpenCV中自带的模板匹配算法,完全是像素基本的模板匹配,特别容易受到光照影响,光照稍微有所不同,该方法就会歇菜了!搞得很多OpenCV初学者刚学习到该方法时候很开心,一用该方法马上很伤心,悲喜交加,充分感受到了理想与现实的距离,不过没关系,这里介绍一种新的模板匹配算法,主要是基于图像边缘梯度,它对图像光照与像素迁移都有很强的抗干扰能力,在工业应用场景中已经得到广泛使用。基本原理主要是基于梯度跟边缘实现NCC计算与匹配,首先计算梯度:
在这里插入图片描述
然后基于梯度,实现非最大抑制与边缘提取以后,就得到了所有的边缘点集,每个边缘点有三个值,分别是:

x方向梯度、
y方向梯度、
xy方向梯度

然后对输入的每张图像,根据模板图像的每个边缘点计算NCC,得到匹配阈值,开启匹配搜索:
在这里插入图片描述
如果其中任何一个点的匹配阈值小于minScore就停止搜索与匹配当前像素点,继续搜索下一个,直到遍历完成所有像素点,得到匹配得分图像。然后采用跟NCC相似的处理,去重以后得到最终匹配结果。

代码实现与演示

说实话我也不是从零开始的,之前我写过一个版本,但是我发现一个别人写好的一个原始版本,好像是这个算法的作者自己写,基于OpenCV3.x版本完成的,链接如下:

https://github.com/daxiaHuang/edge-template-match/tree/master

同时原始版本 不支持 多角度、多对象、多尺度,所以我在这个上面一通狂改,就让它各种支持了,这个大概花了我三天时间。最终我给他们封装成两个类,配合上Qt C++ 的一个界面,通过点点鼠标即可运行。客户端直接调用API即可,客户端代码如下:

task.initailization(tpl);
double start = (double)cv::getTickCount();
task.detect(target, results);
float time = (((double)cv::getTickCount() - start)) / cv::getTickFrequency();
std::cout << "edge template match execute time: " << time << std::endl;
for (auto item : results) {for (auto pt : item.pts) {cv::circle(result, pt, 1, cv::Scalar(0, 255, 0), 1, 8);}cv::RotatedRect rrt = cv::minAreaRect(item.pts);cv::Point2f minbox[4];rrt.points(minbox);for (int r = 0; r < 4; r++){cv::line(result, minbox[r], minbox[(r + 1) % 4], cv::Scalar(0, 0, 255), 2, 8);}std::cout << "conf: " << item.conf << std::endl;cv::putText(result, cv::format("conf:%.2f, angle:%d", item.conf, item.angle), item.center, cv::FONT_HERSHEY_SIMPLEX, .5, cv::Scalar(255, 0, 0), 1, 8);
}cv::imshow("边缘模板匹配", result);
cv::waitKey(0);

边缘匹配运行结果 - 测试一
在这里插入图片描述
速度测试数据:执行时间: 126.06 ms
在这里插入图片描述
速度测试数据:执行时间: 229.82 ms
在这里插入图片描述
速度测试数据:执行时间: 117.60 ms
在这里插入图片描述
速度测试数据:执行时间: 405.60 ms
最后一张测试目标图像大小为 830x822,目标数目为13

最后说明

演示基于QT + OpenCV C++ 完成,源码购买站内私信博主即可!

好书推荐

《OpenCV应用开发:入门、进阶与工程化实践》全书共计16个章节,重点聚焦OpenCV开发常用模块详解与工程化开发实践,提升OpenCV应用开发能力,助力读者成为OpenCV开发者,同时包含深度学习模型训练与部署加速等知识,帮助OpenCV开发者进一步拓展技能地图,满足工业项目落地所需技能提升。购买请点链接:
《OpenCV4 应用开发-入门、进阶与工程化实践》

学习课程有专属答疑群,负责贴身答疑解惑

读者专属QQ群 :657875553
进群暗号:OpenCV4读者

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

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

相关文章

【剪映】如何使用曲线变速?

如何使用曲线变速 进入视频编辑界面后&#xff0c;选中视频&#xff0c;点击下方工具栏的-【变速】-【曲线变速】&#xff0c;进入后可以看到七个预设变速&#xff0c;其中后六个为系统自带预设变速&#xff0c;每个预设变速效果不同&#xff0c;直接点击这六个预设&#xff0c…

Python一些可能用的到的函数系列124 GlobalFunc

说明 GlobalFunc是算网的下一代核心数据处理基础。 算网是一个分布式网络&#xff0c;为了能够实现真的分布式计算&#xff08;加快大规模任务执行效率&#xff09;&#xff0c;以及能够在很长的时间内维护不同版本的计算方法&#xff0c;需要这样一个对象/服务来支撑。Globa…

如何使用python在三天内制作出一个赛车游戏

制作一个赛车游戏是一个复杂的过程&#xff0c;涉及多个方面&#xff0c;如游戏设计、图形渲染、物理引擎、用户输入处理等。在三天内完成这个任务可能非常具有挑战性&#xff0c;特别是如果你是初学者。但如果你有基本的Python编程知识和一些游戏开发经验&#xff0c;以下是一…

尚硅谷最新Node.js 学习笔记(三)

目录 六、Node.js 模块化 6.1、介绍 什么是模块化与模块&#xff1f; 什么是模块化项目&#xff1f; 模块化好处 6.2、模块暴露数据 模块初体验 暴露数据 6.3、导入&#xff08;引入&#xff09;模块 6.4、导入模块的基本流程 6.5、CommonJS规范 七、包管理工具 7…

Win 10 如何升级 Win 11

方法一&#xff1a; 设置->Windows 更新->检查更新 然后会有许多要下载更新的&#xff0c;期间会要求多次重启&#xff0c;每次重启完之后再检查更新&#xff0c;直到显示是最新&#xff0c;然后一般会有一个Win11的入口&#xff0c;点这里就可以了。 我很久之前升的&…

Java-数组遍历

for循环遍历 具体描述 假设有一个数组nums,设置初始条件i0,即从数组的第一个开始,循环结束条件为i<nums.length,即数组中所有元素的数量&#xff0c;设置更新条件i,即依次遍历完数组中所有元素 实例&#xff1a; public class demo04 {public static void main(String[]…

2019年全年回顾

本文于2020年Q1完成&#xff0c;发布在个人博客网站上。 最近几年处于动荡之中&#xff0c;比较忙碌&#xff0c;好几年没有写年度总结了。 现在2020年Q1马上结束&#xff0c;先把19年的总结补了。 年度大事记 1月 启动项目迁移工作。 深圳团队的人员释放&#xff0c;在南京…

java数据结构前置知识以及认识泛型

目录 什么是集合框架 容器 时间复杂度 空间复杂度 包装类 装箱 拆箱 引出泛型 泛型类的使用 类型推导 泛型如何编译的 泛型的上界 泛型方法静态泛型方法以及泛型上界 什么是集合框架 Java 集合框架 Java Collection Framework &#xff0c;又被称为容器 containe…

算法训练营day24(补),回溯4-2

import ( "fmt" "sort" ) 78. 子集 func subsets(nums []int) [][]int { //存储全部集合 result : make([][]int, 0) if len(nums) 0 { return result } //存储单次集合 path : make([]int, 0) var backtrace func(numList []int, startIndex int) bac…

变量与运算符

目录 1. 关键字&#xff08;keyword&#xff09; 2. 标识符( identifier) 3. 变量 3.1 为什么需要变量 3.2 初识变量 3.3 Java中变量的数据类型 3.4 变量的使用 3.4.1 步骤1&#xff1a;变量的声明 3.4.2 步骤2&#xff1a;变量的赋值 4. 基本数据类型介绍 4.1 整数…

cool Nodejs后端框架 如何快速入门 写一个接口

1.cool 框架 js前端开发者 想自己写后端接口 快速入门的就是node.js 了 可以用这个框架自己做一些东西 或者实现前后端的开发 2.目录结构 这个基本上 就是cool 框架的项目结构 主要是 这个src 中的modules 文件夹 这个文件夹 主要是一些接口模块 比如 business 中 相当于…

OJ_深度优先搜索

题干 c代码 #include <iostream> #include <algorithm> using namespace std; #define Max_M 100 #define Max_N 100 char a[Max_M][Max_N],M,N; void dfs(int x,int y) {//先把w替换成.//然后遍历8个方向a[x][y] .;for(int dx -1;dx < 1;dx){for(int dy -1…

基于 Python 的大数据的电信反诈骗系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

车载诊断协议DoIP系列 —— 车载以太网诊断需求规范(网关、路由)

车载诊断协议DoIP系列 —— 车载以太网诊断需求规范(网关、路由) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自…

Springboot加载bootstrap和application原理

Springboot加载bootstrap和application原理 bootstrap.yml能被springboot加载导入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.6</version><rel…

Bitcoin Bridge:治愈还是诅咒?

1. 引言 主要参考&#xff1a; Bitcoin Bridges: Cure or Curse? 2. 为何需关注Bitcoin bridge&#xff1f; 当前的Bitcoin bridge&#xff0c;其所谓bridge&#xff0c;实际是deposit&#xff1a; 在其它链上的BTC情况为&#xff1a; 尽管当前约有43.7万枚BTC在其它链上…

防御保护---防火墙的带宽管理

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.带宽管理概述 带宽管理是指限制网络流量的速率或控制网络流量的优先级&#xff0c;以确保网络的性能和可用性。 防火墙带宽管理核心&#xff1a; 带宽限制&#xff1a;限制非关键业务的流量…

PR:视频源素材的截取操作

导入素材后&#xff0c;双击视频素材&#xff0c;打开源视频 1&#xff1a;设置入点 2&#xff1a;设置出点&#xff0c;设置完出入点&#xff0c;抓取视频就可以将入点至出点的片段拖至时间轴上 3&#xff1a;转到入点 4&#xff1a;后退一帧 5&#xff1a;播放 6&#x…

全面理解JVM虚拟机

为什么要学JVM&#xff1f; ​ 首先&#xff1a;面试需要。面试题层出不穷&#xff0c;难道每次面试都靠背几百上千条面试八股&#xff1f; ​ 其次&#xff1a;基础决定上层建筑。自己写的代码都不知道是怎么回事&#xff0c;怎么可能写出靠谱的系统&#xff1f; ​ 然后&a…

【算法设计与分析】反转链表 ||

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表…