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

如何在含噪声背景的育苗盆图像中检测并分割正方形花盆

育苗区正方形花盆分割问题

我有多张育苗区图像,想编写代码分割每个正方形花盆并保存。目前的处理流程是转灰度图、高斯模糊去噪、阈值二值化,但用cv.findContours检测时,没法精准识别每个花盆的边界,只能获取图像角落点,现有代码效果很差。之前搜的方案大多针对光照对比度充足的场景,不适用当前情况。

相关图像:原图、二值化图、结果图。

现有代码如下:

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
edges = cv2.Canny(blurred, 10, 50)

thresh = cv2.adaptiveThreshold(gray, 400, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 4)
lines = cv2.HoughLines(thresh, rho=1, theta=np.pi/180, threshold=100)
contours, hierarchy = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 
squares = []
for contour in contours:
    peri = cv2.arcLength(contour, True)
    approx = cv2.approxPolyDP(contour, 0.02 * peri, True)
    if len(approx) == 4:
        x, y, w, h = cv2.boundingRect(approx)
        aspect_ratio = float(w) / h
        if 0.98 <= aspect_ratio <= 1:  # Adjust this range as per your requirement
            squares.append(approx)
# Draw squares on the original image
for square in squares:
    cv2.drawContours(image, [square], -1, (0, 255, 0), 2)

改进方案

针对光照不足、对比度低的场景,调整处理流程,重点强化花盆的网格线条,再提取轮廓:

步骤调整

  • 灰度与模糊优化:用更大的高斯模糊核减少噪声,同时保留线条特征
  • 阈值处理替换:改用cv2.THRESH_BINARY_INV反转阈值,让花盆边框变为前景
  • 形态学操作强化线条:用膨胀+腐蚀的组合(闭运算)填补线条间隙,再用开运算去除小噪点
  • 轮廓筛选优化:调整轮廓近似参数,加入面积筛选,排除过小或过大的轮廓

改进代码

import cv2
import numpy as np

def segment_pots(image_path):
    # 读取图像
    image = cv2.imread(image_path)
    if image is None:
        return
    
    # 转灰度
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # 高斯模糊,增大核尺寸减少噪声
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    
    # 自适应阈值,反转二值化,让边框为白色
    thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                                   cv2.THRESH_BINARY_INV, 11, 2)
    
    # 形态学操作:先闭运算填补线条间隙,再开运算去噪点
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
    opened = cv2.morphologyEx(closed, cv2.MORPH_OPEN, kernel, iterations=1)
    
    # 提取轮廓,用RETR_EXTERNAL只取最外层轮廓
    contours, hierarchy = cv2.findContours(opened.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    squares = []
    # 获取图像尺寸,计算花盆面积的合理范围(根据实际场景调整)
    img_h, img_w = gray.shape
    min_area = (img_w // 10) * (img_h // 10)  # 假设至少是图像1/100大小
    max_area = (img_w // 2) * (img_h // 2)    # 不超过图像1/4大小
    
    for contour in contours:
        # 计算轮廓周长
        peri = cv2.arcLength(contour, True)
        # 轮廓近似,调整参数为0.03*peri,适配低对比度场景
        approx = cv2.approxPolyDP(contour, 0.03 * peri, True)
        
        # 筛选四边形、合理宽高比、面积范围
        if len(approx) == 4:
            x, y, w, h = cv2.boundingRect(approx)
            aspect_ratio = float(w) / h
            area = w * h
            if 0.9 <= aspect_ratio <= 1.1 and min_area < area < max_area:
                squares.append(approx)
                # 裁剪并保存花盆图像
                pot_img = image[y:y+h, x:x+w]
                cv2.imwrite(f"pot_{x}_{y}.jpg", pot_img)
    
    # 在原图绘制检测到的花盆边框
    cv2.drawContours(image, squares, -1, (0, 255, 0), 2)
    cv2.imwrite("result.jpg", image)
    return image

# 使用示例
segment_pots("seedling_area.jpg")

关键调整说明

  • 形态学操作:闭运算能把断开的花盆边框连接起来,开运算可以去掉小的噪点轮廓,解决低对比度下线条断裂的问题
  • 轮廓筛选:加入面积范围过滤,排除图像角落的大轮廓和小噪点,只保留花盆大小的轮廓
  • 阈值反转:让原本深色的边框变为白色前景,更适合轮廓检测
  • 轮廓近似参数:把0.02调整为0.03,对低对比度下的不规则轮廓更友好

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 19:03:18