Вопрос или проблема
Я новичок в обработке изображений, я пытаюсь сегментировать КТ изображения легких с помощью Kmeans следующим образом:
import numpy as np
import re
import pandas as pd
from skimage import morphology
from skimage import measure
from PIL import Image
from sklearn.cluster import KMeans
from skimage.transform import resize
from glob import glob
import sys
import os
import cv2
from scipy.ndimage.morphology import binary_dilation,generate_binary_structure
from skimage.morphology import convex_hull_image
def process_mask(mask):
convex_mask = np.copy(mask)
for i_layer in range(convex_mask.shape[0]):
mask1 = np.ascontiguousarray(mask[i_layer])
if np.sum(mask1)>0:
mask2 = convex_hull_image(mask1)
if np.sum(mask2)>2*np.sum(mask1):
mask2 = mask1
else:
mask2 = mask1
convex_mask[i_layer] = mask2
struct = generate_binary_structure(3,1)
dilatedMask = binary_dilation(convex_mask,structure=struct,iterations=10)
return dilatedMask
def lumTrans(img):
lungwin = np.array([-1200.,600.])
newimg = (img-lungwin[0])/(lungwin[1]-lungwin[0])
newimg[newimg<0]=0
newimg[newimg>1]=1
newimg = (newimg*255).astype('uint8')
return newimg
def lungSeg(imgs_to_process,output,name):
if os.path.exists(output+"https://datascience.stackexchange.com/"+name+'_clean.npy') : return
imgs_to_process = Image.open(imgs_to_process)
img_to_save = imgs_to_process.copy()
img_to_save = np.asarray(img_to_save).astype('uint8')
imgs_to_process = lumTrans(imgs_to_process)
imgs_to_process = np.expand_dims(imgs_to_process, axis=0)
x,y,z = imgs_to_process.shape
img_array = imgs_to_process.copy()
A1 = int(y/(512./100))
A2 = int(y/(512./400))
A3 = int(y/(512./475))
A4 = int(y/(512./40))
A5 = int(y/(512./470))
for i in range(len(imgs_to_process)):
img = imgs_to_process[i]
print(img.shape)
x,y = img.shape
#Стандартизируем значения пикселей
allmean = np.mean(img)
allstd = np.std(img)
img = img-allmean
img = img/allstd
# Найдите среднее значение пикселя вблизи легких
# для перенормализации вымытых изображений
middle = img[A1:A2,A1:A2]
mean = np.mean(middle)
max = np.max(img)
min = np.min(img)
kmeans = KMeans(n_clusters=2).fit(np.reshape(middle,[np.prod(middle.shape),1]))
centers = sorted(kmeans.cluster_centers_.flatten())
threshold = np.mean(centers)
thresh_img = np.where(img<threshold,1.0,0.0) # пороговое значение изображения
eroded = morphology.erosion(thresh_img,np.ones([4,4]))
dilation = morphology.dilation(eroded,np.ones([10,10]))
labels = measure.label(dilation)
label_vals = np.unique(labels)
regions = measure.regionprops(labels)
good_labels = []
for prop in regions:
B = prop.bbox
if B[2]-B[0]<A3 and B[3]-B[1]<A3 and B[0]>A4 and B[2]<A5:
good_labels.append(prop.label)
mask = np.ndarray([x,y],dtype=np.int8)
mask[:] = 0
for N in good_labels:
mask = mask + np.where(labels==N,1,0)
mask = morphology.dilation(mask,np.ones([10,10])) # последняя дилатация
imgs_to_process[i] = mask
m1 = imgs_to_process
convex_mask = m1
dm1 = process_mask(m1)
dilatedMask = dm1
Mask = m1
extramask = dilatedMask ^ Mask
bone_thresh = 180
pad_value = 0
img_array[np.isnan(img_array)]=-2000
sliceim = img_array
sliceim = sliceim*dilatedMask+pad_value*(1-dilatedMask).astype('uint8')
bones = sliceim*extramask>bone_thresh
sliceim[bones] = pad_value
x,y,z = sliceim.shape
if not os.path.exists(output):
os.makedirs(output)
img_to_save[sliceim.squeeze()==0] = 0
im = Image.fromarray(img_to_save)
im.save(output + name + '.png', 'PNG')
Метод вызова сегментации легких:
lungSeg(image_path, new_image_path, image_name)
Проблема в том, что сегментированное легкое все еще содержит белые границы, как это:
сегментированное легкое (выход):
несегментированное легкое (вход):
Весь код здесь https://colab.research.google.com/drive/1gdZi7dv2bo4MNgR9suuM1ZCMItSWXggl?usp=sharing
Попробуйте использовать Операции эрозии и дилатации для удаления белой области.
Ответ или решение
В вопросе рассматривается задача сегментации легких на КТ-снимках с использованием алгоритма K-средних (KMeans). При текущей реализации возникает проблема: на сегментированном изображении остаются белые границы. Рассмотрим причины этой проблемы и как её можно устранить.
Теория:
Сегментация изображения на основе алгоритма K-средних заключается в делении пикселей на кластеры по их интенсивностям. В данном случае используется два кластера, что позволяет отделить яркие области (предположительно кости) и менее яркие области (возможные легкие). Однако после сегментации могут возникать нежелательные артефакты, например, белые границы, которые могут быть результатом неточного порогового значения или артефактов, возникающих при морфологических операциях.
Пример проблемы:
Как видно на изображении результата, белые границы могут появляться из-за недостаточно точной сегментации, где области, граничащие с легкими, неправильно классифицируются. Это может быть связано с особенностями алгоритма K-средних, который может не в полной мере учитывать контекст изображения, особенно в сложных медицинских снимках.
Применение:
Для устранения белых границ можно использовать морфологические операции, такие как эрозия и дилатация (расширение). Эти операции могут помочь удалить небольшие артефакты, такие как ненужные белые границы.
-
Эрозия уменьшает белые области в изображении. Это достигается с помощью свертки с ядром (например, матрицей из единиц), которое сканирует изображение и удаляет пиксели на границе объектов, уменьшая их размер.
-
Дилатация увеличивает области объектов, что может помочь восстановить полезную информацию после применения эрозии.
В Python это можно реализовать с использованием библиотеки OpenCV:
import cv2
def remove_white_borders(image_path):
# Загрузите изображение
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
# Примените эрозию для уменьшения белых областей
kernel = np.ones((5, 5), np.uint8)
eroded = cv2.erode(img, kernel, iterations=1)
# Примените дилатацию для восстановления структуры
dilated = cv2.dilate(eroded, kernel, iterations=1)
return dilated
Эту функцию можно использовать на этапе постобработки, чтобы улучшить качество сегментации и удалить белые границы.
Таким образом, внедрение правок и корректная настройка параметров морфологических операций могут существенно улучшить результаты сегментации изображения. Рекомендуется также тщательно проверять и модифицировать алгоритм кластеризации и пороговые значения, чтобы оптимально выделять только интересующие области легких.