改进图像分割,在我的目标周围创建一个封闭的轮廓

2024-05-15 09:04:29 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我从Intel Realsense d435 rgb相机拍摄的场景照片。 enter image description here

我希望能够识别图像中的金属物体,并在其周围绘制闭合轮廓。这样我可以引用轮廓内的所有像素供将来使用。

当前方法

  1. 目前,我正在裁剪场景图像,假装我有一些对象识别软件在运行,允许我在我的对象周围创建一个边界框。所以我裁剪了这个部分,并将它应用到一个空白图像上。在

Cropped Image with threshold applied

  1. 我遵循OpenCV文档,使用形态学变换和分水岭算法对图像进行分割。最后,我提取出可靠的前景图像并运行canny边缘检测和轮廓检测。然而,他们返回的线路相当差。在

2.5条。目前,我使用的是确定的前景图像,并将所有的黑色像素保存为对象,但是,我的确定前景图像中有这些巨大的白点,它们没有被提取。

Sure Foreground image with white spotsContours of my edges after filtering (bad)

如何改进图像分割以获得更好的图像轮廓,从而获取对象包围的所有像素(大多数)?

如果有帮助,我可以添加我的代码,但它相当大。

编辑: 我从SentDex教程中尝试了GrabCut算法,但是它可以去除一些背景,但是分水岭算法后来无法找到准确的前景表示。

enter image description hereenter image description here

左边的图像是在应用了GrabCut之后,然后在右边,GrabCut算法被传递到分水岭算法以找到确定的前景。


Tags: 对象图像算法场景rgb像素照片轮廓
2条回答

在找到轮廓之前先扩张再腐蚀怎么样:

element = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(21, 21))

dilate = cv2.dilate(gray,element,1)
cv2.imshow("dilate",dilate)
erode = cv2.erode(dilate,element,1)

#use erode as a mask to extract the object from the original image
erode = cv2.bitwise_not(erode)

erode = cv2.cvtColor(erode, cv2.COLOR_GRAY2BGR)

res = cv2.add(original,erode)

我只是演示如何应用蒙版,因为我没有您使用的图像和对象识别软件。在

enter image description hereenter image description hereenter image description here

通过从RGB图像上的颜色识别和分析切换到对相机的深度信息进行边缘检测,我能够获得更好的物体轮廓。在

以下是我为找到更好的边缘贴图而采取的一般步骤。在

  1. 将深度信息保存在NxMx1矩阵中。其中N,M值是图像分辨率的形状。对于480640图像,我有一个矩阵(480640,1),其中每个像素(I,j)存储该像素坐标对应的深度值。

  2. 使用二维高斯核平滑和填补我的深度矩阵中的任何缺失数据,使用astropy的卷积方法。

  3. 找到我的深度矩阵的梯度和梯度中每个像素对应的大小。

  4. 基于均匀深度过滤数据。其中均匀深度意味着一个平面物体,所以我发现我的量值的高斯分布(从深度梯度)和那些填充在X标准偏差内的值被设置为零。这减少了图像中的一些附加噪声。

  5. 然后我将我的幅值矩阵的值从0规范化为1,这样我的矩阵就可以被认为是通道1图像矩阵。

因为我的深度矩阵是(480640,1)的形式,当我找到相应的梯度矩阵,也是(480640,1)时,我将值(:,:,1)从0缩放到1。这样以后我可以用灰度或二值图像来表示它。在

def gradient_demo(self, Depth_Mat):
    """
    Gradient display entire image
    """
    shape = (Depth_Mat.shape)
    bounds = ( (0,shape[0]), (0, shape[1]) )

    smooth_depth = self.convolve_smooth_Depth(Depth_Mat, bounds)
    gradient, magnitudes = self.depth_gradient(smooth_depth, bounds)
    magnitudes_prime = magnitudes.flatten()

    #hist, bin = np.histogram(magnitudes_prime, 50)  # histogram of entire image
    mean = np.mean(magnitudes_prime)
    variance = np.var(magnitudes_prime)
    sigma = np.sqrt(variance)

    # magnitudes_filtered = magnitudes[(magnitudes > mean - 2 * sigma) & (magnitudes < mean + 2 * sigma)]
    magnitudes[(magnitudes > mean - 1.5 * sigma) & (magnitudes < mean + 1.5 * sigma)] = 0

    magnitudes = 255*magnitudes/(np.max(magnitudes))
    magnitudes[magnitudes != 0] = 1

    plt.title('magnitude of gradients')
    plt.imshow(magnitudes, vmin=np.nanmin(magnitudes), vmax=np.amax(magnitudes), cmap = 'gray')
    plt.show()

    return  magnitudes.astype(np.uint8)
def convolve_smooth_Depth(self, raw_depth_mtx, bounds):
    """
    Iterate over subimage and fill in any np.nan values with averages depth values
    :param image: 
    :param bounds: ((ylow,yhigh), (xlow, xhigh)) -> (y,x)
    :return: Smooted depth values for a given square
    """
    ylow, yhigh = bounds[0][0], bounds[0][1]
    xlow, xhigh = bounds[1][0], bounds[1][1]

    kernel = Gaussian2DKernel(1)    #generate kernel 9x9 with stdev of 1
    # astropy's convolution replaces the NaN pixels with a kernel-weighted interpolation from their neighbors
    astropy_conv = convolve(raw_depth_mtx[ylow:yhigh, xlow:xhigh], kernel, boundary='extend')
    # extended boundary assumes original data is extended using a constant extrapolation beyond the boundary
    smoothedSQ = (np.around(astropy_conv, decimals= 3))

    return smoothedSQ

def depth_gradient(self, smooth_depth, bounds):
    """

    :param smooth_depth: 
    :param shape: Tuple with y_range and x_range of the image. 
            shape = ((0,480), (0,640)) (y,x) -> (480,640)
            y_range = shape[0]
            x_range = shape[1]
    :return: 
    """
    #shape defines the image array shape. Rows and Cols for an array

    ylow, yhigh = bounds[0][0], bounds[0][1]
    xlow, xhigh = bounds[1][0], bounds[1][1]
    gradient = np.gradient(smooth_depth)
    x,y = range(xlow, xhigh), range(ylow, yhigh)
    xi, yi = np.meshgrid(x, y)
    magnitudes = np.sqrt(gradient[0] ** 2 + gradient[1] ** 2)

    return gradient, magnitudes

使用这个方法/代码,我能够得到下面的图像。仅供参考,我稍微改变了一下场景。在

enter image description here

我问了另一个相关的问题:How to identify contours associated with my objects and find their geometric centroid

这说明了如何在图像中找到物体的轮廓,质心。在

相关问题 更多 >