2022-08-03 11:09阅读: 199评论: 0推荐: 0

OpenCV图像处理笔记[08]

[实验]模板匹配

  • 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。

  • 所以模板匹配首先需要一个模板图像T(给定的子图像)

  • 另外需要一个待检测的图像-源图像S

  • 工作方法,在带检测图像上,从左到右,从上向下计算模板图像与重叠子图像的匹配度程度越大,两者相同的可能性越大

T-灰度变换-二值化-轮廓-外接矩形
信用卡-灰度-二值化-顶帽-梯度-闭操作-闭操作-轮廓-二值化-切分
模板匹配

  • imutils : 工具包

imutils提供一系列便捷功能进行基本的图像处理功能,如平移,旋转,缩放,骨架,matplotlib图像显示,排序的轮廓,边缘检测


  • argparse : 命令行参数解析包

1. 创建一个解析器

使用 argparse 的第一步是创建一个 ArgumentParser 对象:

>>> parser = argparse.ArgumentParser(description='Process some integers.')
2. 添加参数

给一个 ArgumentParser 添加程序参数信息是通过调用 add_argument()方法完成的。通常,这些调用指定 ArgumentParser 如何获取命令行字符串并将其转换为对象。这些信息在 parse_args()调用时被存储和使用

3. 解析参数

ArgumentParser 通过 parse_args() 方法解析参数。它将检查命令行,把每个参数转换为适当的类型然后调用相应的操作。在大多数情况下,这意味着一个简单的 Namespace 对象将从命令行参数中解析出的属性构建:

>>> parser.parse_args(['--sum', '7', '-1', '42'])
Namespace(accumulate=<built-in function sum>, integers=[7, -1, 42])

在脚本中,通常 parse_args()会被不带参数调用,而 ArgumentParser将自动从 sys.argv 中确定命令行参数。


# 根据坐标提取每一个组
group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
cv_show('group',group)

其中“+5”,"-5"是为了不把特征值丢掉


  • cv2.findContours()函数
# 计算轮廓
#cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓
ref_, refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,0,255),3)
cv_show('img',img)
print (np.array(refCnts).shape)
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0] #排序,从左到右,从上到下
digits = {}
  • cv2.findContours()

​ image, contours, hierarchy=cv2.findContours(image,mode,method)

  • 参数

    • mage ,修改后的原始图像
    • contours , 轮廓
    • hierarchy , 图像的拓扑信息(轮廓层次)
    • image , 原始图像
    • ​ mode , 轮廓检索模式
    • method , 轮廓的近似方法
  • cv2.drawContours( )

    ​ r=cv2.drawContours(),contours,contourldx,color[,thickness])

    • r : 目标图像,直接修改目标的像素点,实现绘制。
    • o : 原始图像
    • contours : 需要绘制的边缘数组。
    • contourldx : 需要绘制的边缘索引,如果全部绘制则为一1。
    • color : 绘制的颜色,为BGR格式的Scalar。
    • thickness : 可选,绘制的密度,即描绘轮廓时所用的画笔粗细。

  • refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0]

def sort_contours(cnts, method="left-to-right"):
reverse = False
i = 0
if method == "right-to-left" or method == "bottom-to-top":
reverse = True
if method == "top-to-bottom" or method == "bottom-to-top":
i = 1
boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一个最小的矩形,把找到的形状包起来x,y,h,w
(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
key=lambda b: b[1][i], reverse=reverse))
return cnts, boundingBoxes

for (i, c) in enumerate(refCnts):
# 计算外接矩形并且resize成合适大小
(x, y, w, h) = cv2.boundingRect(c)
roi = ref[y:y + h, x:x + w]
roi = cv2.resize(roi, (57, 88))
# 每一个数字对应每一个模板
digits[i] = roi

enumerate:

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

enumerate(sequence, [start=0])

参数

  • sequence -- 一个序列、迭代器或其他支持迭代对象。
  • start -- 下标起始位置。

返回值

​ 返回 enumerate(枚举) 对象。

cv2.boundingRect(img)

得到包覆此轮廓的最小正矩形


  • cv2.getStructuringElement( )
# 初始化卷积核读入信用卡图像
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))#根据字体大小设定核的大小
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

返回指定形状和尺寸的结构元素。

例: kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11))

​ 函数的第一个参数表示内核的形状,有三种形状可以选择。

​ 矩形:MORPH_RECT;

​ 交叉形:MORPH_CROSS;

​ 椭圆形:MORPH_ELLIPSE;

​ 第二和第三个参数分别是内核的尺寸以及锚点的位置。一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得

getStructuringElement函数的返回值: 对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心点。element形状唯一依赖锚点位置,其他情况下,锚点只是影响了形态学运算结果的偏移。


#礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) #明亮的区域提取出来
cv_show('tophat',tophat)
# 梯度运算
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的
ksize=-1)

礼帽(image) = 原始图像(image) - 开运算(image)

  • 得到噪声图像

    函数morphologyEX

​ result = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)

  • result ,礼帽结果 | img,源图像

    ​ | cv2.MORPH_TOPHAT,礼帽

    ​ | kernel,卷积核 例:kernel = np.ones((5,5),np.unit8)

    dst = cv2.Sobel( src, ddepth, dx, dy, [ ksize ])

​ dst, 计算结果 src, 原始图像

​ ddepth, 处理结果图像深度

​ dx, x轴方向

​ dy, y轴方向

​ ksize, 核大小


#通过闭操作(先膨胀,再腐蚀,去除内部空洞)将数字连在一起
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_show('gradX',gradX)
#THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show('thresh',thresh)

闭运算(image) = 腐蚀(膨胀(image))

  • 先膨胀,后腐蚀

  • 它有助于关闭前景物体内部的小孔,或物体上的小黑点

函数morphologyEX

closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)

closing ,闭运算结果 | img,源图像

​ | cv2.MORPH_CLOSE,闭运算

​ | kernel,卷积核 例:kernel = np.ones((5,5),np.unit8)

opencv二值化函数 threshold(src_gray,dst,threshold_value,max_BINARY_value,threshold_type),threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU)

这里二值化,即图像像素值变成0或255,THRESH_OTSU是确定阈值分割点,这个是库函数确定的

Ostu方法又名最大类间差方法,通过统计整个图像的直方图特性来实现全局阈值T的自动选取

算法步骤:

  1. 先计算图像的直方图,即将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量

  2. 归一化直方图,也即将每个bin中像素点数量除以总的像素点

  3. i表示分类的阈值,也即一个灰度级,从0开始迭代

  4. 通过归一化的直方图,统计0~i 灰度级的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例w0,并统计前景像素的平均灰度u0;统计i~255灰度级的像素(假设像素值在此范围的像素叫做背景像素) 所占整幅图像的比例w1,并统计背景像素的平均灰度u1;

  5. 计算前景像素和背景像素的方差 g = w0w1(u0-u1) (u0-u1)

  6. i++;转到4),直到i为256时结束迭代

7)将最大g相应的i值作为图像的全局阈值


  • 模板匹配函数
# 在模板中计算每一个得分
for (digit, digitROI) in digits.items():
# 模板匹配
result = cv2.matchTemplate(roi, digitROI,cv2.TM_CCOEFF)
(_, score, _, _) = cv2.minMaxLoc(result)
scores.append(score)

matchTemplate(InputArray image, InputArray templ, OutputArray result, int method);

image:输入一个待匹配的图像,支持8U或者32F。
templ:输入一个模板图像,与image相同类型。
result:输出保存结果的矩阵,32F类型。
method:要使用的数据比较方法。

result:

​ result是一个结果矩阵,假设待匹配图像为 I,宽高为(W,H),模板图像为 T,宽高为(w,h)。那么result的大小就为(W-w+1,H-h+1) 。

method:

img

方差匹配方法:完全匹配会得到1, 完全不匹配会得到0。

归一化方差匹配方法:完全匹配结果为0。

相关性匹配方法:完全匹配会得到很大值,不匹配会得到一个很小值或0。

归一化的互相关匹配方法:完全匹配会得到1, 完全不匹配会得到0。相关系数匹配方法:完全匹配会得到一个很大值,完全不匹配会得到0,完全负相关会得到很大的负数。

归一化的相关系数匹配方法:完全匹配会得到1,完全负相关匹配会得到-1,完全不匹配会得到0。

本文作者:Hecto

本文链接:https://www.cnblogs.com/tow1/p/16546355.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Hecto  阅读(199)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑