图片主色提取

提取主色

最近有个小任务,需要提取图片中的主色块。最基本的做法就是聚类找主色,但是目前需要自适应提取,也就是说需要对于不同的图片提取出不同的主色块数量。

1. RGB Or HSV

貌似大多数提取主色都是建立在RGB色彩空间中,但是就人眼感知而言对红色不太敏感而对蓝色较为敏感;而且,RGB色彩空间是利用三个颜色分量的线性组合来表示颜色相关性很高,所以RGB是一种不均匀的颜色空间。

img

再来看看HSV,对于单一颜色我们可以控制颜色角H,通过调整饱和度和明度就能得到同颜色系的不同颜色,这样的话我们聚类的结果也应该更为准确,所以我这里选择HSV颜色空间来进行聚类。

2. KMeans 自适应

我们都知道聚类效果的好坏有很多评价指标,比如SSE、轮廓系数……但是“肘部法”对于自适应来说并不适用,所以还是选择轮廓系数最大的k值作为最优k值。

并且对于图片聚类来说,一张图中的像素点很多,计算KMeans以及轮廓系数十分耗时,为了效率我进行了以下操作:

  • 对输入图片进行缩放,缩小图片大小
  • 使用MiniBatchKMeans代替``Kmeans`
  • 计算轮廓系数时进行采样计算

3. 整体过程及代码

  1. 读取图片,并缩小
  2. 将RGB转为HSV进行聚类,找到最好的K值
  3. 利用最好的K值再次聚类,得到最终结果并转回RGB
  4. 可视化提取的主色块
import time
from functools import wraps
import matplotlib.pyplot as plt
import numpy as np
from skimage.color import rgb2hsv, hsv2rgb
from skimage import transform
from skimage.io import imread
from sklearn.cluster import MiniBatchKMeans
from sklearn.metrics import silhouette_score

# calculating time
def time_it(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"Spend time:{time.time() - start} s")
        return result

    return wrapper


@time_it
def get_best_k(src):
    K_list = [i for i in range(2, 8)]
    scores = []
    for i in K_list:
        mbk = MiniBatchKMeans(n_clusters=i, random_state=0)
        scores.append(silhouette_score(src, mbk.fit_predict(src), sample_size=int(src.shape[0] / 128)))
    index = scores.index(max(scores))
    best_k = K_list[index]
    print(f'best_k:', best_k)
    return best_k


def get_main_Color(src):
    # to_HSV
    img = rgb2hsv(src)
    h, w, d = img.shape
    img = np.reshape(img, (h * w, d))
    k = get_best_k(img)
    bk = MiniBatchKMeans(n_clusters=k, random_state=0)
    bk.fit(img)
    result = bk.cluster_centers_
    # to_RGB
    maincolor = hsv2rgb(result) * 255
    return maincolor


def maincolor_show(maincolor):
    N = len(maincolor)
    img = np.zeros((300, 100 * N, 3), np.uint8)

    for i in range(N):
        img[:, 100 * i:100 * (i + 1)] = [maincolor[i]]
    plt.imshow(img)
    plt.axis('off')
    plt.show()


def main():
    src = imread("/home/shelgi/图片/1.jpeg")
    plt.imshow(src)
    plt.axis('off')
    plt.show()

    src = transform.rescale(src, [0.4, 0.4, 1])
    maincolor = get_main_Color(src)
    print(maincolor)
    # visualization
    maincolor_show(maincolor)


if __name__ == '__main__':
    main()

4. 结果

image-20220503020034332

image-20220503020250630

后续

这个功能我觉得还是很可玩的,如果实时性有一定保障的话,我准备有空写个简单的服务,传一张图片显示提取主色块图,这样又水一篇blog。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用 Python 的 Pillow 库来获取图片的主题色。具体步骤如下: 1. 安装 Pillow 库:在命令行中输入 `pip install Pillow` 即可。 2. 导入相关库:在 Python 脚本中导入以下库: ``` from PIL import Image import numpy as np from sklearn.cluster import KMeans ``` 3. 加载图片:使用 Pillow 库中的 Image 类加载图片,示例代码如下: ``` image = Image.open('image.jpg') ``` 4. 将图片转换为数组:使用 numpy 库将图片转换为数组,示例代码如下: ``` image_array = np.array(image) ``` 5. 将数组转换为二维数组:由于 KMeans 算法需要二维数组作为输入,因此需要将上一步得到的数组转换为二维数组。示例代码如下: ``` width, height = image.size image_array = image_array.reshape(width * height, 3) ``` 6. 使用 KMeans 算法提取主题色:使用 sklearn 库中的 KMeans 类,将上一步得到的二维数组作为输入,提取出主题色。示例代码如下: ``` kmeans = KMeans(n_clusters=1, random_state=0).fit(image_array) main_color = kmeans.cluster_centers_[0] ``` 7. 输出主题色:将得到的主题色输出即可。示例代码如下: ``` print(main_color) ``` 完整代码示例: ``` from PIL import Image import numpy as np from sklearn.cluster import KMeans image = Image.open('image.jpg') image_array = np.array(image) width, height = image.size image_array = image_array.reshape(width * height, 3) kmeans = KMeans(n_clusters=1, random_state=0).fit(image_array) main_color = kmeans.cluster_centers_[0] print(main_color) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shelgi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值