一种想法是执行 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])
Mask ->
Result
对于中等地区
lower = np.array([90, 0, 0])
upper = np.array([102, 255, 255])
最后得到小区域
lower = np.array([84, 0, 0])
upper = np.array([98, 255, 255])
Code
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()