opencv学习笔记(五)

北城以北 提交于 2020-01-30 07:19:36

图像金字塔

高斯金字塔

  • 向下采样法从金字塔底层向上采样(面积从大到小)先使用高斯内核与原图进行卷积操作,然后将偶数行列去除。
  • 向上采样法向下采样法的逆操作,先将原图像扩大为原来的两倍,用0填充新增行列,然后使用与先前相同的内核与放大后的图像进行卷积,得到近似值。

在opencv中代码如下:

def up(img ,upordown):
    if(upordown ==1):
        return cv2.pyrUp(img)
    else:
        return cv2.pyrDown(img)

拉普拉斯金字塔

L i =G i PyrUp(PyrDown(G i ))L~i~ = G~i~ - PyrUp(PyrDown(G~i~))

得到的是原图与执行了down然后在执行up后的结果之间的差异。
代码如下:

def Lapras(img):
    return (img - cv2.pyrUp(cv2.pyrDown(img)))

轮廓检测

cv2.findContours(img,mode,method)

mode:

  • RETR_EXTERNAL:只检测最外面的轮廓
  • RETR_LIST:检索所有轮廓并放入链表
  • RETR_CCOMP:检索所有轮廓并分成两层,顶层是各部分的边界,第二层是空洞的边界
  • RETR_TREE:检测所有轮廓并重构嵌套轮廓的整个层次,优先使用
    method:轮廓逼近方法
  • CHTR_APPROX_NONE:以Freeman链码的形式输出轮廓,所有其他方法输出多边形。
  • CHTR_APPROX_SIMPLE:压缩水平的,垂直的和斜的部分,只保留终点部分。

一般轮廓检测使用二值图像

def thre(img):
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) #转成二值图像
    binary,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)#binary 原图像 contours轮廓信息,hierarchy层级
    copy_img = img.copy()#会改原图
    #
    app = approximate(contours)#轮廓近似
    res = cv2.drawContours(copy_img,[app],-1,(0,0,255),2)#-1指所有轮廓,第几层级的轮廓,轮廓颜色,线条宽度
    showImg(0,img,"img")
    showImg(0,res,"img")
    return res,img,contours

轮廓近似

取任意一条曲线段AB,线段连接AB,当曲线段AB不上存在一点C到线段AB距离大于阈值时,AB线段可以近似代替曲线段AB,反之则用线段连接AC,CB,继续近似过程,近似代码如下:

def approximate(contours):
    #epsilon = 0.1*cv2.arcLength(contours,True)#一般是周长百分比
    epsilon = 0.1
    approx = cv2.approxPolyDP(contours[30],epsilon,True)
    return approx

模板匹配

在原图中检索与目标图像相符合的部分,输出大小为(A-a+1)*(B-b+1)的矩阵

cv2.TM_CCOEFF:平方计算,数值越小越相关
cv2.TM_CCOEFF_NORMED:计算相关性,值越大越相关
cv2.TM_CCORR:值越大越相关
cv2.TM_CCORR_NORMED:计算归一化平方,值越接近零越相关
cv2.TM_SQDIFF:计算归一化相关性,值越接近1越相关
cvv2.TM_SQDIFF_NORMED:计算归一化相关系数,越接近1越相关

公式传送门

在opencv-python中实现如下:

method = ["cv2.TM_CCOEFF","cv2.TM_CCOEFF_NORMED","cv2.TM_CCORR","cv2.TM_CCORR_NORMED","cv2.TM_SQDIFF","cv2.TM_SQDIFF_NORMED"]

def matchT(img1,img2):
    for meth in method:
        img_copy = img1.copy()
        methodItem = eval(meth)
        res = cv2.matchTemplate(img1,img2,methodItem)
        min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res)
        print(res.shape)
        print(min_val)
        print(max_val)
         print(min_loc)
        print(max_loc)#根据方法不同取值
        print(img2.shape)
        if(methodItem in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]):
            top_left = min_loc
        else:
            top_left = max_loc
        bottom_right = (top_left[0]+img2.shape[1],top_left[1]+img2.shape[0])
        cv2.rectangle(img_copy,top_left,bottom_right,255,2)
    
        plt.subplot(121),plt.imshow(res,cmap="gray")
        plt.xticks([]),plt.yticks([])
        plt.subplot(122),plt.imshow(img_copy,cmap="gray")
        plt.xticks([]),plt.yticks([])
        plt.suptitle(meth)
        plt.show()

我使用的原图像如下:
在这里插入图片描述
在这里插入图片描述

效果图如下所示:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

左侧图片是经过计算得到的一组矩阵,根据公式不同,图片上的最大值或者最小值既是我们需要的值,即图片上最亮或者最暗的点,右边是得到的结果图,我放大了一下便于观察,除了TM_CCORR那张有点离谱意外,效果都还可,后来发现一般经过归一化处理的公式效果要优于为归一化处理的图片。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!