Сегментация водосбора за исключением одного объекта? - PullRequest
0 голосов
/ 19 ноября 2018

Задача

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

Я насчитал 123 объекта, и программа возвращает 117, как видно ниже. Кажется, что объекты, обведенные красным, отсутствуют:

Missing objects

Использование следующего изображения с веб-камеры 720p:

Picture with 123 objects

код

import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import label
import urllib.request


# https://stackoverflow.com/a/14617359/7690982
def segment_on_dt(a, img):
    border = cv2.dilate(img, None, iterations=5)
    border = border - cv2.erode(border, None)

    dt = cv2.distanceTransform(img, cv2.DIST_L2, 3)
    plt.imshow(dt)
    plt.show()
    dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)
    _, dt = cv2.threshold(dt, 140, 255, cv2.THRESH_BINARY)
    lbl, ncc = label(dt)
    lbl = lbl * (255 / (ncc + 1))
    # Completing the markers now.
    lbl[border == 255] = 255

    lbl = lbl.astype(np.int32)
    cv2.watershed(a, lbl)
    print("[INFO] {} unique segments found".format(len(np.unique(lbl)) - 1))
    lbl[lbl == -1] = 0
    lbl = lbl.astype(np.uint8)
    return 255 - lbl


# Open Image
resp = urllib.request.urlopen("https://i.stack.imgur.com/YUgob.jpg")
img = np.asarray(bytearray(resp.read()), dtype="uint8")
img = cv2.imdecode(img, cv2.IMREAD_COLOR)

## Yellow slicer
mask = cv2.inRange(img, (0, 0, 0), (55, 255, 255))
imask = mask > 0
slicer = np.zeros_like(img, np.uint8)
slicer[imask] = img[imask]

# Image Binarization
img_gray = cv2.cvtColor(slicer, cv2.COLOR_BGR2GRAY)
_, img_bin = cv2.threshold(img_gray, 140, 255,
             cv2.THRESH_BINARY)

# Morphological Gradient
img_bin = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,
        np.ones((3, 3), dtype=int))

# Segmentation
result = segment_on_dt(img, img_bin)
plt.imshow(np.hstack([result, img_gray]), cmap='Set3')
plt.show()

# Final Picture
result[result != 255] = 0
result = cv2.dilate(result, None)
img[result == 255] = (0, 0, 255)
plt.imshow(result)
plt.show()

Вопрос

Как считать недостающие предметы?

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

Глядя на ваш код, это вполне разумно, поэтому я просто собираюсь сделать одно маленькое предложение, а именно выполнить inRange, используя цветовое пространство HSV.

документы opencv по цветовым пространствам:

https://opencv -python-tutroals.readthedocs.io / ен / последний / py_tutorials / py_imgproc / py_colorspaces / py_colorspaces.html

другой пример SO с использованием inRange с HSV:

Как определить два разных цвета, используя `cv2.inRange` в Python-OpenCV?

и небольшой код редактирует для вас:

img = cv2.blur(img, (5,5))  #new addition just before "##yellow slicer"

## Yellow slicer
#mask = cv2.inRange(img, (0, 0, 0), (55, 255, 255))   #your line: comment out.
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)  #new addition...convert to hsv
mask = cv2.inRange(hsv, (0, 120, 120), (35, 255, 255))  #new addition use hsv for inRange and an adjustment to the values.
0 голосов
/ 25 ноября 2018

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

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

enter image description here

Причиной слабого сигнала преобразования расстояния была неправильная сегментация на этапе сегментации цвета и сложность установки единого порога для удаления шума и извлечения сигнала.

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

Вот код, который я изменил. Я включил метод цветовой сегментации @ user1269942 в коде. Дополнительное объяснение в коде.

import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import label
import urllib.request


# https://stackoverflow.com/a/14617359/7690982


def segment_on_dt(a, img, img_gray):

    # Added several elliptical structuring element for better morphology process
    struct_big = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
    struct_small = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))

    # increase border size
    border = cv2.dilate(img, struct_big, iterations=5)
    border = border - cv2.erode(img, struct_small)




    dt = cv2.distanceTransform(img, cv2.DIST_L2, 3)
    dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)

    # blur the signal lighty to remove noise
    dt = cv2.GaussianBlur(dt,(7,7),-1)

    # Adaptive threshold to extract local maxima of distance trasnform signal
    dt = cv2.adaptiveThreshold(dt, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, -9)
    #_ , dt = cv2.threshold(dt, 2, 255, cv2.THRESH_BINARY)


    # Morphology operation to clean the thresholded signal
    dt = cv2.erode(dt,struct_small,iterations = 1)
    dt = cv2.dilate(dt,struct_big,iterations = 10)

    plt.imshow(dt)
    plt.show()

    # Labeling
    lbl, ncc = label(dt)
    lbl = lbl * (255 / (ncc + 1))
    # Completing the markers now.
    lbl[border == 255] = 255

    plt.imshow(lbl)
    plt.show()

    lbl = lbl.astype(np.int32)
    cv2.watershed(a, lbl)
    print("[INFO] {} unique segments found".format(len(np.unique(lbl)) - 1))
    lbl[lbl == -1] = 0
    lbl = lbl.astype(np.uint8)
    return 255 - lbl

# Open Image
resp = urllib.request.urlopen("https://i.stack.imgur.com/YUgob.jpg")
img = np.asarray(bytearray(resp.read()), dtype="uint8")
img = cv2.imdecode(img, cv2.IMREAD_COLOR)


## Yellow slicer
# blur to remove noise
img = cv2.blur(img, (9,9))

# proper color segmentation
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)  
mask = cv2.inRange(hsv, (0, 140, 160), (35, 255, 255)) 
#mask = cv2.inRange(img, (0, 0, 0), (55, 255, 255))

imask = mask > 0
slicer = np.zeros_like(img, np.uint8)
slicer[imask] = img[imask]



# Image Binarization
img_gray = cv2.cvtColor(slicer, cv2.COLOR_BGR2GRAY)

_, img_bin = cv2.threshold(img_gray, 140, 255,
             cv2.THRESH_BINARY)


plt.imshow(img_bin)
plt.show()
# Morphological Gradient
# added
cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)),img_bin,(-1,-1),10)
cv2.morphologyEx(img_bin, cv2.MORPH_ERODE,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)),img_bin,(-1,-1),3)

plt.imshow(img_bin)
plt.show()

# Segmentation
result = segment_on_dt(img, img_bin, img_gray)
plt.imshow(np.hstack([result, img_gray]), cmap='Set3')
plt.show()

# Final Picture
result[result != 255] = 0
result = cv2.dilate(result, None)
img[result == 255] = (0, 0, 255)
plt.imshow(result)
plt.show()

Окончательные результаты: 124 Уникальных предметов найдено. Был найден дополнительный предмет, потому что один из предметов был разделен на 2. При правильной настройке параметров вы можете получить точное число, которое вы ищете. Но я бы посоветовал приобрести лучшую камеру.

enter image description here enter image description here

0 голосов
/ 23 ноября 2018

Повышение точности

Обнаружение пропущенных объектов

enter image description here enter image description here enter image description here

im_1 , im_2 , im_3

Я насчитал 12 пропущенных объектов: 2, 7,8, 11, 65, 77, 78, 84, 92, 95, 96. изменить: 85 тоже

117 найдено, 12 пропало, 6 неправильно


1 ° Попытка: уменьшить чувствительность маски

#mask = cv2.inRange(img, (0, 0, 0), (55, 255, 255))  #Current
mask = cv2.inRange(img, (0, 0, 0), (80, 255, 255))   #1' Attempt

Документация inRange

enter image description here

enter image description here enter image description here enter image description here

im_4 , im_5 , im_6 , im_7

[INFO] 120 unique segments found

120 найдено, 9 пропало, 6 неправильно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...