Python+OpenCV實(shí)戰(zhàn)之利用?K-Means?聚類進(jìn)行色彩量化
前言
K-Means 聚類算法的目標(biāo)是將 n 個樣本劃分(聚類)為 K 個簇,在博文《OpenCV與機(jī)器學(xué)習(xí)的碰撞》中,我們已經(jīng)學(xué)習(xí)利用 OpenCV 提供了 cv2.kmeans() 函數(shù)實(shí)現(xiàn) K-Means 聚類算法,該算法通過找到簇的中心并將輸入樣本分組到簇周圍,同時通過簡單的示例了解了 K-Means 算法的用法。在本文中,我們將學(xué)習(xí)如何利用 K-Means 聚類進(jìn)行色彩量化,以減少圖像中顏色數(shù)量。
利用 K-Means 聚類進(jìn)行色彩量化
色彩量化問題可以定義為減少圖像中顏色數(shù)量的過程。色彩量化對于某些設(shè)備顯示圖像非常關(guān)鍵,這些設(shè)備可能由于內(nèi)存限制等原因只能顯示有限顏色,因此,在這些設(shè)備上顯示色彩通常需要在準(zhǔn)確性和減少顏色數(shù)量之間進(jìn)行權(quán)衡,在利用 K-Means 聚類進(jìn)行色彩量化時,權(quán)衡兩者是通過正確設(shè)置 K 參數(shù)來進(jìn)行的。
利用 K-Means 聚類算法來執(zhí)行色彩量化,簇中心數(shù)據(jù)由 3 個特征組成,它們對應(yīng)于圖像每個像素的 B、G 和 R 值。因此,關(guān)鍵是將圖像轉(zhuǎn)換為數(shù)據(jù):
data = np.float32(image).reshape((-1, 3))
為了觀察如何權(quán)衡準(zhǔn)確性和顏色數(shù),我們使用不同 K 值 (3 、 5 、 10 、 20 和 40) 執(zhí)行聚類過程,以查看生成的圖像如何變化,如果我們想要只有 3 種顏色 (K = 3) 的結(jié)果圖像,需要執(zhí)行以下操作:
加載 BGR 圖像:
img = cv2.imread('example.jpg')
使用 color_quantization()
函數(shù)執(zhí)行色彩量化:
def color_quantization(image, k): # 將圖像轉(zhuǎn)換為數(shù)據(jù) data = np.float32(image).reshape((-1, 3)) # 算法終止條件 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0) # K-Means 聚類 ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) # 簇中心 center = np.uint8(center) # 將具有 k 顏色中心的圖像轉(zhuǎn)換為 uint8 result = center[label.flatten()] result = result.reshape(img.shape) return result color_3 = color_quantization(img, 3)
color_quantization()
函數(shù)中,關(guān)鍵點(diǎn)是利用 cv2.kmeans()
方法。最后,可以用 k 種顏色來構(gòu)建圖像,用它們對應(yīng)的中心值替換每個像素值,程序的運(yùn)行結(jié)果如下所示:
完整代碼
利用 K-Means 聚類進(jìn)行色彩量化的完整代碼如下所示:
import numpy as np import cv2 from matplotlib import pyplot as plt def show_img_with_matplotlib(color_img, title, pos): img_RGB = color_img[:, :, ::-1] ax = plt.subplot(2, 4, pos) plt.imshow(img_RGB) plt.title(title, fontsize=8) plt.axis('off') def color_quantization(image, k): # 將圖像轉(zhuǎn)換為數(shù)據(jù) data = np.float32(image).reshape((-1, 3)) # 算法終止條件 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0) # K-Means 聚類 ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) # 簇中心 center = np.uint8(center) # 將具有 k 顏色中心的圖像轉(zhuǎn)換為 uint8 result = center[label.flatten()] result = result.reshape(img.shape) return result fig = plt.figure(figsize=(16, 8)) plt.suptitle("Color quantization using K-means clustering algorithm", fontsize=14, fontweight='bold') # 圖片加載 img = cv2.imread('example.png') show_img_with_matplotlib(img, "original image", 1) # 使用不同 K 值進(jìn)行色彩量化 for i in range(7): color = color_quantization(img, (i+1) * 10) show_img_with_matplotlib(color, "color quantization (k = {})".format((i+1) * 10), i+2) plt.show()
顯示色彩量化后的色彩分布
可以擴(kuò)展以上程序使其顯示色彩量化后的色彩分布,該色彩分布顯示了分配給每個聚類中心的像素數(shù)。只需擴(kuò)展 color_quantization()
函數(shù)已被修改為包含所需功能:
import collections def color_quantization(image, k): # 將圖像轉(zhuǎn)換為數(shù)據(jù) data = np.float32(image).reshape((-1, 3)) # 算法終止條件 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0) # K-Means 聚類 ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) # 簇中心 center = np.uint8(center) # 將具有 k 顏色中心的圖像轉(zhuǎn)換為 uint8 result = center[label.flatten()] result = result.reshape(img.shape) # 統(tǒng)計分配給每個聚類中心的像素數(shù) counter = collections.Counter(label.flatten()) print(counter) # 計算輸入圖像的總像素數(shù) total = img.shape[0] * img.shape[1] # 為色彩分布圖像指定寬度和高度: desired_width = img.shape[1] desired_height = 70 desired_height_colors = 50 # 初始化色彩分布圖像 color_distribution = np.ones((desired_height, desired_width, 3), dtype='uint8') * 255 start = 0 for key, value in counter.items(): # 歸一化 value_normalized = value / total * desired_width end = start + value_normalized # 繪制與當(dāng)前顏色對應(yīng)的矩形 cv2.rectangle(color_distribution, (int(start), 0), (int(end), desired_height_colors), center[key].tolist(), -1) start = end return np.vstack((color_distribution, result))
上述代碼中,使用 collections.Counter() 來統(tǒng)計分配給每個聚類中心的像素數(shù):
counter = collections.Counter(label.flatten())
例如,如果 K = 10,則可以得到如下結(jié)果:
Counter({7: 37199, 3: 36302, 0: 29299, 5: 23987, 6: 23895, 1: 20077, 9: 19814, 8: 18427, 4: 16221, 2: 14779})
構(gòu)建色彩分布圖像后,將其與色彩量化后的圖像連接在一起:
np.vstack((color_distribution, result))
程序的輸出如下所示:
從上圖可以看出,使用 K-Means 聚類算法應(yīng)用色彩量化后改變參數(shù) k (10、20、30、40、50、60 和 70) 的結(jié)果,k 值越大產(chǎn)生的圖像越逼真。
Note:除了 color_quantization() 函數(shù)外,由于其他代碼并未修改,因此不再另外給出。?
到此這篇關(guān)于Python+OpenCV實(shí)戰(zhàn)之利用 K-Means 聚類進(jìn)行色彩量化的文章就介紹到這了,更多相關(guān)OpenCV? K-Means 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python greenlet和gevent使用代碼示例解析
這篇文章主要介紹了Python greenlet和gevent使用代碼示例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04PyTorch中 tensor.detach() 和 tensor.data 的
這篇文章主要介紹了PyTorch中 tensor.detach() 和 tensor.data 的區(qū)別解析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04Python通過調(diào)用mysql存儲過程實(shí)現(xiàn)更新數(shù)據(jù)功能示例
這篇文章主要介紹了Python通過調(diào)用mysql存儲過程實(shí)現(xiàn)更新數(shù)據(jù)功能,結(jié)合實(shí)例形式分析了Python調(diào)用mysql存儲過程實(shí)現(xiàn)更新數(shù)據(jù)的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2018-04-04Django+Ajax+jQuery實(shí)現(xiàn)網(wǎng)頁動態(tài)更新的實(shí)例
今天小編就為大家分享一篇Django+Ajax+jQuery實(shí)現(xiàn)網(wǎng)頁動態(tài)更新的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05Python通用函數(shù)實(shí)現(xiàn)數(shù)組計算的方法
數(shù)組的運(yùn)算可以進(jìn)行加減乘除,同時也可以將這些算數(shù)運(yùn)算符進(jìn)行任意的組合已達(dá)到效果。這篇文章主要介紹了Python通用函數(shù)實(shí)現(xiàn)數(shù)組計算的代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧2019-06-06