020 OpenCV 轮廓、外接圆、外接矩形

一、环境

本文使用环境为:

  • Windows10
  • Python 3.9.17
  • opencv-python 4.8.0.74

二、原理

2.1 函数接口

OpenCV中的findContours函数用于检测图像中的轮廓。轮廓是图像中连续的点集,它们通常表示物体的边缘或形状。在计算机视觉和图像处理中,轮廓分析是一种常见的任务,例如目标检测、形状识别等。

findContours函数的基本语法如下:

python 复制代码
contours, hierarchy = cv.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

参数说明:

  • image:输入图像,通常是一个二值图像。
  • mode:轮廓检索模式。这个参数决定了函数如何返回轮廓。常见的模式有:
    • cv2.RETR_EXTERNAL:只检索最外层的轮廓。
    • cv2.RETR_LIST:检索所有轮廓并将其保存到列表中。
    • cv2.RETR_CCOMP:检索所有轮廓,并将它们组织到两个不同的层次结构中(例如,外部和内部)。
    • cv2.RETR_TREE:检索所有轮廓,并将它们组织到一个层次结构中。
  • method:轮廓的近似方法。常见的有:
    • cv2.CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角分段。
    • cv2.CHAIN_APPROX_NONE:存储所有的段(4点)。
    • cv2.CHAIN_APPROX_SIMPLEcv2.CHAIN_APPROX_DP:使用动态规划压缩轮廓。
  • contours(可选):输出参数,返回找到的轮廓。
  • hierarchy(可选):输出参数,返回有关轮廓之间关系的信息。
  • offset(可选):偏移量,用于调整轮廓的位置。

返回值:

  • 如果指定了 contours 参数,则返回找到的轮廓。
  • 如果指定了 hierarchy 参数,则返回有关轮廓之间关系的信息。

2.2 原理理解

在OpenCV库中,函数cv2.findContours()是一个用于查找图像中物体轮廓的重要工具。该函数的主要参数包括:输入图像、轮廓检索模式和近似方法等。

首先,输入的图像通常是二值化的单通道图像,其中黑色代表背景,白色代表目标物体。这样的图像通常通过Canny或拉普拉斯等边缘检测算子进行处理得到。

其次,轮廓检索模式决定了如何处理图像中的轮廓。例如,cv2.RETR_EXTERNAL只检测外轮廓;cv2.RETR_LIST检测的轮廓不建立等级关系;cv2.RETR_CCOMP建立两个等级的轮廓,上一层为外边界,内层为内孔的边界;而cv2.RETR_TREE则建立一个等级树结构的轮廓。

最后,近似方法决定了如何简化轮廓。例如,cv2.CHAIN_APPROX_SIMPLE就表示用尽可能少的像素点表示轮廓。

函数的返回值包括两个部分:contours和hierarchy。其中,contours是一个包含所有检测到的轮廓信息的数组,每个轮廓又是由若干个点所构成的;而hierarchy则是一个包含了各轮廓之间的层次关系的数组。

三、完整代码

python 复制代码
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng

rng.seed(12345)

def thresh_callback(val):
    threshold = val
    # 使用canny检测边缘
    canny_output = cv.Canny(src_gray, threshold, threshold * 2)
    # 查找轮廓
    contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
    

    # 这里在分配空间
    contours_poly = [None]*len(contours)
    boundRect = [None]*len(contours)
    centers = [None]*len(contours)
    radius = [None]*len(contours) 

    # 依据canny检测出来的边缘,下面查找边缘的轮廓、边缘的外接圆、外接矩形
    for i, c in enumerate(contours):
        contours_poly[i] = cv.approxPolyDP(c, 3, True) # 轮廓
        boundRect[i] = cv.boundingRect(contours_poly[i]) # 外接矩形
        centers[i], radius[i] = cv.minEnclosingCircle(contours_poly[i]) # 外接圆
   
    # 搞一张黑色的图,用于绘制
    drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
    
    # 绘制轮廓、矩形、圆
    for i in range(len(contours)):
        color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
        cv.drawContours(drawing, contours_poly, i, color)
        cv.rectangle(drawing, (int(boundRect[i][0]), int(boundRect[i][1])), \
          (int(boundRect[i][0]+boundRect[i][2]), int(boundRect[i][1]+boundRect[i][3])), color, 2)
        cv.circle(drawing, (int(centers[i][0]), int(centers[i][1])), int(radius[i]), color, 2) 
    cv.imshow('Contours', drawing)

parser = argparse.ArgumentParser(description='Code for Creating Bounding boxes and circles for contours tutorial.')
parser.add_argument('--input', help='Path to input image.', default='data/stuff.jpg')
args = parser.parse_args()
# 读取图片
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
    print('Could not open or find the image:', args.input)
    exit(0)

# 彩色图转灰度图
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 图片平滑
src_gray = cv.blur(src_gray, (3,3))

# 显示原彩色图
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)

# 创建滑条,控制canny查找边缘的阈值
max_thresh = 255
thresh = 100 # canny初始化阈值
cv.createTrackbar('Canny thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)

cv.waitKey()
相关推荐
cxr8288 分钟前
上下文工程框架之11 模块与优先级链和冲突消解、淘汰与版本
人工智能·架构
Cosolar12 分钟前
DeepSeek Harness 理解 Harness 的设计哲学 - 可组合的插件运行时
人工智能·设计模式·架构
DFT计算杂谈17 分钟前
Janus单层Cr2SSe中的应变可调多压电效应与谷电子学
人工智能·算法·机器学习
今天AI了吗18 分钟前
从 LLM 到 Agent Skill:把 AI 底层概念串起来
数据库·人工智能·sql·深度学习·神经网络·算法·机器学习
DS随心转小程序18 分钟前
巧用 AI 导出鸭攻克各类难题完善 ChatGPT 输出 word 文档转化工作
人工智能·chatgpt·aigc·word·豆包·deepseek·ai导出鸭
梦想的旅途222 分钟前
企微 API 二次开发:结合 AI 打造考勤打卡与报表智能分析系统
人工智能·企业微信
Kari1123 分钟前
腾讯云 ADP 实施问题解析:回答异常时企业如何组织排查与支持协同?
人工智能
刘新洲24 分钟前
别再只做会聊天的 Agent:我用 1 天把工具调用做成了可验证、可评测的工程系统
人工智能·python·openai
码云骑士25 分钟前
102-向量数据增删改查-增量更新-过期策略-向量漂移重索引
python
小唔w26 分钟前
文件越攒越多?三步分类归档法 + 常用工具体验分享
人工智能