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
相关产品推荐
相关产品推荐

