我在这里找到了这个代码,但它只是计算黑色和红色,这只适用于黑色和红色图像。
from PIL import Image
im = Image.open('oh.png')
black = 0
red = 0
for pixel in im.getdata():
if pixel == (0, 0, 0, 255): # if your image is RGB (if RGBA, (0, 0, 0, 255) or so
black += 1
else:
red += 1
print('black=' + str(black)+', red='+str(red))
我如何能够检查不同的颜色而不是如此精确,例如黑色可以是(0,0,0)到(40,40,40)。
这可能太多了,请让我知道。 谢谢:))
答案 0 :(得分:1)
这是一种使用KDTree进行有效最近颜色查找的方法。请注意,虽然KDTrees可能非常先进,但使用它们实际上非常简单。
import numpy as np
from matplotlib import colors
from scipy.spatial import cKDTree as KDTree
from scipy.misc import face
REDUCED_COLOR_SPACE = True
# borrow a list of named colors from matplotlib
if REDUCED_COLOR_SPACE:
use_colors = {k: colors.cnames[k] for k in ['red', 'green', 'blue', 'black', 'yellow', 'purple']}
else:
use_colors = colors.cnames
# translate hexstring to RGB tuple
named_colors = {k: tuple(map(int, (v[1:3], v[3:5], v[5:7]), 3*(16,)))
for k, v in use_colors.items()}
ncol = len(named_colors)
if REDUCED_COLOR_SPACE:
ncol -= 1
no_match = named_colors.pop('purple')
else:
no_match = named_colors['purple']
# make an array containing the RGB values
color_tuples = list(named_colors.values())
color_tuples.append(no_match)
color_tuples = np.array(color_tuples)
color_names = list(named_colors)
color_names.append('no match')
# get example picture
img = face()
# build tree
tree = KDTree(color_tuples[:-1])
# tolerance for color match `inf` means use best match no matter how
# bad it may be
tolerance = np.inf
# find closest color in tree for each pixel in picture
dist, idx = tree.query(img, distance_upper_bound=tolerance)
# count and reattach names
counts = dict(zip(color_names, np.bincount(idx.ravel(), None, ncol+1)))
print(counts)
import pylab
pylab.imshow(img)
pylab.savefig('orig.png')
pylab.clf()
pylab.imshow(color_tuples[idx])
pylab.savefig('minimal.png' if REDUCED_COLOR_SPACE else 'reduced.png')
使用完整的matplotlib命名颜色空间输出:
{' aliceblue':315,' antiquewhite':0,' aqua':0,'海蓝宝石':0,&# 39; azure':0,'米色':27,' bisque':0,' black':88584,' blanchedalmond' :0,'蓝':0,' blueviolet':0,'布朗':0,' burlywood':76,&#39 ; cadetblue':0,'黄绿色':0,'巧克力':0,'珊瑚':0,' cornflowerblue': 0,' cornsilk':0,' crimson':0,' cyan':0,' darkblue':0,' darkcyan':0,' darkgoldenrod':0,' darkgray':0,' darkgreen':4148,' darkgrey':71985 ,' darkkhaki':32907,' darkmagenta':0,' darkolivegreen':90899,' darkorange':0,' darkorchid& #39;:0,'黑暗':0,' darksalmon':0,' darkseagreen':30171,' darkslateblue':134, ' darkslategray':108608,' darkslategrey':0,' darkturquoise':0,' darkviolet':0, ' deeppink':0,' deepskyblue':0,' dimgray':0,' dimgrey':108318,' dodgerblue&# 39;:0,'耐火砖':0,' floralwhite':0,' forestgreen':1,' fuchsia':0,& #39; gainboro':10438,' ghostwhite':736,' gold':0,' goldenrod':0,' grey&#39 ;:0,'绿色':0,' greenyellow':0,' grey':79835,' honeydew':0,&# 39; hotpink':0,' indianred':0,' indigo':0,'象牙':0,' khaki' :1056,'薰衣草':4650,' lavenderblush':46,' lawngreen':0,' lemonchiffon':0,&#39 ;浅蓝色':3,' lightcoral':0,' lightcyan':0,' lightgoldenrodyellow':0,' lightgray': 11905,' lightgreen':2323,' lightgrey':0,' lightpink':0,' lightsalmon':0,' lightseagreen':0,' lightskyblue':0,' lightslategray':0,' lightslategrey':31920 ,' lightsteelblue':3590,' lightyellow':0,' lime':0,' limegreen':0,'亚麻& #39;:46,' magenta':0,' maroon':0,' mediumaquamarine':0,' mediumblue':0, ' mediumorchid':0,' mediumpurple':15,' mediumseagreen':0,' mediumslateblue':0,' mediumspringgreen&# 39;:0,' mediumturquoise':0,' mediumvioletred':0,' midnightblue':54,' mintcream':0,& #39; misyrose':19,' moccasin':0,' navajowhite':0,'海军':0,' oldlace&#39 ;:0,'橄榄':0,' olivedrab':30828,'橙':0,' orangered':0,&# 39;兰花':0,' palegoldenrod':1499,' palegreen':285,' paleturquoise':0,' palevioletred' :0,' papayawhip':0,' peachpuff':0,'秘鲁':21,'粉红色':0,&#39 ;李子':0,'粉蓝':0,'紫':0,' rebeccapurple': 0,' red':0,' rosybrown':2831,' royalblue':0,' saddlebrown':0,'鲑鱼':0,' sandybrown':0,' seagreen':0,'贝壳':0,' sienna':5 ,'银':35951,' skyblue':0,' slateblue':0,' slategray':7836,' slategrey& #39;:0,' snow&#39 ;: 18,' springgreen':0,' steelblue':0,' tan':3925, ' teal':0,'蓟':10274,'番茄':0,'绿松石':0,'紫&# 39;:0,'小麦':21,'白色':3,'白色':834,'黄色':0,& #39; yellowgreen':9292,' no match':0}
仅使用基本颜色输出:
{' red':0,' green':403561,' blue':3262,' black':153782,&# 39;黄色':225827,'不匹配':0}
原始图片:
减少颜色版本:
基本颜色版本:
答案 1 :(得分:0)
如果它只做红色&黑色,你可以检查红色值是否小于或等于40.
if pixel[0] <= 40:
修改强>
colors = {}
for pixel in im.getdata():
r = pixel[0]
g = pixel[1]
b = pixel[2]
color = ''
brightness = ''
avg = (r + g + b) / 3
if avg < 40 then brightness = 'black'
else if avg < 80 then brightness = 'dark'
else if avg > 220 then brightness = 'white'
else if avg > 150 then brightness = 'light'
if avg / r > 0.9 then hue = 'red'
else if avg / r > 0.8 and avg / g > 0.6 then hue = 'orange'
else if avg / r > 0.7 and avg / g > 0.7 then hue = 'yellow'
else if avg / g > 0.8 and avg / r > 0.6 then hue = 'lime'
else if avg / g > 0.9 then hue = 'green'
else if avg / g > 0.7 and avg / b > 0.7 then hue = 'cyan'
else if avg / b > 0.9 then hue = 'blue'
else if avg / b > 0.8 and avg / r > 0.6 then hue = 'indigo'
else if avg / b > 0.7 and avg / r > 0.7 then hue = 'magenta'
color = brightness + hue
if color not in colors:
colors[color] = 1
else
colors[color] = colors[color] + 1
答案 2 :(得分:0)
您必须定义颜色桶。我建议使用hsv色彩空间。
from PIL import Image
import colorsys
im = Image.open('download.png')
NUM_BUCKETS = 6 # Just for example
colour_counts = [0] * NUM_BUCKETS
for pixel in im.getdata():
hue, saturation, value = colorsys.hsv_to_rgb(pixel[0], pixel[1], pixel[2])
hue_bucket = hue * NUM_BUCKETS // 255 # Using python3 to get an int
colour_counts[hue_bucket] += 1
colour_names = ["red", "yellow", "green", "cyan", "blue", "magenta"]
for name, count in [x for x in zip(colour_names, colour_counts)]:
print("{n} = {c}".format(n=name, c=count))
因此,这只是将颜色空间划分为6,但您可以使用任何您喜欢的数字(您只需要考虑所有这些数字的名称)。黑人和白人不能很好地工作,因为我们正在看色调。要捕捉黑白,也要使用&#34;值&#34;和&#34;饱和&#34;,即:
for pixel in im.getdata():
hue, saturation, value = colorsys.hsv_to_rgb(pixel[0], pixel[1], pixel[2])
if value < 32: # It's very dark
blacks += 1
elif saturation < 32 and value > 224: # it's basically white
whites += 1
else: # if it fails both of those, we can call it a colour
hue_bucket = hue * NUM_BUCKETS // 255 # Using python3 to get an int
colour_counts[hue_bucket] += 1
黑色的特点是低value
。白色具有高value
和低saturation
。低saturation
颜色为灰色。我通常认为hsv
比rgb
更容易理解。
答案 3 :(得分:0)
保罗的答案更优雅,但基本上我认为你可以通过定义一个函数来解决它,它可以在任何两种RGB颜色之间提供&#34;距离&#34; 像这样:
def distance(col1, col2):
(r1,g1,b1) = col1
(r2,g2,b2) = col2
return (r1 - r2)**2 + (g1 - g2) ** 2 + (b1 - b2) **2
现在,您需要做的只是(伪代码):
load your pre-existing reference colours into a list
load your new image
for each pixel in new image
# Calculate distance from this pixel to first one in reference list
mindist=distance(this pixel, first pixel in reference colours)
nearest=first pixel in reference colours
# Now see if any other colour in reference list is closer
for index=1 to number of colours in reference list
d=distance(this pixel, reference list[index])
if d < mindist:
mindist=d
nearest=reference list[index]
end
replace pixel with nearest one from reference list as determined above
end
我还在学习Python,所以我对上述内容的翻译可能不是最优的,但它确实有效!
#!/usr/local/bin/python3
from PIL import Image
import numpy as np
# Calculate distance in RGB space between two RGB pixels
def distance(col1, col2):
r1,g1,b1 = col1
r2,g2,b2 = col2
return (r1 - r2)**2 + (g1 - g2) ** 2 + (b1 - b2) **2
# All colours in the image will be forced to nearest one in this list
refColours=(
[[255, 0, 0], # red
[ 0, 255, 0], # green
[ 0, 0, 255], # blue
[255, 255, 0], # yellow
[ 0, 255, 255], # cyan
[255, 0, 255], # magenta
[ 0, 0, 0], # black
[255, 255, 255]]) # white
# Load your new image and note its width and height
im = Image.open('colorwheel.png')
imrgb = im.convert("RGB")
(w,h)=im.size[0],im.size[1]
# Make a buffer for our output pixels
px=np.zeros(w*h,dtype=np.uint8)
idx=0
for pixel in list(imrgb.getdata()):
# Calculate distance from this pixel to first one in reference list
mindist = distance([pixel[0],pixel[1],pixel[2]],refColours[0])
nearest = 0
# Now see if any other colour in reference list is closer
for index in range(1,len(refColours)):
d=distance([pixel[0],pixel[1],pixel[2]],refColours[index])
if d < mindist:
mindist=d
nearest=index
# Set output pixel to nearest
px[idx]=nearest
idx += 1
# Reshape our output pixels to match input image
px=px.reshape(w,h)
# Make output image from our pixels
outimg=Image.fromarray(px).convert('P')
# Put our palette of favourite colours into the output image
palette=[item for sublist in refColours for item in sublist]
outimg.putpalette(palette)
outimg.save("result.png")
所以,我从colorwheel.png
开始:
并以此结束:
当然,像我在评论中建议的那样,更简单的解决方案是使用像 ImageMagick 这样的工具将新图像中的颜色重新映射到您的&#34;参考&#34;中的颜色。图像,你在命令行上这样做:
convert colorwheel.png +dither -remap colormap.png result.png
如my other answer here所示。所以在Python中,您可以使用system()
调用或使用subprocess
模块执行此操作:
cmd="https://stackoverflow.com/a/38328879/2836621"
system(cmd)