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

Plant Village数据集叶片去背景:如何判断Id图像的(x,y)像素是否为边缘

提问内容

我正在对叶片数据集做背景去除处理,调研过程中找到了相关论文,其中描述的植物前景与背景分离步骤如下:
背景提取步骤

但我不清楚如何判断像素(x,y)是否处于Id的边缘位置。目前我已经实现了前面的步骤,代码如下:

import numpy as np
import cv2
import skimage.morphology as morph

image = cv2.imread(filename)
height, width, _ = image.shape
Ihsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
Is = Ihsv[:,:,2]

#Apply Spacial Gaussian Filter
trunc_val = 2
sigma_val = 2
k_size = int(sigma_val * trunc_val)
Ifg = cv2.GaussianBlur(Is, (k_size,k_size), sigma_val)
A = np.zeros((height, width), dtype=np.uint8)
for h in range(0, height):
    for w in range(0, width):
        if Ifg[h, w] > 0.23:
            A[h, w] = 1

#Apply Morphological Operations
kernelD2 = morph.diamond(2)
kernelD3 = morph.diamond(3)
Ie = cv2.erode(A, kernelD2)
Id = cv2.dilate(Ie, kernelD3)
回答

Id是你已经得到的二值掩码(前景为1,背景为0),判断边缘像素有三种常用实现方案,你可以根据需求选择:

  • 方案1:Canny边缘检测
    先把Id转成标准8位灰度图再做Canny检测,得到的非零像素就是边缘点:
    edge_canny = cv2.Canny(Id * 255, threshold1=50, threshold2=150)
    # 判断(x,y)是否为边缘:edge_canny[y, x] > 0 即为边缘
    
  • 方案2:形态学梯度
    用膨胀结果减去腐蚀结果,得到的高亮区域就是边缘:
    kernel = morph.diamond(1)
    dilate = cv2.dilate(Id, kernel)
    erode = cv2.erode(Id, kernel)
    edge_gradient = dilate - erode
    # 判断(x,y)是否为边缘:edge_gradient[y, x] == 1 即为边缘
    
  • 方案3:轮廓提取
    直接提取Id的外轮廓,轮廓上的所有点就是边缘坐标:
    contours, _ = cv2.findContours(Id.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    # 合并所有轮廓点得到全部边缘坐标
    edge_points = np.concatenate(contours).squeeze()
    # 判断(x,y)是否为边缘:将edge_points转成集合后查询效率更高
    

另外你当前生成二值掩码A的部分用了双层for循环,可以用numpy向量化操作替代,运行速度会提升很多:

# 替换原有双层循环即可
A = (Ifg > 0.23).astype(np.uint8)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 11:06:03