我有一个我使用pil
将其加载到2D数组中的RGB图像img = Image.open(path)
imgData = numpy.array(img)
我需要有效地将其转换为2D阵列的RGB元组(从某种意义上说,3D阵列(与包含每个像素的粗糙"分类"相同的大小 - "红色","红色","绿色","白色","白色"或"其他"在每个索引上,基于它们内部的"颜色区域"。这是出于图像识别的目的。
我当前的实现使用元素进行循环,但非常慢(8MP图像需要1多分钟(:
for i in range(cols): # for every col
for j in range(rows): # for every row
r,g,b = imgData[i,j]
if b > 220: # white
n = 3
elif r > 230: # red
n = 2
else: # green
n = 1
mapData[i,j] = n
(我意识到此处的IF语句的顺序会影响分类的优先级 - 尽管我更希望专门定义颜色空间,但这不是现在的主要问题(
我正在运行python 3.6.4,并乐于使用numpy。进行了大量研究后,似乎有很多更快,更" Pythonic"和矢量化的方法来做到这一点,但我无法进行任何工作。
任何帮助将不胜感激谢谢!
使用 np.where
使它很快。
mapData = np.where(imgData[:,:,2] > 220, 3, np.where(imgData[:,:,0]>230, 2, 1))
,但是将其应用于图片时,唯一的结果。我是否错过任何东西,或者应该以不同的方式制作案件?
可以像这样捕获您的算法:
r, g, b = imgData[...,0], imgData[...,1], imgData[...,2]
mapData = np.ones_like(r, dtype=int)
mapData[r > 230] = 2
mapData[b > 220] = 3
请注意分配这些数字的操作顺序。
颜色分类通常是通过将RGB颜色视为向量来完成的。将每个范围归一化,然后找到与目标颜色的距离。
例如,smartcrop.js中的皮肤检测器这样(使用pyvips(:
def pythag(im):
return sum([x ** 2 for x in im]) ** 0.5
skin = [0.78, 0.57, 0.44]
score = 1 - pythag(img / pythag(img) - skin)
现在score
是一个浮点图像,其值为0-1,对于像素最有可能是皮肤色的1是1。请注意,它忽略了亮度:您需要另一条规则才能砍掉非常黑暗的区域。
在您的情况下,我想您需要一个目标向量的数组集,然后计算所有颜色概率,最后用得分最高的向量为输出像素标记输出像素。类似:
import sys
import pyvips
def pythag(im):
return sum([x ** 2 for x in im]) ** 0.5
def classify(img, target):
return 1 - pythag(img / pythag(img) - target)
# find [index, max] of an array of pyvips images
def argmax(ar):
if len(ar) == 1:
return [0, ar[0]]
else:
index, mx = argmax(ar[:-1])
return [(ar[-1] > mx).ifthenelse(len(ar) - 1, index),
(ar[-1] > mx).ifthenelse(ar[-1], mx)]
skin = [0.78, 0.57, 0.44]
red = [1, 0, 0]
green = [0, 1, 0]
targets = [red, green, skin]
# we're not doing any coordinate transformations, so we can stream the image
img = pyvips.Image.new_from_file(sys.argv[1], access="sequential")
scores = [classify(img, x) for x in targets]
index, mx = argmax(scores)
index.write_to_file(sys.argv[2])
(插头:Pyvips通常比Numpy快2倍或3倍,并且需要更少的内存(