通过K-means提取图片主颜色

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

想着提取图片当中的颜色,然后查阅了相关代码,吸取了其他大佬们的经验,鼓捣出来的东西,分享出来。


提示:以下是本篇文章正文内容,下面案例可供参考

一、基本流程是什么?

代码基本功能是做到识别一张图片的颜色,通过设定好的聚类数,将颜色聚类,识别结果输入到Excel中,并且可以生成相关图像在文件夹中,更利于可视化。图片样例如下:
在这里插入图片描述

二、使用步骤

1.引入库

代码如下:

from pydantic import ValidationError
from sklearn.cluster import KMeans
import cv2
import matplotlib.pyplot as plt
import numpy as np
from time import sleep
import os
import pandas as pd
from operator import itemgetter

2.从图像中提取主要颜色,并生成十六进制颜色列表

代码如下:

def ExtractColors(img, clust=3):
    if img.lower().endswith(('.png', '.jpg', '.jpeg')):

        image = cv2.imread(img)

        height, width = image.shape[:2]

        if height > 1000 and width > 1000:

            # 调整图像大小的百分比
            scale_percent = 30

            # 计算原始尺寸的50%
            width = int(image.shape[1] * scale_percent / 100)
            height = int(image.shape[0] * scale_percent / 100)
            dsize = (width, height)

            # 调整图像大小
            image = cv2.resize(image, dsize)

        else:
            pass

        # 加载图像并将其从BGR转换为RGB,以便
        # 我们可以用matplotlib来显示它

        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        # 将图像重塑为像素列表
        image = image.reshape((image.shape[0] * image.shape[1], 3))
        # 对像素强度进行聚类
        print("please wait,This may take a moment :)")
        ExtractColors.clt = KMeans(n_clusters=clust)
        ExtractColors.clt.fit(image)

        colors = ExtractColors.clt.cluster_centers_
        colors = colors.astype(int)
        # 将numpy数组转换为列表
        rgblist = np.array(colors).tolist()
        hexlist = ['#%02x%02x%02x' % tuple(i) for i in rgblist]

        for i in range(21):
            print("\r[%-21s] %d%%" % ('=' * i, 5 * i), end='')
            sleep(0.25)

        print("")

        return (hexlist)

    else:
        raise ValidationError("Only .jpg and .png images can be accepted")

3.生成颜色簇的直方图

def centroid_histogram():
    # 获取不同聚类的数量并创建直方图
    # 基于分配给每个聚类的像素数
    numLabels = np.arange(0, len(np.unique(ExtractColors.clt.labels_)) + 1)
    (hist, _) = np.histogram(ExtractColors.clt.labels_, bins=numLabels)
    # 归一化直方图,使其总和为1
    hist = hist.astype("float")
    hist /= hist.sum()
    # 返回直方图
    return hist

这里生成的意义是以便进一步的颜色分析和图表绘制

4.生成颜色分布的饼图,并保存或显示

def ClusterAnalysis(hexlist, histogram, save_path=None):
    if hexlist is None:
        raise TypeError("Hex Color List Not Found")
    else:
        # 过滤掉占比小于0.1%的颜色
        filtered_data = [(color, percent) for color, percent in zip(hexlist, histogram) if percent >= 0.01]
        if not filtered_data:
            raise ValueError("No colors with more than 0.1% presence found.")

        # 重新分配颜色列表和直方图数据
        filtered_hexlist, filtered_hist = zip(*filtered_data)

        fig, ax = plt.subplots(figsize=(12, 6), subplot_kw=dict(aspect="equal"), facecolor='#FAFAFA')
        data = filtered_hist
        color = filtered_hexlist

        wedges, texts, autopcts = ax.pie(data, colors=color, autopct=lambda pct: "{:.1f}%".format(pct) if pct > 5 else '',
                                         pctdistance=0.85, wedgeprops=dict(width=0.3, linewidth=3, edgecolor='white'), startangle=-40)

        plt.setp(autopcts, **{'color': 'black', 'weight': 'bold', 'fontsize': 6})
        bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
        kw = dict(arrowprops=dict(arrowstyle="-"), bbox=bbox_props, zorder=0, va="center")

        for i, p in enumerate(wedges):
            ang = (p.theta2 - p.theta1) / 2. + p.theta1
            y = np.sin(np.deg2rad(ang))
            x = np.cos(np.deg2rad(ang))
            horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
            connectionstyle = "angle,angleA=0,angleB={}".format(ang)
            kw["arrowprops"].update({"connectionstyle": connectionstyle})
            # Only annotate larger wedges with labels
            if data[i] > 5:
                ax.annotate(f"{filtered_hexlist[i]}: {data[i] * 100:.1f}%", xy=(x, y), xytext=(1.5*np.sign(x), 1.4*y),
                            horizontalalignment=horizontalalignment, **kw)

        # Create a legend for smaller wedges
        ax.legend(wedges, [f"{h}: {d*100:.1f}%" for h, d in zip(filtered_hexlist, data)],
                  title="Color Legend", loc="center left", bbox_to_anchor=(1, 0, 0.5, 1))

        if save_path is not None:
            plt.savefig(save_path, bbox_inches='tight')
            plt.close()
        else:
            plt.show()

5.将颜色数据保存到Excel文件中

def save_color_data_to_excel(image_name, hex_list, hist, output_excel_path):
    # 准备数据并按百分比从大到小排序
    color_data = sorted([(hex_code, f"{percentage * 100:.2f}%") for hex_code, percentage in zip(hex_list, hist) if percentage >= 0.01], key=itemgetter(1), reverse=True)

    # 将排序后的数据转换为pandas DataFrame
    data_dict = {"Image": image_name}
    for i, (color, percentage) in enumerate(color_data):
        data_dict[f"Color_{i + 1}"] = color
        data_dict[f"Percentage_{i + 1}"] = percentage

    df = pd.DataFrame([data_dict])

    # 检查Excel文件是否存在,根据情况选择写入模式
    if os.path.exists(output_excel_path):
        with pd.ExcelWriter(output_excel_path, mode='a', engine='openpyxl', if_sheet_exists='overlay') as writer:
            # 如果Sheet1已存在,追加数据
            if 'Sheet1' in writer.book.sheetnames:
                df.to_excel(writer, index=False, header=False, startrow=writer.sheets['Sheet1'].max_row)
            else:
                # 如果Sheet1不存在,创建并添加列名
                df.to_excel(writer, index=False, header=True)
    else:
        # 创建一个新的Excel文件并添加数据
        with pd.ExcelWriter(output_excel_path, mode='w', engine='openpyxl') as writer:
            df.to_excel(writer, index=False)

所生成的颜色比例从大到小进行排序到Excel中。最后生成的结果如下图所示:
在这里插入图片描述
如果图片生成的颜色聚类少于设定的簇数,则会有几种显示几种

6.批量处理文件夹中的图像,提取颜色,生成图表,并保存数据到Excel

def analyze_images_in_folder(input_folder, output_folder, num_clusters, output_excel_path):
    os.makedirs(output_folder, exist_ok=True)

    for filename in os.listdir(input_folder):
        if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            img_path = os.path.join(input_folder, filename)
            hex_list = ExtractColors(img_path, num_clusters)
            hist = centroid_histogram()  # 确保我们生成了颜色直方图
            save_path = os.path.join(output_folder, os.path.splitext(filename)[0] + '_color_chart.png')
            ClusterAnalysis(hex_list, hist, save_path)  # 现在我们传递了hist作为参数
            save_color_data_to_excel(filename, hex_list, hist, output_excel_path)  # 保存颜色数据到Excel

if __name__ == "__main__":
    input_folder = 'xxxxx'
    output_folder = 'xxxxx'
    num_clusters = 10
    output_excel_path = 'xxxxx'

    analyze_images_in_folder(input_folder, output_folder, num_clusters, output_excel_path)

7.main主程序

设置输入文件夹、输出文件夹、颜色簇数量(我这里设定的是10种)和输出Excel文件路径,并调用analyze_images_in_folder函数处理图像。结果如下图所示:

在这里插入图片描述


总结

以上就是K-means函数相关的颜色聚类使用,本文仅仅简单分享了相关代码,如有不足还望批评指正。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于SSM的图片识别颜色系统是一种利用SSM框架(Spring+SpringMVC+MyBatis)开发的系统,用于对图片进行颜色识别和分析的应用。下面是该系统的要功能和实现方式: 1. 图片上传:用户可以通过系统界面将图片上传到系统中。 2. 图片处理:系统会对上传的图片进行处理,提取图片中的颜色信息。 3. 颜色识别:系统会对提取出的颜色信息进行识别,判断图片中包含的颜色。 4. 颜色分析:系统会对识别出的颜色进行分析,统计每种颜色图片中的占比。 5. 结果展示:系统将识别和分析的结果展示给用户,以图表或文字形式呈现。 实现该系统可以按照以下步骤进行: 1. 搭建SSM框架:使用Spring框架管理系统的各个模块,使用SpringMVC框架处理用户请求,使用MyBatis框架与数据库进行交互。 2. 图片上传:在系统界面中添加上传按钮,使用SpringMVC接收用户上传的图片,并保存到服务器指定的目录。 3. 图片处理:使用Java图像处理库(如OpenCV)对上传的图片进行处理,提取颜色信息。 4. 颜色识别:根据提取出的颜色信息,使用颜色识别算法(如K-means聚类算法)对图片中的颜色进行识别。 5. 颜色分析:统计识别出的颜色图片中的占比,可以使用统计算法(如直方图统计)进行分析。 6. 结果展示:将识别和分析的结果以图表或文字形式展示给用户,可以使用前端框架(如Bootstrap)进行页面设计和展示。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值