溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python+OpenCV中如何利用K-Means?聚類進(jìn)行色彩量化

發(fā)布時間:2021-12-03 13:33:29 來源:億速云 閱讀:226 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下Python+OpenCV中如何利用K-Means 聚類進(jìn)行色彩量化,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

    利用 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)鍵點是利用 cv2.kmeans() 方法。最后,可以用 k 種顏色來構(gòu)建圖像,用它們對應(yīng)的中心值替換每個像素值,程序的運行結(jié)果如下所示:

    Python+OpenCV中如何利用K-Means?聚類進(jìn)行色彩量化

    Python+OpenCV中如何利用K-Means?聚類進(jìn)行色彩量化

    完整代碼

    利用 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()

    顯示色彩量化后的色彩分布

    可以擴展以上程序使其顯示色彩量化后的色彩分布,該色彩分布顯示了分配給每個聚類中心的像素數(shù)。只需擴展 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))

    程序的輸出如下所示:

    Python+OpenCV中如何利用K-Means?聚類進(jìn)行色彩量化

    從上圖可以看出,使用 K-Means 聚類算法應(yīng)用色彩量化后改變參數(shù) k (10、20、30、40、50、60 和 70) 的結(jié)果,k 值越大產(chǎn)生的圖像越逼真。

    Note:除了 color_quantization() 函數(shù)外,由于其他代碼并未修改,因此不再另外給出。 

    以上是“Python+OpenCV中如何利用K-Means 聚類進(jìn)行色彩量化”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI