Opencv学习笔记(三)-----Canny边缘检测和模板匹配
- 前言
- 一、Canny边缘检测
- 二、模板匹配
- 2.1函数说明
- 2.2匹配步骤
- 2.3模板匹配六种模式对比
- 三、多模板匹配
- 总结
前言
本文介绍了Canny检测和模板匹配的方法以及代码示例和效果图对比
一、Canny边缘检测
- Canny函数常用用法:edge = cv2.Canny(image, threshold1, threshold2)
参数image:是需要处理的原图像,该图像必须为单通道的灰度图;
参数threshold1:阈值1;
参数threshold2:阈值2;
其中较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来。
四组不同的边界阈值的对比效果图,代码如下:
# -*- coding: utf-8 -*-
import numpy as np
import cv2
def cv_show(img,name,writename):
cv2.imshow(name,img)
cv2.imwrite(writename,img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('lena.jpg',0)
# 指定的边界越小检测得越详细
v1 = cv2.Canny(img,100,200)
v2 = cv2.Canny(img,40,200)
v3 = cv2.Canny(img,40,100)
v4 = cv2.Canny(img,20,50)
# 对比四组不同的边界阈值的处理效果
res = np.hstack((v1,v2,v3,v4))
cv_show(res,'res','res.jpg')
二、模板匹配
使用模板在图像中查找目标,找到原图中模板的坐标,根据模板的大小可以框出原图中模板位置;
2.1函数说明
- 函数res = cv2.matchTemplate(img,template,method):
参数img:待匹配的图像(原图)
参数temple:搜索模板,需要和原图一样的数据类型且尺寸不能大于原图像
参数method:指定匹配方法,有如下几种:
- 函数min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res):
参数res为cv2.matchTemplate处理后得到的矩阵;
返回值为图像中模板的最小值和最大值和对应位置;
2.2匹配步骤
第一步:读入原图片和模板图片的灰度图;
第二步:使用cv2.matchtemplate(img, template, method) 设置匹配方法进行模板匹配,获得大量的结果;
第三步:使用min_val, max_val, min_loc, max_loc = cv2.minMaxLoc() 找出最大值数所在的位置;
第四步:使用cv2.rectangle() 画框操作;
2.3模板匹配六种模式对比
# -*- coding: utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
def cv_show(img, name, writename):
cv2.imshow(name, img)
cv2.imwrite(writename, img)
cv2.waitKey()
cv2.destroyAllWindows()
# 读取原始图像
img = cv2.imread('lena.jpg ',0)
# 读取模板图像
template = cv2.imread('modle.png',0)
# 获取模板高h和长w
h = template.shape[0]
w = template.shape[1]
methods =['cv2.TM_CCOEFF','cv2.TM_CCOEFF_NORMED','cv2.TM_CCORR','cv2.TM_CCORR_NORMED','cv2.TM_SQDIFF','cv2.TM_SQDIFF_NORMED']
png = '.png'
for meth in methods:
#复制原图,因为在做处理时会修改原图
img2 = img.copy()
#匹配方法的真值
method = eval(meth)
#模板匹配方法设置
res = cv2.matchTemplate(img, template, method)
# 获取图像中最小值和最大值的位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
#如果是平方差匹配cv2.TM_SQDIFF或归一化平方差匹配到cv2.TM_SQDIFF_NORMED,取最小值
if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] +w,top_left[1]+h)
# 在原图中画模板位置矩形
cv2.rectangle(img2,top_left,bottom_right,255,2)
#每张图的保存名称
endname = meth + png
plt.subplot(121),plt.imshow(res,cmap='gray')
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img2, cmap='gray')
plt.xticks([]),plt.yticks([])
plt.suptitle(meth)
#保存每张图
plt.savefig(endname)
plt.show()
三、多模板匹配
多模板匹配使用的是一个阈值,当大于这个阈值时,我们认为已经获得一个模板的匹配值,而cv2.matchTemplate匹配出的res是不同匹配方法得到的矩阵;
第一步:读入图片原图片和模板并进行灰度化;
第二步:匹配模板,获得res;
第三步:使用np.where(res>0.8) 筛选合适的位置;
第四步:使用loc[::-1]将位置进行调换,使用*loc[::-1]使得矩阵发生拆分,使用zip进行两两组合;
第五步:使用cv2.rectangle画多个矩阵并展示;
# -*- coding: utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
# 读取原始图像
img = cv2.imread('mario.jpg')
# 对图像进行二值化
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 读取模板图像
template = cv2.imread('mario_coin.jpg',0)
# 获取模板高h和长w的范围
h,w = template.shape[:2]
# 设定匹配方法
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCORR_NORMED) #
threshold = 0.8
# 获取匹配程序大于0.8的坐标
loc = np.where(res >=threshold)
# 开始匹配
for pt in zip(*loc[::-1]):#*表示可选参数
bottom_right = (pt[0] + w,pt[1]+ h )
cv2.rectangle(img,pt,bottom_right,(0,0,255),2)
cv2.imshow('img', img)
cv2.waitKey()
cv2.imwrite('mario_end.png', img)
cv2.destroyAllWindows()
总结
小白在学习OpenCV过程中的学习笔记,可能理解的不到位,若有不对之处请指正。