Сегментируйте фотографии биологических образцов для выделения круговой области интереса с обработкой изображения Python - PullRequest
3 голосов
/ 22 января 2020

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

biofilm of pseudomona

Я пытаюсь сегментировать область внутри круга и посмотреть, как значения пикселей меняются с течением времени. Я пробовал много техник, так как я относительно новичок в анализе таких образцов. Сначала я использовал opencv, но я не получил желаемых результатов, поэтому теперь я использую scikit-image для всех методы обработки и сегментации изображений. Вот код, который у меня есть до сих пор:

from skimage import morphology, exposure, io, filters
from scipy import ndimage as ndi
from skimage.color import rgb2gray, label2rgb
from skimage.filters import sobel, rank
import matplotlib.pyplot as plt
y1=400
y2=1600
x1=700
x2=1900
test_img = io.imread(folders_path+hour_tested[0]+'5.jpg')
roi_test = test_img[y1:y2, x1:x2,:]
gray_img = rgb2gray(roi_test)
denoised_img = rank.median(gray_img, morphology.disk(5))
val = filters.threshold_otsu(denoised_img)
mask = denoised_img > val
elevation_map=sobel(denoised_img)
segmentation = morphology.watershed(elevation_map, mask=mask)
labeled_bio, num_seg = ndi.label(segmentation)
image_label_overlay = label2rgb(labeled_bio, image=gray_img)
plt.imshow(image_label_overlay)
plt.show()

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

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

Ну вот помеченное изображение образца:

segmented area with labels

Ответы [ 2 ]

0 голосов
/ 24 января 2020

После исправления кода это правильный ответ для сегментации биопленки:

import cv2
import numpy as np
import os
def resize_image(image, percentage):
   scale_percent=percentage
   width = int(image.shape[1] * scale_percent/100)
   height= int(image.shape[0] * scale_percent/100)
   dimensions = (width, height)
   resized = cv2.resize(image, dimensions, interpolation = cv2.INTER_AREA)
   return resized
#this path is changed for each image in the DB
path=folders_path+hour_tested[0]+'1.jpg'
image = cv2.imread(path)
s_image = resize_image(image,50)
original = s_image.copy()
mask = np.zeros(s_image.shape, dtype=np.uint8)
gray = cv2.cvtColor(s_image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Morph close
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=3)
# Find contours and filter using contour area + contour approximation
# Determine perfect circle contour then draw onto blank mask
im,cnts,hierarchy = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.04*peri, True)
    area = cv2.contourArea(c)
    if len(approx) > 4 and (area > 8000 and area < 250000) and (peri<2000 and peri>1000):
        ((x, y), r) = cv2.minEnclosingCircle(c)
        x,y,r = int(x),int(y),int(r)
        blank_circle=cv2.circle(mask, (x, y), r, (255, 255, 255), -1)
        filled_circle=cv2.circle(s_image, (x, y), r, (36, 255, 12), 3)
        # Extract ROI
        mask_ROI = blank_circle[y-r:y+r, x-r:x+r]
        mask_ROI = cv2.cvtColor(mask_ROI, cv2.COLOR_BGR2GRAY)
        image_ROI = filled_circle[y-r:y+r, x-r:x+r]
        result = cv2.bitwise_and(image_ROI, image_ROI, mask=mask_ROI)
        cv2.imwrite('result.png',result)
0 голосов
/ 23 января 2020

Вот подход, использующий простые методы обработки изображений

  • Получение двоичного изображения. Загрузка изображения, преобразование в оттенки серого, затем порог Оцу для получения двоичного изображения

  • Выполнение морфологических операций. Мы создаем ядро ​​эллиптической формы, затем выполняем морфологическое закрытие, чтобы заполнить контуры

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

  • Изолировать ROI. Мы находим ограничивающую ROI прямоугольника на маске, затем обрезать, используя Numpy нарезку

  • Побитово - и получить результат. Наконец мы побитовые - и два извлеченных ROI


Вот визуализация каждого шага:

Входное изображение

image

Двоичное изображение

image

Morph close

image

Изолированная область интереса, выделенная зеленым и заполненный контур, нарисованный на пустой маске

image image

Отдельные области интереса

image image

Поразрядно и для результата (две версии, одна с черным фоном и одна с белым фоном, в зависимости от того, что Вы хотите)

image image

Код

import cv2
import numpy as np

# Load image, create blank mask, grayscale, Otsu's threshold
image = cv2.imread('1.jpg')
original = image.copy()
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Morph close
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=5)

# Find contours and filter using contour area + contour approximation
# Determine perfect circle contour then draw onto blank mask
cnts = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.04 * peri, True)
    area = cv2.contourArea(c)
    if len(approx) > 4 and area > 10000 and area < 500000:
        ((x, y), r) = cv2.minEnclosingCircle(c)
        cv2.circle(mask, (int(x), int(y)), int(r), (255, 255, 255), -1)
        cv2.circle(image, (int(x), int(y)), int(r), (36, 255, 12), 3)

# Extract ROI
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
x,y,w,h = cv2.boundingRect(mask)
mask_ROI = mask[y:y+h, x:x+w]
image_ROI = original[y:y+h, x:x+w]

# Bitwise-and for result
result = cv2.bitwise_and(image_ROI, image_ROI, mask=mask_ROI)
result[mask_ROI==0] = (255,255,255) # Color background white

cv2.imwrite('close.png', close)
cv2.imwrite('thresh.png', thresh)
cv2.imwrite('image.png', image)
cv2.imwrite('mask.png', mask)
cv2.imwrite('result.png', result)
cv2.waitKey()

Примечание: Другой подход для определения круговой области интереса использовать Hough Circle Transform, уже реализованную как cv2.HoughCircles(), но есть много параметров, поэтому это может быть не самый практичный метод.

...