В этом блоге я поделюсь объясненной реализацией сегментации изображений с использованием кластеризации K-средних. Также я поделюсь своей реализацией Jupyter Notebook для справки.
Итак, прежде чем мы перейдем к реализации, давайте узнаем, что такое сегментация изображений и как ее использовать.
Сегментация изображения:
В компьютерном зрении сегментация изображения — это процесс разделения изображения на несколько сегментов. Цель сегментации изображения состоит в том, чтобы изменить представление изображения во что-то более осмысленное и более простое для анализа. Обычно он используется для поиска объектов и создания границ.
Не рекомендуется обрабатывать изображение целиком, потому что многие части изображения могут не содержать никакой полезной информации. Поэтому, сегментируя изображение, мы можем использовать для обработки только важные сегменты.
Изображение в основном представляет собой набор заданных пикселей. При сегментации изображения пиксели со схожими атрибутами группируются вместе. Сегментация изображения создает попиксельную маску для объектов на изображении, что дает нам более полное и детальное представление об объекте.
Использование:
- Используется в беспилотных автомобилях. Автономное вождение невозможно без обнаружения объектов, которое включает сегментацию.
- Используется в сфере здравоохранения. Полезен для сегментации раковых клеток и опухолей, с помощью которых можно оценить их тяжесть.
Есть много других применений сегментации изображений.
Теперь давайте рассмотрим метод чтения изображения и кластеризации различных областей изображения с использованием алгоритма кластеризации K-средних и OpenCV.
Итак, в основном мы будем выполнять кластеризацию цветов и обнаружение Canny Edge.
Прежде чем мы перейдем к реализации, если вы хотите узнать о кластеризации OpenCV и K-Means, у меня тоже есть блог для них, так что проверьте.
OpenCV:
Кластеризация K-средних:
Итак, теперь давайте начнем с кода.
Цветовая кластеризация:
Загрузите все необходимые библиотеки:
import numpy as np import cv2 import matplotlib.pyplot as plt
Следующим шагом является загрузка изображения в цветовом пространстве RGB.
original_image = cv2.imread("/Users/path/../image1.jpg")
Исходное изображение:
Нам нужно преобразовать наше изображение из цветового пространства RGB в HSV, чтобы продолжить работу.
Но вопрос в том, почему??
Согласно Википедии, компоненты R, G и B цвета объекта в цифровом изображении коррелируют с количеством света, попадающего на объект, и, следовательно, друг с другом, описание изображения с точки зрения этих компонентов делает различение объектов затруднено. Описания в терминах оттенок/яркость/цветность или оттенок/яркость/насыщенность часто более уместны.
img=cv2.cvtColor(original_image,cv2.COLOR_BGR2RGB)
Затем преобразует изображение MxNx3 в матрицу Kx3, где K=MxN, а каждая строка теперь является вектором в трехмерном пространстве RGB.
vectorized = img.reshape((-1,3))
Мы преобразуем значения unit8 в числа с плавающей запятой, поскольку это требование метода k-means в OpenCV.
vectorized = np.float32(vectorized)
Мы собираемся сгруппировать с k = 3, потому что, если вы посмотрите на изображение выше, оно имеет 3 цвета: зеленую траву и лес, синее море и зеленовато-голубой морской берег.
Определите критерии, количество кластеров (K) и примените k-means()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
OpenCV предоставляет функцию cv2.kmeans(samples, nclusters(K), критерии, попытки, флаги) для цветовой кластеризации.
1. образцы: он должен иметь тип данных np.float32, и каждая функция должна быть помещена в один столбец.
2. nclusters(K): количество кластеров, необходимых в конце
3. критерии: это критерии завершения итерации. При выполнении этого критерия итерация алгоритма останавливается. На самом деле это должен быть кортеж из 3-х параметров. Это `( type, max_iter, epsilon )`:
Тип критериев прекращения. Он имеет 3 флага, как показано ниже:
- cv.TERM_CRITERIA_EPS — остановить итерацию алгоритма, если достигнута заданная точность, epsilon.
- cv.TERM_CRITERIA_MAX_ITER — остановить алгоритм после указанного количества итераций, max_iter.
- cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER — остановить итерацию при выполнении любого из вышеуказанных условий.
4. попыток: Флаг, указывающий, сколько раз алгоритм выполняется с использованием различных начальных меток. Алгоритм возвращает метки, обеспечивающие наилучшую компактность. Эта компактность возвращается в качестве вывода.
5. флаги: этот флаг используется для указания того, как берутся начальные центры. Обычно для этого используются два флага: cv.KMEANS_PP_CENTERS и cv.KMEANS_RANDOM_CENTERS.
K = 3 attempts=10 ret,label,center=cv2.kmeans(vectorized,K,None,criteria,attempts,cv2.KMEANS_PP_CENTERS)
Теперь конвертируйте обратно в uint8.
center = np.uint8(center)
Затем нам нужно получить доступ к меткам, чтобы восстановить кластеризованное изображение.
res = center[label.flatten()] result_image = res.reshape((img.shape))
Теперь давайте визуализируем результат вывода с K = 3.
figure_size = 15 plt.figure(figsize=(figure_size,figure_size)) plt.subplot(1,2,1),plt.imshow(img) plt.title('Original Image'), plt.xticks([]), plt.yticks([]) plt.subplot(1,2,2),plt.imshow(result_image) plt.title('Segmented Image when K = %i' % K), plt.xticks([]), plt.yticks([]) plt.show()
Таким образом, алгоритм разделил наше исходное изображение на три доминирующих цвета.
Давайте посмотрим, что произойдет, если мы изменим значение K=5:
Давайте перейдем к нашей следующей части — обнаружению Canny Edge.
Обнаружение краев Canny: это метод обработки изображения, используемый для обнаружения краев на изображении с подавлением шума.
Алгоритм обнаружения Canny Edge состоит из 5 шагов:
- Расчет градиента
- Немаксимальное подавление
- Двойной порог
- Отслеживание границ по гистерезису
OpenCV предоставляет функцию cv2.Canny(image, threshold1,threshold2) для обнаружения границ.
Первый аргумент — это наше входное изображение. Второй и третий аргументы — это наши минимальный и максимальный порог соответственно.
Функция находит края во входном изображении (8-битное входное изображение) и отмечает их в краях выходной карты, используя алгоритм Кэнни. Наименьшее значение между порогом 1 и порогом 2 используется для привязки к границе. Наибольшее значение используется для поиска начальных сегментов сильных ребер.
Исходное изображение:
Это будет изображение, которое мы будем использовать для обнаружения хитрых краев.
edges = cv2.Canny(img,150,200) plt.figure(figsize=(figure_size,figure_size)) plt.subplot(1,2,1),plt.imshow(img) plt.title('Original Image'), plt.xticks([]), plt.yticks([]) plt.subplot(1,2,2),plt.imshow(edges,cmap = 'gray') plt.title('Edge Image'), plt.xticks([]), plt.yticks([]) plt.show()
Изображение будет выглядеть так:
Вот ссылка на мой Jupyter Notebook для справки.
Изображения можно найти в том же каталоге в папке с именем Images.
Итак, это все, что я могу сказать о сегментации изображений с использованием кластеризации K-средних. Я надеюсь, что вы найдете это полезным. Спасибо, что дочитали до конца.