0
点赞
收藏
分享

微信扫一扫

使用 Python OpenCV 实现图像形状检测


概述

图像形状检测是计算机视觉中的一个重要任务,广泛应用于物体识别、机器人导航等领域。本文将详细介绍如何使用 Python 和 OpenCV 实现图像形状检测,包括读取图像、预处理图像、查找轮廓、绘制轮廓以及形状分类。通过本文的学习,你将能够理解和实现一个完整的图像形状检测系统。

环境准备

确保你已经安装了 OpenCV 库。如果没有安装,可以使用以下命令进行安装:

pip install opencv-python

此外,准备好一张包含不同形状的图像文件 shapes.png,用于形状检测。

示例详解

import cv2

from utils import img_stack_util


def get_contours(img, img_contour):
    """
    获取轮廓
    :param img: 预处理图(灰度高斯模糊图)
    :param img_contour: 原图副本,绘制轮廓
    :return:
    """
    # 寻找轮廓
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        # 计算轮廓区域面积
        area = cv2.contourArea(cnt)
        print(area)
        if area > 500:
            # 面积大于500
            # 绘制轮廓
            cv2.drawContours(img_contour, cnt, -1, (255, 0, 0), 3)
            # 计算曲线周长(轮廓曲线,是否封闭)
            perimeter = cv2.arcLength(curve=cnt, closed=True)
            print(perimeter)
            # 近似多边曲线(轮廓曲线,逼近精度[值越小,两线最大距离越小,折线越多,多边形边数越多],是否封闭),返回定点向量
            approx = cv2.approxPolyDP(curve=cnt, epsilon=0.02*perimeter, closed=True)
            print(approx)
            # 多边形角数
            obj_cor = len(approx)
            print(obj_cor)
            # 计算灰度图像边距
            x, y, w, h = cv2.boundingRect(approx)

            # 根据角数判断形状
            if obj_cor == 3:
                object_type = "Tri"
            elif obj_cor == 4:
                asp_ratio = w/float(h)
                if 1.03 > asp_ratio > 0.98:
                    object_type = "Square"
                else:
                    object_type = "Rectangle"
            elif obj_cor > 4:
                object_type = "Circles"
            else:
                object_type = "None"

            # 绘制矩形边框
            cv2.rectangle(img_contour, (x, y), (x+w, y+h), (0, 255, 0), 2)
            # 边框左下角绘制文字
            cv2.putText(img_contour, object_type,
                        (x, y + h), cv2.FONT_HERSHEY_COMPLEX, 0.7,
                        (0, 0, 0), 2)


def start():
    """
    入口
    :return:
    """
    img = cv2.imread(r'./resources/shapes.png')  # 读取原始图像
    # 副本
    img_contour = img.copy()

    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换为灰度图像
    # 高斯模糊,降噪
    img_blur = cv2.GaussianBlur(img_gray, ksize=(7, 7), sigmaX=1)
    img_canny = cv2.Canny(img_blur, 40, 40)  # Canny边缘检测
    get_contours(img_canny, img_contour)  # 获取轮廓并绘制

    img_stack = img_stack_util.stack_img(
        img_arr=([img, img_gray, img_blur],
                 [img_canny, img_contour]),
        scale=0.6,
        labels=(['origin', 'gray', 'blur'],
                ['canny', 'contour'])
    )

    cv2.imshow("Stack", img_stack)  # 显示图像堆栈

    cv2.waitKey(0)  # 等待用户按键
    cv2.destroyAllWindows()  # 关闭所有窗口


if __name__ == '__main__':
    start()

代码详解
1. 导入必要的库

import cv2
from utils import img_stack_util

  • import cv2:导入 OpenCV 库,用于图像处理和显示。
  • from utils import img_stack_util:导入自定义的图像堆叠工具函数 img_stack_util,用于将多个图像堆叠在一起显示。
2. 定义 get_contours 函数

def get_contours(img, img_contour):
    """
    获取轮廓
    :param img: 预处理图(灰度高斯模糊图)
    :param img_contour: 原图副本,绘制轮廓
    :return:
    """
    # 寻找轮廓
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        # 计算轮廓区域面积
        area = cv2.contourArea(cnt)
        print(area)
        if area > 500:
            # 面积大于500
            # 绘制轮廓
            cv2.drawContours(img_contour, cnt, -1, (255, 0, 0), 3)
            # 计算曲线周长(轮廓曲线,是否封闭)
            perimeter = cv2.arcLength(curve=cnt, closed=True)
            print(perimeter)
            # 近似多边曲线(轮廓曲线,逼近精度[值越小,两线最大距离越小,折线越多,多边形边数越多],是否封闭),返回定点向量
            approx = cv2.approxPolyDP(curve=cnt, epsilon=0.02*perimeter, closed=True)
            print(approx)
            # 多边形角数
            obj_cor = len(approx)
            print(obj_cor)
            # 计算灰度图像边距
            x, y, w, h = cv2.boundingRect(approx)

            # 根据角数判断形状
            if obj_cor == 3:
                object_type = "Tri"
            elif obj_cor == 4:
                asp_ratio = w/float(h)
                if 1.03 > asp_ratio > 0.98:
                    object_type = "Square"
                else:
                    object_type = "Rectangle"
            elif obj_cor > 4:
                object_type = "Circles"
            else:
                object_type = "None"

            # 绘制矩形边框
            cv2.rectangle(img_contour, (x, y), (x+w, y+h), (0, 255, 0), 2)
            # 边框左下角绘制文字
            cv2.putText(img_contour, object_type,
                        (x, y + h), cv2.FONT_HERSHEY_COMPLEX, 0.7,
                        (0, 0, 0), 2)

  • cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE):寻找图像中的轮廓,cv2.RETR_EXTERNAL 表示只检索外部轮廓,cv2.CHAIN_APPROX_NONE 表示存储所有的轮廓点。
  • cv2.contourArea(cnt):计算轮廓的面积。
  • cv2.drawContours(img_contour, cnt, -1, (255, 0, 0), 3):在原图副本 img_contour 上绘制轮廓,颜色为蓝色,线条宽度为 3。
  • cv2.arcLength(curve=cnt, closed=True):计算轮廓的周长。
  • cv2.approxPolyDP(curve=cnt, epsilon=0.02*perimeter, closed=True):近似多边曲线,epsilon 参数控制逼近精度。
  • len(approx):计算多边形的角数。
  • cv2.boundingRect(approx):计算轮廓的边界矩形。
  • cv2.rectangle(img_contour, (x, y), (x+w, y+h), (0, 255, 0), 2):在原图副本 img_contour 上绘制矩形边框,颜色为绿色,线条宽度为 2。
  • cv2.putText(img_contour, object_type, (x, y + h), cv2.FONT_HERSHEY_COMPLEX, 0.7, (0, 0, 0), 2):在矩形边框的左下角绘制形状类型文字。
3. 定义 start 函数

def start():
    """
    入口
    :return:
    """
    img = cv2.imread(r'./resources/shapes.png')  # 读取原始图像
    # 副本
    img_contour = img.copy()

    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换为灰度图像
    # 高斯模糊,降噪
    img_blur = cv2.GaussianBlur(img_gray, ksize=(7, 7), sigmaX=1)
    img_canny = cv2.Canny(img_blur, 40, 40)  # Canny边缘检测
    get_contours(img_canny, img_contour)  # 获取轮廓并绘制

    img_stack = img_stack_util.stack_img(
        img_arr=([img, img_gray, img_blur],
                 [img_canny, img_contour]),
        scale=0.6,
        labels=(['origin', 'gray', 'blur'],
                ['canny', 'contour'])
    )

    cv2.imshow("Stack", img_stack)  # 显示图像堆栈

    cv2.waitKey(0)  # 等待用户按键
    cv2.destroyAllWindows()  # 关闭所有窗口

  • cv2.imread(r'./resources/shapes.png'):读取原始图像 shapes.png
  • img.copy():创建原图的副本,用于绘制轮廓。
  • cv2.cvtColor(img, cv2.COLOR_BGR2GRAY):将图像从 BGR 格式转换为灰度格式。
  • cv2.GaussianBlur(img_gray, ksize=(7, 7), sigmaX=1):对灰度图像进行高斯模糊,以减少噪声。
  • cv2.Canny(img_blur, 40, 40):使用 Canny 边缘检测算法检测图像边缘。
  • get_contours(img_canny, img_contour):调用 get_contours 函数,获取轮廓并在原图副本上绘制。
  • img_stack_util.stack_img:使用自定义的图像堆叠工具函数,将多个图像堆叠在一起显示。
  • cv2.imshow("Stack", img_stack):在窗口中显示图像堆栈。
  • cv2.waitKey(0):等待用户按键。
  • cv2.destroyAllWindows():关闭所有 OpenCV 窗口。
运行效果展示

假设我们有一张包含不同形状的图像 shapes.png

使用 Python OpenCV 实现图像形状检测_OpenCV

运行上述代码后,生成的结果图像如下所示:

使用 Python OpenCV 实现图像形状检测_python_02

总结

本文详细介绍了如何使用 Python 和 OpenCV 实现图像形状检测,包括读取图像、预处理图像、查找轮廓、绘制轮廓以及形状分类。通过理解这些基本概念和技术,你可以更加灵活地在图像处理和物体识别中应用 OpenCV。


举报

相关推荐

0 条评论