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

如何用cv2.minAreaRect获取存在断裂区域图像的最大轮廓?

问题描述

原始图像:
原始图像

希望用cv2.minAreaRect获取下图所示的最大轮廓:
目标轮廓

尝试1 - 失败

结果图:
尝试1结果

代码:

cnt, hierarchy  = cv2.findContours(im_bw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
min_rect = cv2.minAreaRect(cnt[0])
box = np.int0(cv2.boxPoints(min_rect))
cv2.drawContours(temp_result, [box], 0, (255, 0, 0), 2)

尝试2 - 失败

参考相关文章实现有序坐标绘制,但结果线条不匹配,且四点无法用于cv2.minAreaRect:
尝试2结果

代码:

def order_points(pts):
    # 初始化有序坐标列表,顺序为左上、右上、右下、左下
    rect = np.zeros((4, 2), dtype = "float32")

    # 左上角点的横纵坐标和最小,右下角点的和最大
    s = np.sum(pts, axis = 1)
    rect[0] = pts[np.argmin(s)] # 左上
    rect[2] = pts[np.argmax(s)] # 右下

    # 右上角点的横纵坐标差最小,左下角点的差最大
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)] # 右上
    rect[3] = pts[np.argmax(diff)] # 左下

    # 返回有序坐标
    return rect
#########################################################################
# pts = [(93, 50), (109, 82), (76, 47), (93, 77), (58, 38), (76, 72), (36, 32), (54, 67), (20, 27), (35, 62), (3, 22), (18, 56), (111, 54), (128, 87)]

t = order_points(pts)
cv2.line(temp_result, pt1=(int(t[0][0]), int(t[0][1])), pt2=(int(t[1][0]), int(t[1][1])), color=(0, 0, 255), thickness=2)
cv2.line(temp_result, pt1=(int(t[3][0]), int(t[3][1])), pt2=(int(t[2][0]), int(t[2][1])), color=(0, 0, 255), thickness=2)
解决方案

核心问题分析

  1. 尝试1直接取了第一个轮廓cnt[0],但该轮廓并非图像中面积最大的目标轮廓;
  2. 尝试2误用了透视变换的点排序逻辑,cv2.minAreaRect需要传入完整的轮廓数据,而非零散点集。

正确实现步骤

方法1:从二值图像中提取最大轮廓并绘制最小外接矩形

import cv2
import numpy as np

# 假设im_bw是你的二值图像,temp_result是用于绘制的彩色/灰度图像
cnt, hierarchy = cv2.findContours(im_bw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 筛选出面积最大的轮廓
max_contour = max(cnt, key=cv2.contourArea)

# 计算最小外接矩形
min_rect = cv2.minAreaRect(max_contour)
# 将矩形的四个角点转换为整数格式
box = np.int0(cv2.boxPoints(min_rect))

# 在结果图上绘制矩形
cv2.drawContours(temp_result, [box], 0, (255, 0, 0), 2)

方法2:针对零散点集生成最小外接矩形

如果你的输入是类似尝试2中的零散点列表,需要先将其转换为OpenCV轮廓的格式(形状为(N,1,2)的numpy数组),再传入cv2.minAreaRect:

import cv2
import numpy as np

# 你的零散点列表
pts = [(93, 50), (109, 82), (76, 47), (93, 77), (58, 38), (76, 72), (36, 32), (54, 67), (20, 27), (35, 62), (3, 22), (18, 56), (111, 54), (128, 87)]

# 转换为OpenCV接受的轮廓格式
pts_contour = np.array(pts, dtype=np.int32).reshape((-1, 1, 2))

# 计算并绘制最小外接矩形
min_rect = cv2.minAreaRect(pts_contour)
box = np.int0(cv2.boxPoints(min_rect))
cv2.drawContours(temp_result, [box], 0, (0, 0, 255), 2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:21:26