Улучшение сегментации изображения для создания замкнутого контура, окружающего мой объект

1

Это фотография моей сцены, сделанная с камеры Intel Realsense d435 rgb. Изображение 174551

Я хочу иметь возможность идентифицировать металлический объект на моем изображении и нарисовать замкнутый контур вокруг него. Таким образом, я могу ссылаться на все пиксели в контуре для будущего использования.

Текущая методология

  1. В настоящее время я обрезаю изображение сцены, делая вид, что у меня запущено какое-то программное обеспечение для распознавания объектов, позволяющее мне создать ограничивающий прямоугольник вокруг моего объекта. Поэтому я обрезаю этот раздел и применяю его к чистому изображению.

Изображение 174551

  1. Я следовал документации OpenCV и использовал морфологические преобразования и алгоритм водораздела для сегментации изображения. Я заканчиваю тем, что извлекал уверенное изображение переднего плана и запускаю обнаружение четких краев и контуров. Однако линии, которые они возвращают, довольно плохие.

2.5. В настоящее время я просто использую надежное изображение переднего плана и беру все пиксели черного цвета и сохраняю их в качестве объекта, однако у меня есть эти огромные белые пятна внутри моего уверенного изображения переднего плана, которые не собираются.

Изображение 174551 Изображение 174551

Как я могу улучшить свою сегментацию изображения, чтобы получить лучший контур моего изображения, чтобы я мог захватить все пиксели (большинство), которые окружены моим объектом?

Я могу добавить свой код, если это поможет, но он довольно большой.

РЕДАКТИРОВАТЬ: Я попробовал алгоритм GrabCut из учебника SentDex, однако, хотя он может удалить некоторые фоны, я алгоритм водораздела не может найти точное представление переднего плана впоследствии.

Изображение 174551 Изображение 174551

Изображение слева - после того, как GrabCut был применен, а затем справа алгоритм GrabCut передается алгоритму водораздела, чтобы найти верный передний план.

  • 1
    Попробуйте использовать grabCut. Это будет хорошо для вашего случая
  • 0
    GrabCut был хорошим предложением, но в приложении моей программы не будет никакого пользовательского интерфейса. Ограничительная рамка размещается статически как заполнитель для последующего распознавания объекта. Применение GrabCut дает остальной части моего кода труднее идентифицировать края.
Теги:
opencv
image-processing
computer-vision
image-segmentation

2 ответа

1
Лучший ответ

Я смог получить лучший контур моего объекта, переключившись с распознавания цвета и анализа по изображению RGB на обнаружение краев на информации о глубине от моей камеры.

Вот общие шаги, которые я предпринял, чтобы найти лучшую карту краев.

  1. Сохраните информацию о моей глубине в матрице NxMx1. Где N, M values - это форма моего разрешения изображения. Для изображения 480 640 у меня была матрица (480 640,1), где каждый пиксель (i, j) сохранял соответствующее значение глубины для этой координаты пикселя.

  2. Использовал двумерное ядро Гаусса, чтобы сгладить и заполнить все недостающие данные в моей матрице глубины, используя метод астропии.

  3. Найти градиент моей матрицы глубины и соответствующую величину каждого пикселя в градиенте.

  4. Отфильтруйте данные на основе одинаковой глубины. Где однородная глубина подразумевала бы плоский объект, поэтому я нашел гауссово распределение для моих величин (от градиента глубины), а те, которые заполняют в пределах X стандартных отклонений, были установлены на ноль. Это уменьшило дополнительный шум на изображении.

  5. Затем я нормализовал значения моей матрицы амплитуд от 0 до 1, чтобы моя матрица могла рассматриваться как матрица изображений канала 1.

Так как моя матрица глубины имела форму (480 640,1), и когда я нашла свою соответствующую матрицу градиента, которая также была (480 640,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 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

Используя этот метод/код, я смог получить следующее изображение. Просто к вашему сведению, я немного изменил сцену.

Изображение 174551

Я задал еще один связанный с этим вопрос: как определить контуры, связанные с моими объектами, и найти их геометрический центроид

Это показывает, как найти контуры, центроиды моего объекта на изображении.

0

Как насчет расширения, а затем разрушения, прежде чем найти контуры:

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)

Я просто показываю, как применить маску, потому что у меня нет программного обеспечения для распознавания изображений и объектов, которое вы используете.

Изображение 174551 Изображение 174551 Изображение 174551

  • 0
    Я пытаюсь получить контур, который окружает объект внутри моей ограничивающей рамки, а не контур ограничивающей рамки. Я заинтересован в отделении моего объекта переднего плана от фона.
  • 0
    Я отредактировал ответ. Вы можете просто использовать размытое изображение в качестве маски для разделения переднего плана.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню