OpenCV机器视觉-边缘与轮廓

边缘与轮廓


  • 基于图像边缘提取或二值化的基础寻找对象轮廓
  • 边缘提取的阈值会最终影响轮廓发现的结果
  • 主要API要有以下俩个
    1. findContours发现轮廓
    2. drawContours绘制轮廓

查找轮廓


处理的图像,轮廓列表,继承关系 = cv.findContours(图像,轮廓检索模式,检索的方法)

# hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号
  • 轮廓检索模式
RETR_EXTERNAL 只检测最外层轮廓
RETR_LIST 提取所有轮廓,并放置在list中,检测的轮廓不建立等级关系
RETR_CCOMP 提取所有轮廓,并将轮廓组织成双层结构(two-level hierarchy),顶层为连通域的外围边界,次层位内层边界
RETR_TREE 提取所有轮廓并重新建立网状轮廓结构
  • 轮廓检索算法
CHAIN_APPROX_NONE 获取每个轮廓的每个像素,相邻的两个点的像素位置差不超过1
CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息
CHAIN_APPROX_TC89_L1 Teh-Chinl链逼近算法
CHAIN_APPROX_TC89_KCOS Teh-Chinl链逼近算法

绘制轮廓


cv.drawContours(图像,轮廓列表,轮廓索引-1则绘制所有,轮廓颜色,轮廓的宽度)

绘制外切圆


cv.drawContours(图像,轮廓列表,轮廓索引-1则绘制所有,轮廓颜色,轮廓的宽度)

实现步骤:

  1. 读取图片
  2. 将图片转换成一张灰色图片
  3. 对图片进行二值化处理
  4. 使用findContours查找轮廓
  5. 对轮廓进行处理

示例代码

import cv2 as cv


def read_rgb_img(img_name):
    rgb_img = cv.imread(img_name, cv.IMREAD_COLOR)
    cv.imshow("rgb img", rgb_img)
    return rgb_img


def convert_rgb2gray(img):
    gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    cv.imshow("gray img", gray_img)
    return gray_img


def convert_gray2binary(img):
    binary_img = cv.adaptiveThreshold(img,
                                      255,
                                      cv.ADAPTIVE_THRESH_GAUSSIAN_C,
                                      cv.THRESH_BINARY, 5, 2)
    # _,binary_img = cv.threshold(img,50,255,cv.THRESH_BINARY_INV)
    cv.imshow("binary img", binary_img)
    return binary_img


def getContours(img):
    _, contours, hierarchy = cv.findContours(img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
    print(contours, hierarchy)
    return contours


def draw_contours(img, contours):
    index = -1  # 所有的轮廓
    thickness = 2  # 轮廓的宽度
    color = (255, 125, 125)  # 轮廓的颜色
    cv.drawContours(img, contours, index, color, thickness)
    cv.imshow('draw contours', img)


if __name__ == '__main__':
    img_name = "img/shape0.jpg"

    rgb_img = read_rgb_img(img_name)
    gray_img = convert_rgb2gray(rgb_img)
    binary_imgage = convert_gray2binary(gray_img)
    contours = getContours(binary_imgage)
    draw_contours(rgb_img, contours)

    cv.waitKey(0)
    cv.destroyAllWindows()

网球案例


实现步骤:

  1. 读取图片
  2. 过滤出球的颜色
  3. 使用轮廓检测
  4. 找到球的中心点
  5. 展示信息

示例代码

import cv2 as cv
import numpy as np


def read_rgb_img(img_name):
    rgb_img = cv.imread(img_name, cv.IMREAD_COLOR)
    cv.imshow("rgb img", rgb_img)
    return rgb_img


def convert_rgb2gray(img):
    gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 采用高斯滤波去掉噪点
    gray_img = cv.GaussianBlur(gray_img, (5, 5), 0)
    cv.imshow("gray img", gray_img)

    return gray_img


def convert_gray2binary(img):
    binary_img = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 5, 2)
    cv.imshow("binary img", binary_img)
    return binary_img


def filter_tenis(img, lower_color, upper_color):
    hsv_img = cv.cvtColor(img, cv.COLOR_BGR2HSV)
    # 查找颜色
    mask_img = cv.inRange(hsv_img, lower_color, upper_color)
    cv.imshow("mask img", mask_img)
    return mask_img


def getContours(img):
    # 这里只需要传入俩个参数即可 高斯模糊
    contours, hierarchy = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    print(contours, hierarchy)
    return contours


def process_tenis_contours(rgb_img, contours):
    black_img = np.zeros([rgb_img.shape[0], rgb_img.shape[1], 3], np.uint8)

    for c in contours:
        # 计算面积
        area = cv.contourArea(c)
        # 该函数计算曲线长度或闭合轮廓周长。
        perimeter = cv.arcLength(c, True)
        # 获取最小的外切圆
        ((x, y), radius) = cv.minEnclosingCircle(c)

        # 绘制轮廓
        cv.drawContours(rgb_img, [c], -1, (150, 250, 150), 2)
        cv.drawContours(black_img, [c], -1, (150, 250, 150), 2)
        # 获取轮廓中心点
        # cx,cy = get_contour_center(c)
        # print(cx,cy)
        x = int(x)
        y = int(y)
        cv.circle(rgb_img, (x, y), int(radius), (0, 0, 255), 2)
        cv.circle(black_img, (x, y), int(radius), (0, 0, 255), 2)

        print("Area:{},primeter:{}".format(area, perimeter))

    print("number of contours:{}".format(len(contours)))
    cv.imshow("rgb img contours", rgb_img)
    cv.imshow("black img contours", black_img)


if __name__ == '__main__':
    img_name = "img/tenis1.jpg"
    # 定义范围
    lower_color = (30, 120, 130)
    upper_color = (60, 255, 255)

    rgb_img = read_rgb_img(img_name)
    binary_imgage = filter_tenis(rgb_img, lower_color, upper_color)

    contours = getContours(binary_imgage)
    process_tenis_contours(rgb_img, contours)

    cv.waitKey(0)
    cv.destroyAllWindows()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45946270/article/details/124835743