Как удалить артефакт грубых линий с изображения после бинаризации

Я застрял в проблеме, когда хочу различать объект и фон ( имеющий полупрозрачный белый лист с подсветкой) то есть фиксированная грубая линия, введенная в фон и сливающаяся с объектом. Мой алгоритм сейчас таков: я беру изображение с камеры, сглаживаю его размытием по Гауссу, затем извлекаю компонент Value из HSV, применяя локальную бинаризацию с помощью метода волка, чтобы получить бинаризованное изображение, после чего, используя алгоритм связанного компонента OpenCV, я удаляю некоторые небольшие артефакты, которые не связаны с объектом, как видно здесь. Теперь есть только этот строковый артефакт, который объединен с объектом, но мне нужен только объект, показанный в этом изображение. Обратите внимание, что в двоичном изображении есть 2 строки, поэтому использование 8 подключенной логики для обнаружения строк, не образующих цикл, невозможно, это то, что я думаю и тоже пробовал. вот код для этого

size = np.size(thresh_img)
skel = np.zeros(thresh_img.shape,np.uint8)
element = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
done = False

while( not done):
    eroded = cv2.erode(thresh_img,element)
    temp = cv2.dilate(eroded,element)
    temp = cv2.subtract(thresh_img,temp)
    skel = cv2.bitwise_or(skel,temp)
    thresh_img = eroded.copy()

    zeros = size - cv2.countNonZero(thresh_img)
    if zeros==size:
       done = True

# set max pixel value to 1
s = np.uint8(skel > 0)

count = 0
i = 0
while count != np.sum(s):
     # non-zero pixel count
     count = np.sum(s)
     # examine 3x3 neighborhood of each pixel
     filt = cv2.boxFilter(s, -1, (3, 3), normalize=False)
     # if the center pixel of 3x3 neighborhood is zero, we are not interested in it
     s = s*filt
     # now we have pixels where the center pixel of 3x3 neighborhood is non-zero
     # if a pixels' 8-connectivity is less than 2 we can remove it
     # threshold is 3 here because the boxfilter also counted the center pixel
     s[s < 1] = 0
     # set max pixel value to 1
     s[s > 0] = 1
     i = i + 1

Любая помощь в виде кода будет принята с благодарностью.


person hawxeye    schedule 16.11.2019    source источник
comment
Вы знакомы с операцией скелетонирования? Вы можете использовать это, чтобы удалить все, кроме петли.   -  person Cris Luengo    schedule 16.11.2019
comment
но не скелетировать, просто дает контур изображения   -  person hawxeye    schedule 16.11.2019


Ответы (1)


Поскольку вы уже используете connectedComponents, лучший способ - исключить не только те, которые маленькие, но и те, которые касаются границ изображения. Вы можете узнать, какие из них следует отбросить, используя connectedComponentsWithStats(), который также дает вам информацию о ограничивающей рамке каждого компонента.

В качестве альтернативы, и очень похоже, вы можете переключиться с connectedComponents() на findContours(), что дает вам напрямую Компоненты, чтобы вы могли отбросить внешние и маленькие, чтобы получить интересующую вас часть.

person Diego Mazzaro    schedule 16.11.2019
comment
Поскольку приложение работает в реальном времени, в некоторых случаях линия может не касаться границы, и теперь с помощью морфологических операций я получил бинаризацию одной строки. - person hawxeye; 16.11.2019
comment
Хорошо, в конце концов, написание полезных алгоритмов обработки изображений - это больше о знании того, каким не будет изображение, а о том, как оно есть. Так что вы можете ожидать, что некоторые входные данные не обманут алгоритм. - person Diego Mazzaro; 20.11.2019