Open CV系列学习笔记(十八)轮廓发现 2021-02-13

Open CV系列学习笔记(十八)轮廓发现

轮廓发现

轮廓检测指在包含目标和背景的数字图像中,忽略背景和目标内部的纹理以及噪声干扰的影响,采用一定的技术和方法来实现目标轮廓提取的过程。它是目标检测、形状分析、目标识别和目标跟踪等技术的重要基础。
目前轮廓检测方法有两类,一类是利用传统的边缘检测算子检测目标轮廓,另一类是从人类视觉系统中提取可以使用的数学模型完成目标轮廓检测。
基于边缘检测的轮廓检测方法是一种低层视觉行为,它主要定义了亮度、颜色等特征的低层突变,通过标识图像中亮度变化明显的点来完成边缘检测,因此很难形成相对完整和封闭的目标轮廓。边缘检测通常将图像与微分算子卷积。比如借助于Sobel算子、Prewitt算子、Canny算子等,此方法没有考虑视觉中层和高层信息,因此很难得出完整的、连续的轮廓边缘,仅仅使用这类方法很难得出完整的目标轮廓,这种过程往往复杂且精度难以保证,甚至在含有大量噪声或者纹理的情况下,无法提取轮廓。
从视网膜经典感受野推导出的DoG模型得到初步应用。该模型一般适用于图像平滑与边缘检测领域。Gabor滤波器模型来源于初级视皮层Vl区简单细胞感受野,一般适用于角点检测和纹理特征提取等。Grigorescu和Petkov运用非经典感受野的周边抑制作用,与经典的边缘检测方法结合,取得了令人瞩目的成果。他们假设非经典感受野是圆环形抑制区域,通过对经典感受野的抑制来抑制纹理。他们还提出一个将轮廓检测结果进行量化比较的方法,给以后人们研究轮廓检测或边缘检测提供了新的评价方法。桑农等人根据非经典感受野的假说,提出了蝶形抑制区,使得轮廓检测结果取得了更好的效果。
视觉信息经过加工传递,从视网膜经过LGN到达初级视皮层,这个机制十分复杂,也有许多假说。人为定义一种抑制模型忽略人类视觉感知的过程和刺激传递过程中的信息易造成轮廓断裂,Hubel和Wiesel推断简单细胞的感受野的方向选择性可以由外侧膝状体的感受野经过一种特定的组合拟合而成,因此Azwpardi等提出了CORE模型,直接用外侧膝状体的感受野模型来模拟视觉系统来进行轮廓检测。 Wei H等也根据这项发现提出了自己的计算模型,用来检测线条的方向。
对比以上所述两类方法可以发现,基于人类视觉感知模型的方法己经被广泛研究和应用,属于轮廓检测的研究趋势,效果优于第一类方法。

全局二值

代码:

def contours_demo(image):
    dst = cv.GaussianBlur(image,(3,3),0)
    #全局二值
    gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow("binary",binary)
   

    cloneImage ,contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for i ,contour in enumerate(contours):
        cv.drawContours(image,contours,i,(0,0,255),2)
        print(i)
    cv.imshow("detect contours",image)

结果:
Open CV系列学习笔记(十八)轮廓发现 2021-02-13
Open CV系列学习笔记(十八)轮廓发现 2021-02-13

局部二值

代码:

def contours_demo(image):
    dst = cv.GaussianBlur(image,(3,3),0)
    #全局二值
    #gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
    #ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
    #cv.imshow("binary",binary)
    #局部二值

    gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
    binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
    cv.imshow("binary", binary)

    binary = edge_demo(image)

    cloneImage ,contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for i ,contour in enumerate(contours):
        cv.drawContours(image,contours,i,(0,0,255),2)
        print(i)
    cv.imshow("detect contours",image)

结果:
Open CV系列学习笔记(十八)轮廓发现 2021-02-13
Open CV系列学习笔记(十八)轮廓发现 2021-02-13

Canny边缘提取

代码:

def edge_demo(image):#Canny边缘提取
    blurred = cv.GaussianBlur(image,(3,3),0)#高斯模糊
    gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)#灰度转化
    # X  方向的梯度
    xgrad = cv.Sobel(gray,cv.CV_16SC1,1,0)
    # Y  方向的梯度
    ygrad = cv.Sobel(gray,cv.CV_16SC1,0,1)
    #边缘
    #edge_output = cv.Canny(xgrad,ygrad,50,150)
    edge_output = cv.Canny(gray,30,150)#高低阈值比值2:1到3:1之间
    cv.imshow("Canny Edge",edge_output)
    return edge_output

结果:
Open CV系列学习笔记(十八)轮廓发现 2021-02-13
完整代码:

import cv2 as cv
import numpy as np


def edge_demo(image):#Canny边缘提取
    blurred = cv.GaussianBlur(image,(3,3),0)#高斯模糊
    gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)#灰度转化
    # X  方向的梯度
    xgrad = cv.Sobel(gray,cv.CV_16SC1,1,0)
    # Y  方向的梯度
    ygrad = cv.Sobel(gray,cv.CV_16SC1,0,1)
    #边缘
    #edge_output = cv.Canny(xgrad,ygrad,50,150)
    edge_output = cv.Canny(gray,30,150)#高低阈值比值2:1到3:1之间
    cv.imshow("Canny Edge",edge_output)
    return edge_output


def contours_demo(image):
    dst = cv.GaussianBlur(image,(3,3),0)
    #全局二值
    #gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
    #ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
    #cv.imshow("binary",binary)
    #局部二值

    gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
    binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
    cv.imshow("binary", binary)

    binary = edge_demo(image)

    cloneImage ,contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for i ,contour in enumerate(contours):
        cv.drawContours(image,contours,i,(0,0,255),2)
        print(i)
    cv.imshow("detect contours",image)


print("--------HEllow Python-------")
src = cv.imread("E:/picture/10.bmp")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",src)
edge_demo(src)
cv.waitKey(0)


cv.destroyAllWindows()
上一篇:OpenCV --- 修改图像的对比度、亮度 、RGB转Gray图像、修改图像的尺寸


下一篇:求图像中指定颜色区域的相对面积问题