Анализ водораздела монет - неправильный вывод

Для подсчета круглых объектов на изображении я хочу использовать алгоритм водораздела. Чтобы узнать, как это работает и как я могу использовать его для своих нужд, я искал некоторые рабочие примеры в python ( https://docs.opencv.org/3.1.0/d3/db4/tutorial_py_watershed.html; http://scikit-image.org/docs/dev/auto_examples/segmentation/plot_label.html)

В конце концов я нашел рабочее решение, которое более или менее готово для моих собственных целей ( Как определить маркеры для Watershed в OpenCV?)

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

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

это код:

import cv2
import numpy as np
from scipy.ndimage import label
def segment_on_dt(a, img):
    border = cv2.dilate(img, None, iterations=3)
    border = border - cv2.erode(border, None)
    dt = cv2.distanceTransform(img, cv2.DIST_L2, 3)
    dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)
    _, dt = cv2.threshold(dt, 200, 255, cv2.THRESH_BINARY)
    lbl, ncc = label(dt)
    # Completing the markers now. 
    lbl[border == 255] = 255 
    lbl = lbl.astype(np.int32)
    cv2.watershed(a, lbl)
    lbl[lbl == -1] = 0
    lbl = lbl.astype(np.uint8)
    return 255 - lbl

# Load image file
img = cv2.imread('coins.jpg')
# Pre-processing.
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray = cv2.GaussianBlur(img_gray,(5,5),0)  
width, height = img_gray.shape
_, img_bin = cv2.threshold(img_gray, 0,  255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
img_bin = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,np.ones((5, 5),     dtype=int))
result = segment_on_dt(img, img_bin)
result[result != 255] = 0
result = cv2.dilate(result, None)
img[result == 255] = (0, 0, 255)
cv2.imwrite('Img_output.png',img)

Запуск этого кода даст этот результат (по крайней мере, на моем компьютере)

Монеты обнаружены после водораздела, край изображения также окрашен

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

1 ответ

Решение

Вы можете исправить это, добавив метку фона, используя учебное пособие, предоставленное openCV. https://docs.opencv.org/3.1.0/d3/db4/tutorial_py_watershed.html

Они добавили дополнительный шаг для вставки определенного фона и определенной области переднего плана, чтобы алгоритм водораздела правильно сегментировал области монет.

*********** редактировать**************

После прочтения вашего кода снова. Я обнаружил, что ваш оригинальный код не имеет проблем. Фоновая метка была установлена ​​с помощью переменной border.

Вы, вероятно, получите тот же результат, выполнив код из учебника OpenCV. Проблема в том, как вы рисуете результаты. Так как это проблема с отображением, есть много способов решить эту проблему. Одним из многих является использование информации верного фона

Вот модификация функции сегмент_он_дт

def segment_on_dt(a, img):
    sure_background = cv2.dilate(img, None, iterations=3)
    border = sure_background - cv2.erode(sure_background, None)


    dt = cv2.distanceTransform(img, cv2.DIST_L2, 3)
    dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)
    _, dt = cv2.threshold(dt, 200, 255, cv2.THRESH_BINARY)
    lbl, ncc = label(dt)


    # Completing the markers now. 
    lbl[border == 255] = 255 


    lbl = lbl.astype(np.int32)
    cv2.watershed(a, lbl)
    lbl[lbl == -1] = 0
    # Only draw red line if its not in sure background
    lbl[sure_background == 0] = 255

    lbl = lbl.astype(np.uint8)
    cv2.imshow('lbl_2',lbl)

    return 255 - lbl

Я добавил новое условие для рисования красных линий. Линия рисуется только в том случае, если она не находится в определенной области фона.

Ваш конечный результат должен выглядеть следующим образом.

Другие вопросы по тегам