文章目录

  • 1.轮廓发现
  • 1.1发现轮廓
  • 1.2绘制轮廓
  • 2.操作步骤
  • 2.1阈值法获取轮廓
  • 2.2使用Canny边缘检测获取轮廓
  • 完整代码


1.轮廓发现

轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法,所以边缘提取的阈值选定会影响最终轮廓发现结果。

1.1发现轮廓

在此步骤中我们会使用到findContours这个API,其原型为:

cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

注:opencv3会返回三个值,分别是img, countours, hierarchy;
而opencv4中只有 countours, hierarchy两个返回值
第一个参数是寻找轮廓的图像;
第二个参数表示轮廓的检索模式,有四种:
(1)RETR_EXTERNAL表示只检测外轮廓
(2)RETR_LIST检测的轮廓不建立等级关系
(3)RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息
(4)RETR_TREE建立一个等级树结构的轮廓
其中最常用的是第一种和第四种。
第三个参数method为轮廓的近似办法:
(1)CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
(2)CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
(3)CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

1.2绘制轮廓

在绘制轮廓时我们会用到drawContours该API,其原型为:

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])

第一个参数是指明在哪幅图像上绘制轮廓;
第二个参数是是轮廓本身,在Python中是一个list;
第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓;
之后的参数分别为线的颜色和线宽。

2.操作步骤

1.转换图像为二值化图像:threshold方法或者Canny边缘提取获取的都是二值化图像;
2.通过二值化图像寻找轮廓:findContours;
3.描绘轮廓:drawContours。

2.1阈值法获取轮廓

其代码为:

def conters_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_OTSU | cv.THRESH_BINARY)# 用大律法、全局自适应阈值方法进行图像二值化
    cv.imshow("binary_image", binary)

    contours, heriachy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)    # RETR_TREE检测内部
    # contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)  # RETR_EXTERNAL检测外部轮廓
    for i, contour in enumerate(contours):
        cv.drawContours(image, contours, i, (0, 0, 255), 2)         # 绘制轮廓
        # cv.drawContours(image, contours, i, (0, 0, 255), -1)        # 填充轮廓
        print(i)
    cv.imshow("detect_contours", image)

原图为:

python 获取 Redirecting to python获取referer_opencv


经过二值化后:

python 获取 Redirecting to python获取referer_边缘提取_02


绘制其轮廓后:

python 获取 Redirecting to python获取referer_opencv_03

2.2使用Canny边缘检测获取轮廓

代码为:

def edge_demo(image):
    blur = cv.GaussianBlur(image, (3, 3), 0)        # 降低噪声
    gray = cv.cvtColor(blur, 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)
    cv.imshow("Canny_Edge", edge_output)
    return edge_output


def conters_demo(image):
    binary = edge_demo(image)

    contours, heriachy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)    # RETR_TREE检测内部
    # contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)  # RETR_EXTERNAL检测外部轮廓
    for i, contour in enumerate(contours):
        cv.drawContours(image, contours, i, (0, 0, 255), 2)         # 绘制轮廓
        # cv.drawContours(image, contours, i, (0, 0, 255), -1)        # 填充轮廓
        print(i)
    cv.imshow("detect_contours", image)

Canny边缘检测后的结果为:

python 获取 Redirecting to python获取referer_opencv_04


绘制其轮廓为:

python 获取 Redirecting to python获取referer_二值化_05

完整代码

import cv2 as cv                # 导入opencv模块
import numpy as np              # 导入数学函数库


def edge_demo(image):
    blur = cv.GaussianBlur(image, (3, 3), 0)        # 降低噪声
    gray = cv.cvtColor(blur, 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)
    cv.imshow("Canny_Edge", edge_output)
    return edge_output


def conters_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_OTSU | cv.THRESH_BINARY)# 用大律法、全局自适应阈值方法进行图像二值化
    cv.imshow("binary_image", binary)


    # binary = edge_demo(image)

    contours, heriachy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)    # RETR_TREE检测内部
    # contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)  # RETR_EXTERNAL检测外部轮廓
    for i, contour in enumerate(contours):
        cv.drawContours(image, contours, i, (0, 0, 255), 2)         # 绘制轮廓
        # cv.drawContours(image, contours, i, (0, 0, 255), -1)        # 填充轮廓
        print(i)
    cv.imshow("detect_contours", image)


print("------------hello python!------------")

src = cv.imread("D:/opencv3/image/huafen.jpg")
cv.namedWindow("input_image", cv.WINDOW_AUTOSIZE)
cv.imshow("input_image", src)
conters_demo(src)

cv.waitKey(0)
cv.destroyAllWindows()          # 释放所有窗口