多媒体技术 || 用中位切割算法实现图像减色

  • 实现环境: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无法显示,故只截取了一部分)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/perry0528/article/details/83048388