Одна идея состоит в том, чтобы выполнить квантование цветов Kmeans, чтобы сгруппировать изображение в различное количество цветов. После этого мы можем преобразовать изображение в формат HSV и выполнить пороговое значение цвета, используя cv2.inRange
с нижним / верхним цветовым порогом, чтобы получить двоичную маску. Наконец, мы применяем эту маску к исходному изображению, используя cv2.bitwise_and
.
Исходное изображение ->
Квантование цвета Kmeans с clusters=5
Обратите внимание на небольшую разницу в том, что все изображение сегментировано в пять цветов. Вот визуализация каждого цветового кластера и процент распределения цвета. Основываясь на сегментации цвета, мы можем оценить, что в первых трех цветах (без учета черного) есть бактерии.
[ 67.70980019 86.19251507 121.19410086] 0.87%
[120.61108133 146.00169267 159.48142297] 9.78%
[0.18113609 0.22505063 0.25559479] 21.40%
[134.06236381 170.04397205 167.3696234 ] 23.44%
[140.53640479 189.4275781 171.19319177] 44.50%
Далее мы выполняем пороговое значение цвета для получения маски с этим нижним / верхним цветовым диапазоном
lower = np.array([84, 0, 0])
upper = np.array([179, 255, 255])
Мы применяем маску к исходному изображению, чтобы получить наш результат
Помните, как было три цветовых распределения, которые мы использовали, чтобы определить, были ли бактерии? Если мы изменим диапазон цветового порога, мы можем еще больше разделить изображение на большие, средние и маленькие области бактерий.
Мы можем выделить только крупные области бактерий, используя эту цветовую гамму
lower = np.array([104, 0, 0])
upper = np.array([179, 255, 255])
Маска ->
Результат
Для средних регионов
lower = np.array([90, 0, 0])
upper = np.array([102, 255, 255])
Наконец, для получения небольших регионов
lower = np.array([84, 0, 0])
upper = np.array([98, 255, 255])
Код
import cv2
import numpy as np
# Kmeans color segmentation
def kmeans_color_quantization(image, clusters=8, rounds=1):
h, w = image.shape[:2]
samples = np.zeros([h*w,3], dtype=np.float32)
count = 0
for x in range(h):
for y in range(w):
samples[count] = image[x][y]
count += 1
compactness, labels, centers = cv2.kmeans(samples,
clusters,
None,
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001),
rounds,
cv2.KMEANS_RANDOM_CENTERS)
centers = np.uint8(centers)
res = centers[labels.flatten()]
return res.reshape((image.shape))
# Load original image
original = cv2.imread('2.png')
# Perform kmeans color segmentation
kmeans = kmeans_color_quantization(original, clusters=5)
# Color threshold on kmeans image
hsv = cv2.cvtColor(kmeans, cv2.COLOR_BGR2HSV)
lower = np.array([84, 0, 0])
upper = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
# Apply mask onto original image
result = cv2.bitwise_and(original, original, mask=mask)
result[mask==0] = (255,255,255)
# Display
cv2.imshow('kmeans', kmeans)
cv2.imshow('result', result)
cv2.imshow('mask', mask)
cv2.waitKey()
Этот скрипт HSV для определения цветового разрешения использовался для определения нижнего / верхнего цветовых диапазонов
import cv2
import numpy as np
def nothing(x):
pass
# Load image
image = cv2.imread('1.png')
# Create a window
cv2.namedWindow('image')
# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)
# Set default value for Max HSV trackbars
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)
# Initialize HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0
while(1):
# Get current positions of all trackbars
hMin = cv2.getTrackbarPos('HMin', 'image')
sMin = cv2.getTrackbarPos('SMin', 'image')
vMin = cv2.getTrackbarPos('VMin', 'image')
hMax = cv2.getTrackbarPos('HMax', 'image')
sMax = cv2.getTrackbarPos('SMax', 'image')
vMax = cv2.getTrackbarPos('VMax', 'image')
# Set minimum and maximum HSV values to display
lower = np.array([hMin, sMin, vMin])
upper = np.array([hMax, sMax, vMax])
# Convert to HSV format and color threshold
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)
# Print if there is a change in HSV value
if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
phMin = hMin
psMin = sMin
pvMin = vMin
phMax = hMax
psMax = sMax
pvMax = vMax
# Display result image
cv2.imshow('image', result)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()