急!紧急!优化Python分析图片颜色至Excel报异常的问题

文摘   科技   2024-11-08 18:34   北京  

ISEE小语


“我们常常看到的风景是:一个人总在仰望和羡慕着别人的幸福,一回头,却发现,自己正被别人仰望和羡慕着。”

——马德


首先,这里非常感谢@可乐拉环同学的反馈^^

在06月09日的分享的【惊艳了,Python可以分析一张图片中包含有几种颜色?(附源码)】

惊艳了,Python可以分析一张图片中包含有几种颜色?(附源码)

ISEE小栈,公众号:ISEE小栈惊艳了,Python可以分析一张图片中包含有几种颜色?(附源码)

文章中,无法使用Microsoft Office Excel打开其中的Excel文件。

看到这个问题,小栈先说一下抱歉~~

第一是 一直没有发现

第二是 当初实例是使用WPS打开的,在分享中没说明。

没想到Microsoft Office Excel上会有问题!

从提示信息上看,这个问题应该是格式/样式不兼容的引起的!

小栈找到原文,事情并没有想象那么简单,发现不单单是Excel打不开的问题,即使是原来使用WPS打开的Excel文件,里面“颜色” 列数据也是不全的。


于是,小栈分别对WPS和Microsoft Office Excel测试验证

发现在WPS中,所有数据都在一个Excel文档中,“颜色” 列只显示在64000


而在Microsoft Office Excel中“颜色” 列显示在65430行,只要超过就会报以上出现的问题。


总结下来就是两个表格软件,打开同一个Excel文件,两种显示结果:

软件“颜色”列显示行数
WPS Office64000
Microsoft Office Excel65430

*个人验证结果,非官方数据

为什么会这样???我也想知道⊙﹏⊙

那么,现在要解决的问题是 既能让 “颜色” 列都显示,又可以在Microsoft Office Excel软件正常打开。

目前没有特别完美的办法将所有颜色分析数据放在一个Excel文档中,小栈目前解决的方式是 按照显示的行数,切分多个文档保存数据。



环境:

Pycharm

Python 3.9.16



安装:

本次我们用到了两个三方包协助,一个是“openpyxl”,另一个是“pillow”。

用以下方式可自行安装:

pip install pillow==10.3.0pip install openpyxl==3.1.3




先看实际效果


准备一张图片

首先,准备一张所要分析的图片,以下是实例中所用到的:


实现原理

主要实现步骤:

  • 读取图片:确保图片是在RGB模式下计数每种颜色的像素数

  • 转换颜色编码:将RGB颜色转换为颜色编号。

  • 保存Excel:将颜色编码及呈现的颜色,一一对应保存到Excel中。这里我们为了兼容WPS显示的行数,我们按每64000行保存至一文档中进行切分。


读取图片

首先,将准备的图片命名为image.png,放在当前文件夹下

然后,加载图片、读取所有像素、去重相同颜色,这个时候会打印出图片中所有的颜色和它们各自的计数,包括非常微小的变化,因为它是基于像素级的颜色读取。

from PIL import Imagefrom collections import Counter
# 加载图片image_msg = Image.open('image.png')# 将图片转换为RGB模式image_msg = image_msg.convert('RGB')# 获取图片中的所有像素all_pixels = list(image_msg.getdata())# 计算每种颜色的出现次数color_counts = Counter(all_pixels)# 去重后的颜色列表转换为集合RGB_colors_ = set(color_counts.keys())
# 打印去重后的颜色print(f'所有的颜色值: {RGB_colors_}')

(左右滑动查看完整代码)

结果:

其实很多数字,其实也看不明白,不用担心,这个只是颜色值。

接下来就是需要将这些颜色值转换为颜色编号。

转换颜值编码

我们将以上的颜色值转换为颜色编码

在示例中为了更清晰地看出是什么颜色,我们将少部分颜色值进行转换。

换个说法就是将转换RGB到十六进制颜色代码。

# -*- coding: utf-8 -*-# 截取6个RGB颜色值集合RGB_colors = {(159, 46, 163), (136, 138, 228), (102, 26, 38), (194, 88, 201), (216, 48, 44), (50, 4, 88)}
hex_colors = []for rgb_color in RGB_colors: hex_color = '#{0:02x}{1:02x}{2:02x}'.format(*rgb_color) hex_colors.append(hex_color)# 打印十六进制颜色代码print("打印十六进制颜色代码:", hex_colors)

(左右滑动查看完整代码)

打印十六进制颜色代码结果:

接下来我们用取色工具校验两个颜色,看一下效果:

颜色值:(159, 46, 163)

颜色代码:'#9f2ea3'


颜色值:(136, 138, 228)

颜色代码:'#888ae4'

OK,剩下的就不一一贴出来了,有兴趣的可自行试。

保存Excel

我们以上输出的颜色值和颜色代码为例,结果输出保存到Excel中

from openpyxl import Workbookfrom openpyxl.styles import PatternFill
# 输出的RGB颜色集合RGB_colors = [{'(159, 46, 163)': '#9f2ea3'}, {'(136, 138, 228)': '#888ae4'}, {'(102, 26, 38)': '#661a26'}, {'(194, 88, 201)': '#c258c9'}, {'(216, 48, 44)': '#d8302c'}, {'(50, 4, 88)': '#320458'}]

# 创建一个新的Excel工作簿wb = Workbook()ws = wb.active
# 设置表头ws.cell(row=1, column=1).value = "颜色值"ws.cell(row=1, column=2).value = "颜色编号"ws.cell(row=1, column=3).value = "颜色"
for index, rgb_color in enumerate(RGB_colors, start=2): for key, value in rgb_color.items(): hex_color = 'FF' + value.replace('#', '') # 第一列显示颜色值 ws.cell(row=index, column=1).value = key # 在Excel中设置单元格颜色,确保使用aRGB格式 fill = PatternFill(start_color=hex_color, end_color=hex_color, fill_type="solid") ws.cell(row=index, column=2).value = hex_color ws.cell(row=index, column=3).fill = fill
# 保存Excel文件wb.save('图片颜色分析统计.xlsx')

(左右滑动查看完整代码)

注:其中有一个特殊的处理,就是在保存到Excel中时,openpyxl三方库颜色需要以 "FF" 开头的十六进制格式。其中在RGB颜色代码前面加上了 'FF',这表示颜色是完全不透明的。

Excel中效果:


完整实例

按照WPS显示 64000 行进行切分,结果输出保存到Excel中

# -*- coding: utf-8 -*-from PIL import Imagefrom collections import Counterfrom openpyxl.styles import PatternFillfrom openpyxl.workbook import Workbook
# 加载图片image_msg = Image.open('image.png')
# 将图片转换为RGB模式image_msg = image_msg.convert('RGB')
# 获取图片中的所有像素all_pixels = list(image_msg.getdata())
# 计算每种颜色的出现次数color_counts = Counter(all_pixels)
# 去重后的颜色列表RGB_colors_ = list(set(color_counts.keys()))
# 转换RGB到十六进制颜色代码RGB_colors = []for rgb_color in RGB_colors_: hex_color = dict() hex_color[str(rgb_color)] = '{:02X}{:02X}{:02X}'.format(*rgb_color) RGB_colors.append(hex_color)
# 按WPS显示 64000 行进行切分rgb_size = 63999# 切分块写入不同的Excel文件for rgb_index, start in enumerate(range(0, len(RGB_colors), rgb_size), start=1): # 创建一个新的Excel工作簿 wb = Workbook() ws = wb.active
# 设置表头 ws.cell(row=1, column=1).value = "颜色值" ws.cell(row=1, column=2).value = "颜色编号" ws.cell(row=1, column=3).value = "颜色"
# 获取当前切分的块 chunk = RGB_colors[start:start + rgb_size]
for row_index, rgb_color in enumerate(chunk, start=2): for key, value in rgb_color.items(): hex_color = 'FF' + value # 第一列显示颜色值 ws.cell(row=row_index, column=1).value = key # 在Excel中设置单元格颜色,确保使用aRGB格式 fill = PatternFill(start_color=hex_color, end_color=hex_color, fill_type="solid") ws.cell(row=row_index, column=2).value = hex_color ws.cell(row=row_index, column=3).fill = fill
# 生成Excel文件名 file_name = f'图片颜色分析统计_{rgb_index}.xlsx'
# 保存Excel文件 wb.save(file_name)
# 输出提示    print(f'{file_name} 文档保存成功!!')

(左右滑动查看完整代码)

结果:

分别通过WPS和Microsoft Office Excel 打开,均成功!


总结

目前这个解决方式,有一个小问题,就是所有的分析数据不在一个Excel文档中,如使用代码强行合到一个文档,就仍会出现上面的问题。

做数据分析的时候,需要手动操作切分的Excel合到一起。

如果同学有更好的方案,欢迎留言,大家一起学习探索。

如果有发现一些Bug,同样欢迎留言,小栈会及时解决。

源码已重新整理:



有兴趣的朋友点个“”和“在看”,谢谢支持~!

后台回复“image_color”即可获取!

     

文章就分享到这儿,喜欢就点个吧!



推荐阅读  点击标题可跳转

ISEE小栈
没有花里胡哨,简单才是王道。
 最新文章