Сегментация изображений играет жизненно важную роль в понимании и анализе визуальных данных, а нормализованные разрезы (NCut) — широко используемый метод сегментации на основе графов. В этой статье мы рассмотрим, как применить NCut для неконтролируемой сегментации изображений в Python, используя набор данных от Microsoft Research, уделяя особое внимание улучшению качества сегментации с помощью суперпикселей.
Обзор набора данных
Набор данных, используемый для этой задачи, можно загрузить по следующей ссылке: База данных изображений категорий объектов MSRC. Этот набор данных содержит исходные изображения, а также их семантическую сегментацию на девять классов объектов (обозначенных файлами изображений, заканчивающимися на «_GT»). Эти изображения сгруппированы в тематические подмножества, где первая цифра в имени файла относится к подмножеству класса. Этот набор данных идеально подходит для экспериментов с задачами сегментации.
Мы выполняем сегментацию изображения в наборе данных с использованием алгоритма NCut. Сегментация на уровне пикселей требует больших вычислительных затрат и часто зашумлена. Чтобы преодолеть эту проблему, мы используем SLIC (простую линейную итеративную кластеризацию) для генерации суперпикселей, которая группирует похожие пиксели и уменьшает размер проблемы. Для оценки точности сегментации можно использовать различные метрики (например, Intersection over Union, SSIM, Rand Index).
1. Установите необходимые библиотеки
Мы используем Skimage для обработки изображений, numpy для численных вычислений и matplotlib для визуализации.
pip install numpy matplotlib pip install scikit-image==0.24.0 **2. Load and Preprocess the Dataset**
После загрузки и извлечения набора данных загрузите изображения и основную сегментацию:
wget http://download.microsoft.com/download/A/1/1/A116CD80-5B79-407E-B5CE-3D5C6ED8B0D5/msrc_objcategimagedatabase_v1.zip -O msrc_objcategimagedatabase_v1.zip unzip msrc_objcategimagedatabase_v1.zip rm msrc_objcategimagedatabase_v1.zip
Теперь мы готовы приступить к кодированию.
from skimage import io, segmentation, color, measure from skimage import graph import numpy as np import matplotlib.pyplot as plt # Load the image and its ground truth image = io.imread('/content/MSRC_ObjCategImageDatabase_v1/1_16_s.bmp') ground_truth = io.imread('/content/MSRC_ObjCategImageDatabase_v1/1_16_s_GT.bmp') # show images side by side fig, ax = plt.subplots(1, 2, figsize=(10, 5)) ax[0].imshow(image) ax[0].set_title('Image') ax[1].imshow(ground_truth) ax[1].set_title('Ground Truth') plt.show()
3. Сгенерируйте суперпиксели с помощью SLIC и создайте график смежности регионов
Мы используем алгоритм SLIC для вычисления суперпикселей перед применением NCut. Используя сгенерированные суперпиксели, мы строим граф смежности регионов (RAG) на основе среднего сходства цветов:
from skimage.util import img_as_ubyte, img_as_float, img_as_uint, img_as_float64 compactness=30 n_segments=100 labels = segmentation.slic(image, compactness=compactness, n_segments=n_segments, enforce_connectivity=True) image_with_boundaries = segmentation.mark_boundaries(image, labels, color=(0, 0, 0)) image_with_boundaries = img_as_ubyte(image_with_boundaries) pixel_labels = color.label2rgb(labels, image_with_boundaries, kind='avg', bg_label=0
компактность контролирует баланс между цветовым сходством и пространственной близостью пикселей при формировании суперпикселей. Он определяет, насколько большое внимание уделяется сохранению компактности суперпикселей (ближе в пространственном отношении) по сравнению с обеспечением их более однородной группировки по цвету.
Более высокие значения: более высокое значение компактности заставляет алгоритм отдавать приоритет созданию суперпикселей, пространственно плотных и однородных по размеру, с меньшим вниманием к цветовому сходству. Это может привести к тому, что суперпиксели будут менее чувствительны к краям или цветовым градиентам.
Меньшие значения: более низкое значение компактности позволяет суперпикселям больше различаться по пространственному размеру, чтобы более точно учитывать различия в цвете. Обычно это приводит к тому, что суперпиксели более точно повторяют границы объектов на изображении.
n_segments управляет количеством суперпикселей (или сегментов), которые алгоритм SLIC пытается создать в изображении. По сути, он устанавливает разрешение сегментации.
Более высокие значения: более высокое значение n_segments создает больше суперпикселей, что означает, что каждый суперпиксель будет меньше, а сегментация будет более мелкозернистой. Это может быть полезно, если изображение имеет сложные текстуры или мелкие объекты.
Меньшие значения: меньшее значение n_segments дает меньше суперпикселей большего размера. Это полезно, если вам нужно грубо сегментировать изображение, группируя большие области в отдельные суперпиксели.
4. Примените нормализованные вырезы (NCut) и визуализируйте результат
# using the labels found with the superpixeled image # compute the Region Adjacency Graph using mean colors g = graph.rag_mean_color(image, labels, mode='similarity') # perform Normalized Graph cut on the Region Adjacency Graph labels2 = graph.cut_normalized(labels, g) segmented_image = color.label2rgb(labels2, image, kind='avg') f, axarr = plt.subplots(nrows=1, ncols=4, figsize=(25, 20)) axarr[0].imshow(image) axarr[0].set_title("Original") #plot boundaries axarr[1].imshow(image_with_boundaries) axarr[1].set_title("Superpixels Boundaries") #plot labels axarr[2].imshow(pixel_labels) axarr[2].set_title('Superpixel Labels') #compute segmentation axarr[3].imshow(segmented_image) axarr[3].set_title('Segmented image (normalized cut)')
5. Показатели оценки
Основная проблема неконтролируемой сегментации заключается в том, что NCut не знает точного количества классов в изображении. Количество сегментов, найденных NCut, может превышать фактическое количество наземных регионов. В результате нам нужны надежные показатели для оценки качества сегментации.
Пересечение через объединение (IoU) — широко используемый показатель для оценки задач сегментации, особенно в компьютерном зрении. Он измеряет перекрытие между предсказанными сегментированными регионами и регионами основной истины. В частности, IoU вычисляет отношение области перекрытия между предсказанной сегментацией и основной истиной к области их объединения.
Индекс структурного сходства (SSIM) — это показатель, используемый для оценки воспринимаемого качества изображения путем сравнения двух изображений с точки зрения яркости, контрастности и структуры.
Чтобы применить эти метрики, нам нужно, чтобы прогноз и истинное изображение имели одинаковые метки. Чтобы вычислить метки, мы вычисляем маску на земле, а в прогнозе присваиваем идентификатор каждому цвету, найденному на изображении
Однако сегментация с использованием NCut может обнаружить больше регионов, чем наземная истина, это снизит точность.
def compute_mask(image): color_dict = {} # Get the shape of the image height,width,_ = image.shape # Create an empty array for labels labels = np.zeros((height,width),dtype=int) id=0 # Loop over each pixel for i in range(height): for j in range(width): # Get the color of the pixel color = tuple(image[i,j]) # Check if it is in the dictionary if color in color_dict: # Assign the label from the dictionary labels[i,j] = color_dict[color] else: color_dict[color]=id labels[i,j] = id id =1 return(labels) def show_img(prediction, groundtruth): f, axarr = plt.subplots(nrows=1, ncols=2, figsize=(15, 10)) axarr[0].imshow(groundtruth) axarr[0].set_title("groundtruth") axarr[1].imshow(prediction) axarr[1].set_title(f"prediction") prediction_mask = compute_mask(segmented_image) groundtruth_mask = compute_mask(ground_truth) #usign the original image as baseline to convert from labels to color prediction_img = color.label2rgb(prediction_mask, image, kind='avg', bg_label=0) groundtruth_img = color.label2rgb(groundtruth_mask, image, kind='avg', bg_label=0) show_img(prediction_img, groundtruth_img)
Теперь мы вычисляем показатели точности
from sklearn.metrics import jaccard_score from skimage.metrics import structural_similarity as ssim ssim_score = ssim(prediction_img, groundtruth_img, channel_axis=2) print(f"SSIM SCORE: {ssim_score}") jac = jaccard_score(y_true=np.asarray(groundtruth_mask).flatten(), y_pred=np.asarray(prediction_mask).flatten(), average = None) # compute mean IoU score across all classes mean_iou = np.mean(jac) print(f"Mean IoU: {mean_iou}")
Нормализованные вырезы — это мощный метод неконтролируемой сегментации изображений, но он сопряжен с такими проблемами, как чрезмерная сегментация и настройка параметров. Включая суперпиксели и оценивая производительность с использованием соответствующих показателей, NCut может эффективно сегментировать сложные изображения. Метрики IoU и Rand Index дают содержательную информацию о качестве сегментации, хотя для эффективной обработки сценариев с несколькими классами необходимы дальнейшие уточнения.
Наконец, полный пример доступен в моем блокноте здесь.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3