一、图像梯度计算
1)sobel算子(作用是标注轮廓区域)形式一般是这样
Gx即卷积完之后是右边像素-左边像素,Gy是上边像素-下边像素
dx=1,dy=0时,表示对其进行Gx计算。反之亦然。
白到黑是正数,黑到白是负数,所有的负数会被截断成0(黑色)。所以得取绝对值。使用cv2.CV_64F的原因是从白到黑的边界点导数为负数后,如果使用的是np.int8则会变成0。
def cv_show(img,name): cv2.imshow(name,img) cv2.waitKey(0) cv2.destroyAllWindows() sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) sobelx=cv2.convertScaleAbs(sobelx) #取绝对值 sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) sobely=cv2.convertScaleAbs(sobely) cv_show(sobelx,'sobelx') cv_show(sobely,'sobely') sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0) #0为偏置量 cv_show(sobelxy,'sobelxy')
不建议x,y直接计算,而是分别计算x、y再相加。
2)scharr算子、laplacian算子
拉普拉是算子即中间点与周围点的比较,没有x,y做这些了。代码基本差不多,如下:
import cv2 import numpy as np img=cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE) def cv_show(img,name): cv2.imshow(name,img) cv2.waitKey(0) cv2.destroyAllWindows() #sobel算子 sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) sobelx=cv2.convertScaleAbs(sobelx) sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) sobely=cv2.convertScaleAbs(sobely) sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0) #scharrt算子 scharrx=cv2.Scharr(img,cv2.CV_64F,1,0) scharry=cv2.Scharr(img,cv2.CV_64F,0,1) scharrx=cv2.convertScaleAbs(scharrx) scharry=cv2.convertScaleAbs(scharry) scharrxy=cv2.addWeighted(scharrx,0.5,scharry,0.5,0) #拉普拉斯算子 laplacian=cv2.Laplacian(img,cv2.CV_64F) laplacian=cv2.convertScaleAbs(laplacian) res=np.hstack((sobelxy,scharry,laplacian)) cv_show(res,'res')
二、边缘检测(一般直接转换为灰度图就可以了)
1)canny边缘检测算法
2、非极大值抑制法
3、双阈值检测
算法实现
import cv2 img=cv2.imread('car.png',cv2.IMREAD_GRAYSCALE) v1=cv2.Canny(img,80,120) cv2.imshow('img',v1) cv2.waitKey(0) cv2.destroyAllWindows()
三、图像金字塔(让数据更丰富一些)与轮廓检测
上采样可以放大图片,下采样可以缩小图片。实现代码如下:
up=cv2.pyrUp(img) #pyr表示金字塔,up表示放大 down=cv2.pyrDown(img) #down表示缩小
拉普拉斯金字塔
1)图像轮廓
需要注意的是cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图。需要注意的是,cv2.findCountours()返回两个参数,cv3则返回三个参数。
为了更高的准确率,图像需要二值化,实现代码如下:
img=cv2.imread('car.png') gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 转换为灰度图 ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY) #图像二值化 def cv_show(img,name): cv2.imshow(name,img) cv2.waitKey() cv2.destroyAllWindows() cv_show(thresh,'up')
2)绘制轮廓
contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) #contours为图像轮廓信息,hierarcgy为图像层数 draw_img=img.copy() res=cv2.drawContours(img,contours,-1,(0,0,255),2) #-1一般基本不变,指全部轮廓,括号即为(BGR)三个通道的值 cv_show(res,'res')
3)轮廓近似
4)模板匹配
模板匹配跟卷积很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度在opencv的计算方法里面有6种,然后将每一个结果放入一个矩阵里作为结果输出。加入原图是AXB输出,模板是aXb输出,则输出的结果矩阵为(A-a+1)X(B-b+1).
算法实现
import cv2 #opencv读取图像bgr格式 import numpy as np # 模版匹配 def template_image(): target = cv2.imread("lena.jpg") tpl = cv2.imread("ln.png") cv2.imshow("模板", tpl) cv2.imshow("原图", target) methods = [cv2.TM_SQDIFF_NORMED, cv2.TM_CCORR_NORMED, cv2.TM_CCOEFF_NORMED] #各种匹配算法 th, tw = tpl.shape[:2] #获取模板图像的高宽 for md in methods: print(md) result = cv2.matchTemplate(target, tpl, md) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) if md == cv2.TM_SQDIFF_NORMED: tl = min_loc else: tl = max_loc br = (tl[0] + tw, tl[1] + th) cv2.rectangle(target, tl, br, (0, 0, 255), 2) cv2.imshow("匹配" + np.str(md), target) template_image() cv2.waitKey(0) cv2.destroyAllWindows()