使用OpenCV Python中的K-means在图像中进行颜色量化?
在 颜色量化 的过程中,减少了在图像中使用的颜色数量。 这样做的一个原因是为了减少内存使用。 有时,某些设备只能生成有限数量的颜色。 在这些情况下,执行颜色量化。我们使用 cv2.kmeans() 对颜色量化应用k-means聚类。
步骤
要使用K-means聚类在图像中实现颜色量化,可以按照下面给出的步骤进行操作 −
- 导入所需的库 OpenCV 和 NumPy 。请确保您已经安装了它们。
-
使用 cv2.imread() 方法读取两个输入图像。 指定图像的完整路径。 将图像重塑为大小为Mx3的数组(M是图像中像素的总数)。 将图像的dtype转换为 np.float32 。
-
定义迭代终止条件( criteria ),聚类的数量( K )并应用K-means聚类算法( cv2.kmeans() )。 传递标志 cv2.KMEANS_RANDOM_CENTERS或cv.KMEANS_PP_CENTERS以指定如何获取初始中心。
-
现在将其转换回uint8,并通过将质心值应用于所有像素来制作指定颜色数(K)的结果图像。
-
显示生成的图像。
让我们看一些示例,以使用K-means聚类在图像中实现颜色量化。
输入图像
我们将在下面的示例中将此图像用作输入文件。
示例
在下面的Python代码中,我们在输入图像中使用K-means聚类算法执行颜色量化,其中K = 8。
# 导入所需的库
import numpy as np
import cv2
# 读取输入图像
img = cv2.imread('horizon.jpg')
z = img.reshape((-1,3))
# 转换为 np.float32
z = np.float32(z)
# 定义标准,聚类的数量K并应用kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K =8
ret,label,center=cv2.kmeans(z,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)
# 转换回uint8,并制作原始图像
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))
# 显示图像
cv2.imshow('带有K = 8的图像',res2)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出
运行上述Python程序后,它将生成以下输出窗口−
请注意上面输出图像中使用的颜色数量被减少到8,因为我们使用了K=8。
例子
在下面的Python代码中,我们使用K-means聚类算法对输入图像进行颜色量化,使用不同的K值(K=2,K=5和K=8)。
# import required libraries
import numpy as np
import cv2
import matplotlib.pyplot as plt
# read input image
img = cv2.imread('horizon.jpg')
Z = img.reshape((-1,3))
# convert to np.float32
Z = np.float32(Z)
# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
def colorQuant(Z, K, criteria):
ret,label,center=cv2.kmeans(Z,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)
# Now convert back into uint8, and make original image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))
return res2
res1 = colorQuant(Z, 2, criteria)
res2 = colorQuant(Z, 5, criteria)
res3 = colorQuant(Z, 8, criteria)
plt.subplot(221),plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(222),plt.imshow(cv2.cvtColor(res1, cv2.COLOR_BGR2RGB))
plt.title('K=2'), plt.xticks([]), plt.yticks([])
plt.subplot(223),plt.imshow(cv2.cvtColor(res2, cv2.COLOR_BGR2RGB))
plt.title('K=4'), plt.xticks([]), plt.yticks([])
plt.subplot(224),plt.imshow(cv2.cvtColor(res3, cv2.COLOR_BGR2RGB))
plt.title('K=8'), plt.xticks([]), plt.yticks([])
plt.show()
输出
当您执行上述代码时,它将生成以下 输出 −
请注意不同输出图像中存在的颜色差异。高K值越接近原始图像。