python元素矢量化的布尔操作根据其颜色对图像像素进行分类



我有一个我使用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倍,并且需要更少的内存(

最新更新