多媒體技術 || 用中位切割演算法實現影象減色
阿新 • • 發佈:2018-10-31
- 實現環境:python
處理一張紅蘋果圖:
先描述一下中位切割演算法吧:
- 將圖片內的所有畫素加入到同一個區域
- 對於所有的區域做以下的事:
- 計算此區域內所有畫素的 RGB 三元素最大值與最小值的差。
- 選出相差最大的那個顏色(R 或 G 或 B)
- 根據那個顏色去排序此區域內所有畫素
- 分割前一半與後一半的畫素到二個不同的區域(這裡就是“中位切
割”名字的由來) - 重複第二步直到你有 256 個區域
- 將每個區域內的畫素平均起來,於是你就得到了 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無法顯示,故只截取了一部分)