Улучшение сегментации изображения для создания замкнутого контура, окружающего мой объект - PullRequest
0 голосов
/ 14 февраля 2019

Это фотография моей сцены, сделанная с камеры Intel Realsense d435 rgb.enter image description here

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

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

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

Cropped Image with threshold applied

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

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

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

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

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

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

enter image description hereenter image description here

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

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

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

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

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

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

  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'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

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

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

0 голосов
/ 14 февраля 2019

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

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 here enter image description here enter image description here

...