0

此代码将颜色空间更改为 LAB,并使用阈值查找图像的皮肤区域。但这太慢了。我不知道如何使它更快?

from colormath.color_objects import *

def skinDetection(img, treshold=80, color=[255,20,147]):

    print img.shape
    res=img.copy()
    for x in range(img.shape[0]):
        for y in range(img.shape[1]):
            RGBimg=RGBColor(img[x,y,0],img[x,y,1],img[x,y,2])
            LABimg=RGBimg.convert_to('lab', debug=False)
            if (LABimg.lab_l > treshold):
                res[x,y,:]=color
            else: 
                res[x,y,:]=img[x,y,:]

    return res
4

2 回答 2

4

Python 中的嵌套循环总是很慢。您遍历每个像素,因此需要很多时间。

执行向量化操作总是更快,即对整个数组执行操作并让底层 C 例程执行循环。

我不是很colormath清楚,因此我无法为这个库提供相应的代码(也不知道它是否存在),但是对于scikit-image,我可以:

def mask2(rgb, threshold=80, color=[255,20,147]):
    res = rgb.copy()
    lab = skimage.color.rgb2lab(rgb)
    mask = lab[:,:,0] > threshold
    res[mask] = np.array(color).reshape(1,-1).repeat(mask.sum(),axis=0)
    return res

我将整个图像转换为 LAB 空间,然后确定一个掩码(其中 L 高于阈值),然后将这些像素设置为新颜色。此方法产生的结果与您的方法略有不同(可能是由于不同的转换实现),但它可能满足您的需求。

下面是一个完整的脚本,包括您的方法 ( mask1) 和性能测量。

from binascii import unhexlify
import zlib
from cStringIO import StringIO
import skimage.io, skimage.color
from colormath.color_objects import RGBColor
import numpy as np


def mask1(img, treshold=80, color=[255,20,147]):
    res=img.copy()
    for x in range(img.shape[0]):
        for y in range(img.shape[1]):
            RGBimg=RGBColor(img[x,y,0],img[x,y,1],img[x,y,2])
            LABimg=RGBimg.convert_to('lab', debug=False)
            if (LABimg.lab_l > treshold):
                res[x,y,:]=color
            else: 
                res[x,y,:]=img[x,y,:]
    return res

def mask2(rgb, threshold=80, color=[255,20,147]):
    res = rgb.copy()
    lab = skimage.color.rgb2lab(rgb)
    mask = lab[:,:,0] > threshold
    res[mask] = np.array(color).reshape(1,-1).repeat(mask.sum(),axis=0)
    return res

sdata = "789C9D953D56C52010856363696D49E90AAC73ECDD4396C25228B210CE711B2CC2CAC622CECC9D0C0321313A27E411123EEEFCC07B7BFF7A9CC45EA9BD507BD6F620F769CAF4FEE3096DB76DDACEAEE9865D4CF79C6DAB34F46D441F7F23F88F6F728E6AD794724EDD5CBB9B790EF53FBF1595D9524C517E93CDEA3A433D984E83440327B318B633BF867A4C12734A5654CE26F24F29AB28704A067685363C665B0582D30ADF0F39A2717F3979C9412A6108A1D731C6992C04BD96252ECB9A2AC4A60F2B07904AA8166C84B51545D172C3C8D02B4CA3D51D841F7584B5CD2E17E2698A5DDE991302AD6240189666558242122D68F1C0F19F99475104D0F7C6216D5A6665AFAED62F8A27730A57E3BC4858669D25716B387BA04E39B41059BCC7E99CEAF4B05F971C75AAB0181AE938111CA9DB9A71C9B5443EA000D4231183A4F8ECEF79E7E5B40E2DEF647BDEA9AB6250EA59F70B6AC90E9FAABFB7D040E43C010107D4F1086A4ADA6D8DA66C8AEDD9C10E3514196A0F060220B59825C843883F5D71A67586809FEDF17FFCD75C4CFC012B43550B"
fh = StringIO(zlib.decompress(unhexlify(sdata)))
rgb = skimage.io.imread(fh)

res1 = mask1(rgb)
res2 = mask2(rgb)

import timeit
t1 = timeit.timeit("mask1(rgb)", setup="from __main__ import rgb, mask1", number=100)
t2 = timeit.timeit("mask2(rgb)", setup="from __main__ import rgb, mask2", number=100)

print t1, t2, t1/t2

我在这段代码中嵌入了一张图片,部分代码只是为了解码。

这个脚本的输出是

4.43572092984 0.0531735152348 83.4197421453

所以我的方法是你的80倍。对于更大的图像(这个只有 24 x 24 像素),差异甚至更大,快 120 倍。

看看矢量化的力量!

于 2013-02-11T16:10:08.813 回答
0

我建议遵循一个简单的过程来优化您的代码:
1. 添加一些性能指标。您必须了解大部分时间都在使用代码的哪一部分。
2. 通过更多性能更新这些功能
3. 衡量性能改进

于 2013-02-11T15:58:53.987 回答