首页 > 其他分享 >通过K-means提取图片主颜色

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

时间:2024-05-25 20:31:40浏览次数:18  
标签:提取 颜色 means image hist path folder data

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

文章目录


前言

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


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

一、基本流程是什么?

代码基本功能是做到识别一张图片的颜色,通过设定好的聚类数,将颜色聚类,识别结果输入到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函数相关的颜色聚类使用,本文仅仅简单分享了相关代码,如有不足还望批评指正。

标签:提取,颜色,means,image,hist,path,folder,data
From: https://blog.csdn.net/diyuxiaoguaishou/article/details/139198144

相关文章

  • ffmpeg提取aac数据
    方法1:通过命令提取ffmpeg-iinput.mp4-vn-acodecaac../output.aac方法2:通过代码提取流程图  main.c#include"libavutil/log.h"#include"libavformat/avformat.h"#include"libavcodec/avcodec.h"intmain(intargc,char**argv){......
  • Kmeans聚类流程
    1.turtlesIntroductionInthisreport,wewillanalyzeaproblemrelatedtoturtlepopulationsonasmallislandwithtwobeaches:WestBeachandEastBeach.ThegoalistodeterminetheprobabilityofbeingonEastBeachgiventhataLoggerheadTurtlei......
  • 【源码翻译之交互式对象包 AIS-AIS_ColoredShape.hxx文件 多颜色交互式对象
    类AIS_ColoredShape形状的呈现具有可自定义的子形状属性。此类可以将topods的子拓扑分别设置不同的颜色然后作为一个整体显示成员类型定义文档◆DataMapOfDrawerCompdtypedefNCollection_IndexedDataMap<Handle<AIS_ColoredDrawer>,TopoDS_Compound,TColStd_MapT......
  • ArcPy按掩膜提取ExtractByMask的边界问题
    问题描述按掩膜提取是GIS数据处理中常用的功能之一。按照官方的示例,使用ArcPy的ExtractByMask方法可实现提取,代码如下:1importarcpy2fromarcpyimportenv3fromarcpy.saimport*45env.workspace="C:/sapyexamples/data"6outExtractByMask=Extrac......
  • 每日一练——颜色分类(快慢指针排序)
    目录题目代码分析案例模拟重难点分析自检复习 题目75.颜色分类-力扣(LeetCode)代码//交换函数,交换指针a和指针b指向的整数voidswap(int*a,int*b){intt=*a;*a=*b;*b=t;}voidsortColors(int*nums,intnumsSize){//双指针......
  • R语言聚类、文本挖掘分析虚假电商评论数据:K-Means(K-均值)、层次聚类、词云可视化|附
    全文链接:http://tecdat.cn/?p=32540原文出处:拓端数据部落公众号聚类分析是一种常见的数据挖掘方法,已经广泛地应用在模式识别、图像处理分析、地理研究以及市场需求分析。本文主要研究聚类分析算法K-means在电商评论数据中的应用,挖掘出虚假的评论数据。本文主要帮助客户研究聚类......
  • 【瞎写】熊是什么颜色的?
    网上流传着一个这样的地理题:一个探险家在野外扎了顶帐篷,之后他往南走了10公里,往西走了10公里,再往北走了10公里后,发现有一头熊在撕扯他的帐篷。问这头熊是什么颜色的?答案大家都能猜到,探险家的帐篷在北极,因此这头熊是白色。这是因为,一般情况下,如果走的路径不是一个闭合的路线,是不......
  • antd 的 ProTable 通过rowClassName 设置行的字体颜色时,固定列fixed不生效的问题
    1、其他列是已经生效了,但是固定列是没有生效的 constrowClassName=(record)=>{returntableTreeSearchKey.includes(record.key)?'selected-row':'';};<ProTable ...... rowClassName={rowClassName}> 2、分析原因:固定列的子组件也有color属性,覆盖......
  • Java实现抓取在线视频并提取视频语音为文本
     最近在做大模型相关的项目,其中有个模块需要提取在线视频语音为文本并输出给用户。作为一个纯后端Jave工程师,搞这个确实是初次尝试。二、调研基于上述功能模块,主要有三大任务:1、提取网页中的视频2、视频转语音3、语音转文本。首先是第一项:尝试了jsoup,webmagic等工......
  • 填涂颜色
    传送锚点:https://www.luogu.com.cn/problem/P1162血色先锋队题目描述由数字\(0\)组成的方阵中,有一任意形状的由数字\(1\)构成的闭合圈。现要求把闭合圈内的所有空间都填写成\(2\)。例如:\(6\times6\)的方阵(\(n=6\)),涂色前和涂色后的方阵如下:如果从某个\(0\)出发,只向上下......