1. 程式人生 > >多媒體技術 || 用中位切割演算法實現影象減色

多媒體技術 || 用中位切割演算法實現影象減色

  • 實現環境:python
    處理一張紅蘋果圖:
    在這裡插入圖片描述
    先描述一下中位切割演算法吧:
  1. 將圖片內的所有畫素加入到同一個區域
  2. 對於所有的區域做以下的事:
  3. 計算此區域內所有畫素的 RGB 三元素最大值與最小值的差。
  4. 選出相差最大的那個顏色(R 或 G 或 B)
  5. 根據那個顏色去排序此區域內所有畫素
  6. 分割前一半與後一半的畫素到二個不同的區域(這裡就是“中位切
    割”名字的由來)
  7. 重複第二步直到你有 256 個區域
  8. 將每個區域內的畫素平均起來,於是你就得到了 256 色

於是根據維基百科的演算法描述先是實現了一個 cube 的類用於進行區域的篩選,


cube.py:

from statistics import mean

class Cube(object):
    def __init__(self, colors):
        self.colors = colors or []
        self.red = [r[0] for r in colors]
        self.green = [g[1] for g in colors]
        self.blue = [b[2] for b in colors]
        self.size = (max(self.red) - min(self.
red), max(self.green) - min(self.green), max(self.blue) - min(self.blue)) self.range = max(self.size) self.channel = self.size.index(self.range) def __lt__(self, other): return self.range < other.range def average(self): r =
int(mean(self.red)) g = int(mean(self.green)) b = int(mean(self.blue)) return r, g, b def split(self): middle = int(len(self.colors) / 2) colors = sorted(self.colors, key=lambda c: c[self.channel]) return Cube(colors[:middle]), Cube(colors[middle:])

main 函數借助 Cube 類實現了對影象中畫素 rgb 值對應 LUT 的匹配:
main.py

from PIL import Image
from cube import Cube
import numpy as np
import matplotlib.pyplot as plt

def median_cut(img, num):
    colors = []
    for count, color in img.getcolors(img.width * img.height):
        colors += [color]
    cubes = [Cube(colors)]

    while len(cubes) < num:
        cubes.sort()
        cubes += cubes.pop().split()
    i = 0
    LUT = {}
    index = ()
    for c in cubes:
        average = c.average()
        for color in c.colors:
            LUT[color] = average                
    return LUT

def main() :
    image = Image.open('E://Desktop//duomeiti//redapple.jpg')
    LUT = median_cut(image, 256)
    img = np.array(image)
    rows,cols,channel=img.shape
    for i in range(rows):
        for j in range(cols):
            index = (img[i,j,0],img[i,j,1],img[i,j,2])
            color = LUT[index]
            img[i,j] = color
    plt.imshow(img)
    plt.axis('off')
    plt.savefig('result3.jpg')
    plt.show()

if __name__ == "__main__":
    main()

結果示例:
在這裡插入圖片描述

如果將顏色表提取出來效果如下:
(因256色帶是在太大csdn無法顯示,故只截取了一部分)
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述