如何从饼图图片中获取数据?
我需要从一个简单的饼图图片中提取所有相关的数据,这些数据会不时变化。
这里有一个简单饼图的例子:
我该如何定义一个Python函数,来得到类似这样的结果:green=26
,grey=15
,red=4
?
提前感谢你的支持。
我对怎么做完全没有头绪。
1 个回答
2
如果你对图像处理不太熟悉,最快最简单的方法如下:
- 先制作一个你图像中颜色的样本
- 把你图像中的颜色重新映射到这个样本中的颜色
- 统计每种颜色的像素数量,然后计算出它们的百分比
为了快速起见,我会先教你用ImageMagick来做,之后我们再用Python来实现。
首先,制作你的颜色样本:
magick xc:green xc:salmon xc:lightgray xc:white +append swatch.png
下面是swatch.png
的放大版本:
你可以用颜色名称来选择颜色,或者如果你喜欢,也可以使用rgb()
三元组,比如:
magick xc:"rgb(108,254,32)" xc:"rgb(10,10,10)" ...
现在把你的饼图中的颜色重新映射到样本中,并且避免出现杂色:
magick pie.jpg +dither -remap swatch.png result.png
我之所以要映射到一个已知的颜色调色板,是因为你的JPEG图像经过压缩,里面有成千上万种颜色,且每种颜色都有细微的变化,而我们希望把这些颜色统一到饼图中的颜色。
现在检查直方图:
identify -verbose result.png | more
Image:
Filename: result.png
Permissions: rw-r--r--
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: PseudoClass
Geometry: 408x387+0+0
...
...
Colors: 4
Histogram:
52565: (0,128,0) #008000 green <--- HERE
31115: (211,211,211) #D3D3D3 LightGray <--- HERE
7168: (250,128,114) #FA8072 salmon <--- HERE
67048: (255,255,255) #FFFFFF white
Colormap entries: 4
Colormap:
0: (255,255,255,1) #FFFFFFFF white
1: (211,211,211,1) #D3D3D3FF LightGray
2: (0,128,0,1) #008000FF green
3: (250,128,114,1) #FA8072FF salmon
Rendering intent: Perceptual
...
...
现在你可以看到,在90,848个非白色像素中,有52,565个绿色像素(52565+31115+7168),占57%。还有31,115个浅灰色像素,占34%,以及7,168个鲑鱼色像素,占8%。
如果你想用Python做同样的事情,可以使用PIL/Pillow,像这样:
#!/usr/bin/env python3
# https://stackoverflow.com/a/78132079/2836621
import numpy as np
from PIL import Image
# Define the colours to which we want to quantize
colours = [255,255,255, 0,128,0, 211,211,211, 250,128,114]
# Create a 1x1 pixel palette image and push our colours into its palette
p = Image.new('P',(1,1))
p.putpalette(colours)
# Load the image we want to quantize
im = Image.open('pie.jpg')
# Do the work, disable dithering
N = int(len(colours)/3) # Colours have 3 RGB components
result = im.quantize(colors=N, dither=Image.Dither.NONE, palette=p)
# Print result
print(np.array(colours).reshape((-1,3)))
print(f'{result.getcolors()=}')
# Just pretty-printing...
hist = result.getcolors()
Ngreen = hist[1][0]
Ngrey = hist[2][0]
Nsalmon = hist[3][0]
Total = Ngreen + Ngrey + Nsalmon
print(f'Green: {Ngreen*100/Total:.1f}')
print(f'Grey: {Ngrey*100/Total:.1f}')
print(f'Salmon: {Nsalmon*100/Total:.1f}')
输出结果
[[255 255 255] <--- Colour 0 is white
[ 0 128 0] <--- Colour 1 is green
[211 211 211] <--- Colour 2 is light grey
[250 128 114]] <--- Colour 3 is salmon pink
result.getcolors()=[(67000, 0), (52578, 1), (31148, 2), (7170, 3)]
Green: 57.8
Grey: 34.3
Salmon: 7.9
第四行告诉你每种颜色的像素数量,比如67,000个白色像素,52,578个绿色像素,等等。