OpenCV 13(模版匹配和霍夫变换)

一、模版匹配

所谓的模板匹配,就是在给定的图片中查找和模板最相似的区域,该算法的输入包括模板和图片,整个任务的思路就是按照滑窗的思路不断的移动模板图片,计算其与图像中对应区域的匹配度,最终将匹配度最高的区域选择为最终的结果。

将模板块每次移动一个像素 (从左往右,从上往下),在每一个位置,都计算与模板图像的相似程度。

对于每一个位置将计算的相似结果保存在结果矩阵(R)中。如果输入图像的大小(WxH)且模板图像的大小(wxh),则输出矩阵R的大小为(W-w + 1,H-h + 1)将R显示为图像,如下图所示

 获得上述图像后,查找最大值所在的位置,那么该位置对应的区域就被认为是最匹配的。对应的区域就是以该点为顶点,长宽和模板图像一样大小的矩阵。

1.1 API

res = cv.matchTemplate(img,template,method)
  • img: 要进行模板匹配的图像
  • Template :模板
  • method:实现模板匹配的算法,主要有:
    1. 平方差匹配(CV_TM_SQDIFF):利用模板与图像之间的平方差进行匹配,最好的匹配是0,匹配越差,匹配的值越大。
    2. 相关匹配(CV_TM_CCORR):利用模板与图像间的乘法进行匹配,数值越大表示匹配程度较高,越小表示匹配效果差。
    3. 利用相关系数匹配(CV_TM_CCOEFF):利用模板与图像间的相关系数匹配,1表示完美的匹配,-1表示最差的匹配。

通过matchTemplate实现模板匹配,使用minMaxLoc定位最匹配的区域,并用矩形标注最匹配的区域。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 图像和模板读取
img = cv.imread('./image/wulin2.jpeg')
template = cv.imread('./image/wulin.jpeg')
h,w,l = template.shape
# 2 模板匹配
# 2.1 模板匹配
res = cv.matchTemplate(img, template, cv.TM_CCORR)
# 2.2 返回图像中最匹配的位置,确定左上角的坐标,并将匹配位置绘制在图像上
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
# 使用平方差时最小值为最佳匹配位置
# top_left = min_loc
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv.rectangle(img, top_left, bottom_right, (0,255,0), 2)
# 3 图像显示
plt.imshow(img[:,:,::-1])
plt.title('匹配结果'), plt.xticks([]), plt.yticks([])
plt.show()

模板匹配不适用于尺度变换,视角变换后的图像,这时我们就要使用关键点匹配算法,比较经典的关键点检测算法包括SIFT和SURF等,主要的思路是首先通过关键点检测算法获取模板和测试图片中的关键点;然后使用关键点匹配算法处理即可,这些关键点可以很好的处理尺度变化、视角变换、旋转变化、光照变化等,具有很好的不变性。

二、霍夫变换

霍夫变换常用来提取图像中的直线和圆等几何形状

2.1 原理

在笛卡尔坐标系中,一条直线由两个点A=(x​1​​,y​1​​)和B=(x​2​​,y​2​​)确定,如下图所示:

将直线y=kx+q可写成关于(k,q)的函数表达式:

对应的变换通过图形直观的表示下:

变换后的空间我们叫做霍夫空间。即:笛卡尔坐标系中的一条直线,对应于霍夫空间中的一个点。反过来,同样成立,霍夫空间中的一条线,对应于笛卡尔坐标系中一个点,如下所示:

2.1.1 点共线的情况,对应于霍夫空间的情形

在笛卡尔坐标系的点共线,那么这些点在霍夫空间中对应的直线交于一点

2.1.2 点不共线情况

似乎已经完成了霍夫变换的求解。但如果像下图这种情况时(斜率不存在):

上图中的直线是 x=2,那 (k,q)怎么确定呢?

为了解决这个问题,我们考虑将笛卡尔坐标系转换为极坐标

在极坐标下是一样的,极坐标中的点对应于霍夫空间的线,这时的霍夫空间是不在是参数(k,q)的空间,而是(ρ,θ)的空间,ρ是原点到直线的垂直距离,θ表示直线的垂线与横轴顺时针方向的夹角,垂直线的角度为0度,水平线的角度是180度。

只要求得霍夫空间中的交点的位置,即可得到原坐标系下的直线

 

2.2 霍夫变换检测线

假设有一个大小为100∗∗100的图片,使用霍夫变换检测图片中的直线,则步骤如下所示:

直线都可以使用 (ρ,θ) 表示,首先创建一个2D数组,我们叫做累加器,初始化所有值为0,行表示 ρ ,列表示 θ 。

该数组的大小决定了结果的准确性,若希望角度的精度为1度,那就需要180列。对于 ρ,最大值为图片对角线的距离,如果希望精度达到像素级别,行数应该与图像的对角线的距离相等。

  • 取直线上的第一个点 (x,y),将其带入直线在极坐标中的公式中,然后遍历 θ的取值:0,1,2,...,180,分别求出对应的 ρ值,如果这个数值在上述累加器中存在相应的位置,则在该位置上加1.

  • 取直线上的第二个点,重复上述步骤,更新累加器中的值。对图像中的直线上的每个点都直线以上步骤,每次更新累加器中的值。

  • 搜索累加器中的最大值,并找到其对应的 (ρ,θ),就可将图像中的直线表示出来。

cv.HoughLines(img, rho, theta, threshold)
  • img: 检测的图像,要求是二值化的图像,所以在调用霍夫变换之前首先要进行二值化,或者进行Canny边缘检测

  • rho、theta:  ρ 和θ的精确度

  • threshold: 阈值,只有累加器中的值高于该阈值时才被认为是直线。

霍夫线检测的整个流程如下图所示

1、检测图中的点

2、对检测出来的每个点进行遍历,每个点对应于霍夫空间中的一条曲线

3、所有点在霍夫空间中的曲线中, 相交最多的交点求出

4、这样就得到了图像中的线

import numpy as np
import random
import cv2 as cv
import matplotlib.pyplot as plt
# 1.加载图片,转为二值图
img = cv.imread('./image/rili.jpg')gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150)# 2.霍夫直线变换
lines = cv.HoughLines(edges, 0.8, np.pi / 180, 150)
# 3.将检测的线绘制在图像上(注意是极坐标噢)
for line in lines:rho, theta = line[0]a = np.cos(theta)b = np.sin(theta)x0 = a * rhoy0 = b * rhox1 = int(x0 + 1000 * (-b))y1 = int(y0 + 1000 * (a))x2 = int(x0 - 1000 * (-b))y2 = int(y0 - 1000 * (a))cv.line(img, (x1, y1), (x2, y2), (0, 255, 0))
# 4. 图像显示
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img[:,:,::-1]),plt.title('霍夫变换线检测')
plt.xticks([]), plt.yticks([])
plt.show()

2.3 霍夫变换检测圆

圆的表示式是:

其中 a和 b表示圆心坐标, r表示圆半径,因此标准的霍夫圆检测就是在这三个参数组成的三维空间累加器上进行圆形检测,此时效率就会很低,所以OpenCV中使用霍夫梯度法进行圆形的检测。

霍夫梯度法将霍夫圆检测范围两个阶段,第一阶段检测圆心,第二阶段利用圆心推导出圆半径。

  • 圆心检测的原理:圆心是圆周法线的交汇处,设置一个阈值,在某点的相交的直线的条数大于这个阈值就认为该交汇点为圆心。

  • 圆半径确定原理:圆心到圆周上的距离(半径)是相同的,确定一个阈值,只要相同距离的数量大于该阈值,就认为该距离是该圆心的半径

原则上霍夫变换可以检测任何形状,但复杂的形状需要的参数就多,霍夫空间的维数就多,因此在程序实现上所需的内存空间以及运行效率上都不利于把标准霍夫变换应用于实际复杂图形的检测中。霍夫梯度法是霍夫变换的改进,它的目的是减小霍夫空间的维度,提高效率。

circles = cv.HoughCircles(image, method, dp, minDist, param1=100, param2=100, minRadius=0,maxRadius=0 )
  • image:输入图像,应输入灰度图像

  • method:使用霍夫变换圆检测的算法,它的参数是CV_HOUGH_GRADIENT

  • dp:霍夫空间的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半,以此类推

  • minDist为圆心之间的最小距离,如果检测到的两个圆心之间距离小于该值,则认为它们是同一个圆心

  • param1:边缘检测时使用Canny算子的高阈值,低阈值是高阈值的一半。

  • param2:检测圆心和确定半径时所共有的阈值

  • minRadius和maxRadius为所检测到的圆半径的最小值和最大值

返回:

  • circles:输出圆向量,包括三个浮点型的元素——圆心横坐标,圆心纵坐标和圆半径

由于霍夫圆检测对噪声比较敏感,所以首先对图像进行中值滤波。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 1 读取图像,并转换为灰度图
planets = cv.imread("./image/star.jpeg")
gay_img = cv.cvtColor(planets, cv.COLOR_BGRA2GRAY)
# 2 进行中值模糊,去噪点
img = cv.medianBlur(gay_img, 7)  
# 3 霍夫圆检测
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 200, param1=100, param2=30, minRadius=0, maxRadius=100)
# 4 将检测结果绘制在图像上
for i in circles[0, :]:  # 遍历矩阵每一行的数据# 绘制圆形cv.circle(planets, (i[0], i[1]), i[2], (0, 255, 0), 2)# 绘制圆心cv.circle(planets, (i[0], i[1]), 2, (0, 0, 255), 3)
# 5 图像显示
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(planets[:,:,::-1]),plt.title('霍夫变换圆检测')
plt.xticks([]), plt.yticks([])
plt.show()

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

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

相关文章

html 高性能 简易轮播图

目标 实现简易轮播图动画效果 设计理念 无论有多少个轮播图,仅使用常数个轮播图tab,通过js替换更新dom内容,实现性能优化;使用bfc避免回流,(重绘是基本上无法避免,不在考虑)&#…

C++——多态底层原理

虚函数表 先来看这个问题&#xff1a; class Base { public: virtual void Func1() { cout << "Func1()" << endl; } private: int _b 1; }; sizeof(Base)是多少&#xff1f; 答案是&#xff1a;8 因为Base中除了成员变量_b,还有一个虚函数表_vfp…

【WinRAR】去除请购买WinRAR许可

新建rarreg.key文件 在WinRAR安装目录新建rarreg.key文件&#xff0c;文件内容如下: RAR registration datawncnUnlimited Company LicenseUID1b064ef8b57de3ae9b5264122122509b52e35fd885373b214a4a64cc2fc1284b77ed14fa2066ebfca6509f9813b32960fce6cb5ffde62890079861be57…

JDBC-day02(使用PreparedStatement实现CRUD操作)

所需的数据库数据要导入到自己的数据库库中 三&#xff1a;使用PreparedStatement实现CRUD操作 数据库连接被用于向数据库服务器发送命令和 SQL 语句&#xff0c;并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。CRUD操作&#xff1a;根据返回值的有无…

HDLbits: Edgedetect

module top_module (input clk,input [7:0] in,output [7:0] pedge );reg [7:0] in_old;always(posedge clk)beginin_old < in; end assign pedge < in & ~in_old; endmodule 对于边缘检测而言&#xff0c;若是0→1和1→0都检测则为in^in_old&#xf…

java实验(头歌)--面向对象封装继承和多态

文章目录 第一题第二题第三题第四题第五题第六题第七题第八题 快速完成实验的方法&#xff1a; 把对应题目的主函数替换&#xff0c;其他复制粘贴。 第一题 public class TestPersonDemo {public static void main(String[] args) {/********* begin *********/// 声明并实例化…

练[FBCTF2019]RCEService

[FBCTF2019]RCEService 文章目录 [FBCTF2019]RCEService掌握知识解题思路关键paylaod 掌握知识 ​ json字符串格式&#xff0c;命令失效(修改环境变量)–绝对路径使用linux命令&#xff0c;%0a绕过preg_match函数&#xff0c;代码审计 解题思路 打开题目链接&#xff0c;发现…

2023年中国互联网本地生活服务行业发展历程及趋势分析:国内市场仍有增长潜力[图]

我国本地生活进入4.0时代&#xff0c;“附近消费”场景迭代、渠道多元&#xff1b;更多玩家涌入本地生活赛道&#xff0c;本地消费场景分散到多平台、多模式&#xff0c;线下门店短视频直播运营组合蔚然成风。 本地生活行业发展历程 资料来源&#xff1a;共研产业咨询&#xf…

光伏并网逆变器低电压穿越技术研究(Simulink仿真)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

R实现数据分布特征的视觉化——多笔数据之间的比较

大家好&#xff0c;我是带我去滑雪&#xff01; 如果要对两笔数据或者多笔数据的分布情况进行比较&#xff0c;Q-Q图、柱状图、星形图都是非常好的选择&#xff0c;下面开始实战。 &#xff08;1&#xff09;绘制Q-Q图 首先导入数据bankwage.csv文件&#xff0c;该数据集…

解决:docker安装nginx,在腾讯云服务器可以打开但在本地的电脑浏览器不能打开

第一步运行nginx&#xff1a; [rootVM-24-4-centos ~]# docker run -d --name nginx01 -p 8080:80 nginx [rootVM-24-4-centos ~]# curl localhost:8080 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html …

JMeter压测如何分配业务比例?

在进行综合场景压测时&#xff0c;由于不同的请求&#xff0c;要求所占比例不同&#xff0c;那如何实现呢&#xff1f; 有人说将这些请求分别放到单独的线程组下&#xff0c;然后将线程组的线程数按照比例进行配置&#xff0c;这种方法不是很好&#xff0c;想想&#xff0c;不…

关于 Vue-iClient-MapboxGL 的使用注意事项

官网&#xff1a;https://iclient.supermap.io/web/apis/vue/zh/api/guide/installation.html 关于图的使用&#xff0c;其余的引入步骤不再赘述&#xff0c;仅说注意事项。 推荐使用的是全局引入&#xff0c;也就是完整引入 因为单独引入我踩了不少坑&#xff0c;比如说 cs…

Thinking for Doing:让LLMs能推断他人心理状态来做出适当的行动。

LLMs通常能回答有关心理状态的问题&#xff0c;但往往不能将这些推断用于实际行动。例如&#xff0c;如果一个故事中的角色正在寻找他的背包&#xff0c;而模型知道背包在厨房里&#xff0c;那么模型应该能推断出最好的行动是建议角色去厨房查看。T4D 的目的就是要求模型不仅要…

Java学习day08:面向对象三大特性之一:继承

声明&#xff1a;该专栏本人重新过一遍java知识点时候的笔记汇总&#xff0c;主要是每天的知识点题解&#xff0c;算是让自己巩固复习&#xff0c;也希望能给初学的朋友们一点帮助&#xff0c;大佬们不喜勿喷(抱拳了老铁&#xff01;) Java学习day08&#xff1a;面向对象三大特…

辅助寄存器是干什么用的

目录 请问CPU 的 MREQ 引脚和 IORQ 引脚分别是干什么用的 那这里的引脚是什么含义呢&#xff1f; 程序是指令和数据的集合 辅助寄存器是干什么用的 寄存器的用途取决于它的类型 PC 寄存器也叫作“程序指针”&#xff0c;存储着指向 CPU 接下来 要执行的指令的地址。PC 寄存…

Suricata – 入侵检测、预防和安全工具

一、Suricata介绍 Suricata是一个功能强大、用途广泛的开源威胁检测引擎&#xff0c;提供入侵检测 (IDS)、入侵防御 (IPS) 和网络安全监控功能。它执行深度数据包&#xff08;网络流量&#xff09;检查以及模式匹配&#xff0c;在威胁检测中非常强大。 工作流程&#xff1a; 主…

关于对XSS原理分析与绕过总结

一、原理 该文章仅用于信息防御技术教学&#xff0c;请勿用于其他用途。 1、XSS原理 XSS&#xff08;跨站脚本攻击&#xff09;是一种常见的网络安全漏洞&#xff0c;攻击者通常会在网页中插入恶意的 JavaScript 代码。由于服务器对输入数据的过滤和验证不严格&#xff0c;这…

leetcode做题笔记160. 相交链表

给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返回结果后&…

【力扣每日一题】2023.10.7 股票价格跨度

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 给我们一个数组表示不同时间的股票的价格&#xff0c;要我们按照顺序返回每天的股票价格跨度&#xff0c;价格跨度就是股票价格小于或等于…