Подтвердить что ты не робот

Проблемы с обработкой изображений с кровеносными сосудами

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

        clahe = cv2.createCLAHE(clipLimit=100.0, tileGridSize=(100,100))
        self.cl1 = clahe.apply(self.result_array)
        self.cl1 = 255 - self.cl1

введите описание изображения здесь

И затем я использую порог OTSU для извлечения кровеносных сосудов, но не могу сделать это хорошо:

self.ret, self.thresh = cv2.threshold(self.cl1, 0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)
        kernel = np.ones((1,1),np.float32)/1
        self.thresh = cv2.erode(self.thresh, kernel, iterations=3)
        self.thresh = cv2.dilate(self.thresh, kernel, iterations=3)

Здесь результат:

введите описание изображения здесь

Очевидно, там много шума. Я пробовал использовать медианное размытие, но он просто кластеризует шум и превращает его в капли, в некоторых местах. Как я могу устранить шум, чтобы получить кровеносные сосуды?

Это оригинальное изображение, из которого я пытаюсь извлечь кровеносные сосуды:

введите описание изображения здесь

4b9b3361

Ответ 1

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

Один из способов решения таких проблем, основанный на детекторе края Канни, использует два порога - [hi,low] и классифицирует пиксель p с ответом r как принадлежащий кровеносному сосуду V, если r > hi || (r > lo & один из p соседей находится в V).

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

kernel3 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
kernel5 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
kernel7 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7))
t_lo = 136
t_hi = 224

blured = cv2.pyrMeanShiftFiltering(img, 3, 9)
#blured = cv2.bilateralFilter(img, 9, 32, 72)

clahe = cv2.createCLAHE(clipLimit=128.0, tileGridSize=(64, 64))
cl1 = clahe.apply(blured)
cl1 = 255 - cl1

ret, thresh_hi = cv2.threshold(cl1, t_hi, 255, cv2.THRESH_TOZERO)
ret, thresh_lo = cv2.threshold(cl1, t_lo, 255, cv2.THRESH_TOZERO)

низкий порог Изображение с низким порогом hi threshold Высокое пороговое изображение

Подготовка и очистка:

current = np.copy(thresh_hi)
prev = np.copy(current)
prev[:] = 0
current = cv2.morphologyEx(current, cv2.MORPH_OPEN, kernel5)
iter_num = 0
max_iter = 1000

Не самый эффективный способ сделать это... но легко реализовать:

while np.sum(current - prev) > 0 and iter_num < max_iter:
    iter_num = iter_num+1
    prev = np.copy(current)
    current = cv2.dilate(current, kernel3)
    current[np.where(thresh_lo == 0)] = 0

начальная маска Исходная маска

Удалите маленькие капли:

contours, hierarchy = cv2.findContours(current, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
    area = cv2.contourArea(contour)
    if area < 256:
        cv2.drawContours( current, [contour], 0, [0,0,0], -1 )

очищенная маска После удаления небольших капель

Морфологическая очистка:

opening = cv2.morphologyEx(current, cv2.MORPH_OPEN, kernel7)   
cl1[np.where(opening == 0)] = 0

result Результат

Это отнюдь не оптимально, но я думаю, что он должен предоставить вам достаточно инструментов для запуска.

Ответ 2

Как насчет: High-Pass (изображение минус гауссовское сглаженное с сигмой 12), затем удаляется порог (126), а затем подавление мелких объектов (объекты размером менее 300 пикселей)?

(я работал с вашим последним изображением)

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь