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

使用OpenCV识别图像正方形时出现多目标合并问题求助

OpenCV正方形识别合并问题解决方法

问题核心原因

两个正方形被合并识别,本质是Canny边缘检测后边缘发生粘连,导致findContours将其识别为单个轮廓。你之前调整epsilon无效,是因为输入的轮廓本身就是合并后的,参数优化无法改变输入基础。

具体解决步骤

1. 修正多边形逼近的epsilon参数

你当前设置的0.34 * peri过大,会把多个轮廓的逼近结果合并成一个大形状。正方形的合理epsilon范围是0.02 * peri到0.05 * peri,同时可以通过顶点数+宽高比判断是否为正方形:

peri = cv.arcLength(cnt, True)
approx = cv.approxPolyDP(cnt, 0.03 * peri, True)
# 判断是否为正方形:4个顶点 + 宽高比接近1
if len(approx) == 4:
    aspect_ratio = float(w)/h
    if 0.95 < aspect_ratio < 1.05:
        cv.rectangle(imgContour, (x,y), (x+w,y+h), (0,255,0), 5)

2. 优化Canny阈值分离边缘

通过滑动条调整THRESH1(建议50-100)和THRESH2(建议100-150),观察Canny窗口直到两个正方形的边缘完全断开,无连通。

3. 增加形态学腐蚀断开粘连

如果阈值调整后仍有边缘粘连,在Canny检测后添加腐蚀操作:

kernel = np.ones((2,2), np.uint8)
Canny = cv.erode(Canny, kernel, iterations=1)

4. 修复图像复制的潜在问题

循环中img = read会直接引用原图像,导致后续修改污染原图,改为img = read.copy()。

修改后的完整代码

import cv2 as cv
import numpy as np

def empty(a):
    pass

cv.namedWindow("Params")
cv.resizeWindow("Params",640,240)
cv.createTrackbar("THRESH1","Params",80,255,empty)
cv.createTrackbar("THRESH2","Params",120,255,empty)
cv.createTrackbar("ERODE_ITER","Params",1,5,empty)

read = cv.imread("esult.jpg")

def getContours(img,imgContour):
    contours, herarchy = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    for cnt in contours:
        area = cv.contourArea(cnt)
        if area>1000:
            peri = cv.arcLength(cnt, True)
            approx = cv.approxPolyDP(cnt, 0.03 * peri, True)
            x,y,w,h = cv.boundingRect(approx)
            if len(approx) == 4:
                aspect_ratio = float(w)/h
                if 0.95 < aspect_ratio < 1.05:
                    cv.rectangle(imgContour, (x,y), (x+w,y+h), (0,255,0), 5)
                    # 绘制顶点便于观察
                    for point in approx:
                        cv.circle(imgContour, tuple(point[0]), 5, (0,0,255), -1)

while(1):
    img = read.copy()
    imgContour = img.copy()
    gs = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    threshold1 = cv.getTrackbarPos("THRESH1","Params")
    threshold2 = cv.getTrackbarPos("THRESH2","Params")
    erode_iter = cv.getTrackbarPos("ERODE_ITER","Params")
    Canny = cv.Canny(gs,threshold1,threshold2)
    kernel = np.ones((2,2), np.uint8)
    Canny = cv.erode(Canny, kernel, iterations=erode_iter)
    getContours(Canny,imgContour)
    cv.imshow('gs', gs)
    cv.imshow('read',imgContour)
    cv.imshow('canny', Canny)
    if cv.waitKey(1) & 0xFF == ord('q'):
        break
cv.destroyAllWindows()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 06:37:27