You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OpenCV从左到右扫描图像时,如何提取首个闭合圆形ROI?

问题描述

目标图像:
input image

尝试用OpenCV从左到右扫描图像,仅提取其中第一个闭合圆形区域,但现有代码选中的是字符的整个外边缘,而非目标ROI。现有代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def find_closed_round_areas(image_path):
    # Load the image
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

    # Apply binary thresholding
    _, thresh = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY_INV)

    # Find contours
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # Create a color version of the original image
    color_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)

    # Filter and highlight closed round contours
    highlighted_image = color_image.copy()
    for contour in contours:
        if cv2.contourArea(contour) > 100:  # Filter out small contours
            perimeter = cv2.arcLength(contour, True)
            circularity = 4 * np.pi * cv2.contourArea(contour) / (perimeter ** 2)
            if circularity > 0.7:  # Filter based on circularity
                cv2.drawContours(highlighted_image, [contour], -1, (0, 255, 0), thickness=2)  # Green color in BGR

    # Display the original and highlighted images
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.title('Original Image')
    plt.imshow(cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB))
    plt.subplot(1, 2, 2)
    plt.title('Highlighted Closed Round Areas')
    plt.imshow(cv2.cvtColor(highlighted_image, cv2.COLOR_BGR2RGB))
    plt.show()

# Path to the image
image_path = '/mnt/data/ROI_65.png'

# Find and highlight the closed round areas
find_closed_round_areas(image_path)
修改方案

问题核心原因:

  1. 原代码用cv2.RETR_EXTERNAL仅提取最外层轮廓,无法获取字符内部的圆形轮廓
  2. 未按从左到右的顺序筛选轮廓,也没有限制只保留第一个目标

针对性修改步骤:

  • 更换轮廓检索模式为cv2.RETR_TREE,提取所有层级的轮廓(包括内部圆形)
  • 通过轮廓的外接矩形x坐标排序,实现从左到右的查找顺序
  • 增加层级判断过滤最外层大轮廓,同时用面积、圆形度筛选目标,找到第一个符合条件的区域后立即停止遍历
修改后的完整代码
import cv2
import numpy as np
import matplotlib.pyplot as plt

def find_first_left_closed_round_area(image_path):
    # 加载灰度图像
    image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

    # 二值化处理(反转后黑色为前景)
    _, thresh = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY_INV)

    # 提取所有层级的轮廓及层级信息
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    # 创建彩色图像用于可视化
    color_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
    highlighted_image = color_image.copy()

    # 筛选符合条件的圆形轮廓
    valid_contours = []
    for idx, contour in enumerate(contours):
        area = cv2.contourArea(contour)
        # 过滤过小/过大轮廓,且通过层级判断排除最外层轮廓(hierarchy[0][idx][3] != -1表示有父轮廓)
        if 50 < area < 500 and hierarchy[0][idx][3] != -1:
            perimeter = cv2.arcLength(contour, True)
            circularity = 4 * np.pi * area / (perimeter ** 2)
            # 圆形度阈值可根据实际图像调整
            if circularity > 0.8:
                # 获取轮廓外接矩形的x坐标,用于排序
                x, _, _, _ = cv2.boundingRect(contour)
                valid_contours.append((x, contour))

    # 按x坐标从小到大排序,确保从左到右查找
    valid_contours.sort(key=lambda item: item[0])

    # 标记并提取第一个目标ROI
    if valid_contours:
        _, target_contour = valid_contours[0]
        cv2.drawContours(highlighted_image, [target_contour], -1, (0, 255, 0), thickness=2)
        # 获取ROI坐标并提取
        x, y, w, h = cv2.boundingRect(target_contour)
        roi = image[y:y+h, x:x+w]

        # 展示结果
        plt.figure(figsize=(12, 6))
        plt.subplot(1, 3, 1)
        plt.title('原始图像')
        plt.imshow(cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB))
        plt.subplot(1, 3, 2)
        plt.title('标记后的目标区域')
        plt.imshow(cv2.cvtColor(highlighted_image, cv2.COLOR_BGR2RGB))
        plt.subplot(1, 3, 3)
        plt.title('提取的ROI')
        plt.imshow(roi, cmap='gray')
        plt.show()
    else:
        print("未找到符合条件的闭合圆形区域")

# 图像路径
image_path = '/mnt/data/ROI_65.png'

# 执行查找与提取
find_first_left_closed_round_area(image_path)

内容的提问来源于stack exchange,提问作者Ayyoob areacode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:06:13