Python代码慢的皮肤检测

0 投票
2 回答
506 浏览
提问于 2025-04-17 15:30

这段代码把颜色空间转换成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

2 个回答

0

我建议你按照一个简单的步骤来优化你的代码:
1. 添加一些性能指标。你需要了解代码的哪个部分耗时最多。
2. 用更高效的函数来更新这些部分。
3. 测量性能的提升效果。

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倍。

看看向量化的强大之处吧!

撰写回答