python - Python矢量化图像处理中的嵌套for循环
问题描述
我正在尝试检测皮肤。我找到了一个很好且简单的公式来从 RGB 图片中检测皮肤。唯一的问题是,for 循环非常慢,我需要加速这个过程。我已经做了一些研究,矢量化可以加快我的 for 循环,但我不知道如何在我的情况下使用它。
这是我的函数的代码:
函数接收 1 个类型的参数:numpy 数组,形状为 (144x256x3),dtype=np.uint8
函数返回第一个检测到的肤色像素的坐标(如 numpy.array [height,width]);第一张皮肤检测到的图片的皮肤检测像素数(int)和计算角度(从左到右)(浮点数)
# picture = npumpy array, with 144x256x3 shape, dtype=np.uint8
def filter_image(picture):
r = 0.0
g = 0.0
b = 0.0
# In first_point I save first occurrence of skin colored pixel, so I can track person movement
first_point = np.array([-1,-1])
# counter is used to count how many skin colored pixels are in an image (to determine distance to target, because LIDAR isn't working)
counter = 0
# angle of first pixel with skin color (from left to right, calculated with Horizontal FOV)
angle = 0.0
H = picture.shape[0]
W = picture.shape[1]
# loop through each pixel
for i in range(H):
for j in range(W):
# if all RGB are 0(black), we take with next pixel
if(int(picture[i,j][0]+picture[i,j][1]+picture[i,j][2])) == 0:
continue
#else we calculate r,g,b used for skin recognition
else:
r = picture[i,j][0]/(int(picture[i,j][0]+picture[i,j][1]+picture[i,j][2]))
g = picture[i,j][1]/(int(picture[i,j][0]+picture[i,j][1]+picture[i,j][2]))
b = picture[i,j][2]/(int(picture[i,j][0]+picture[i,j][1]+picture[i,j][2]))
# if one of r,g,b calculations are 0, we take next pixel
if(g == 0 or r == 0 or b == 0):
continue
# if True, pixel is skin colored
elif(r/g > 1.185 and (((r * b) / math.pow(r + b + g,2)) > 0.107) and ((r * g) / math.pow(r + b + g,2)) > 0.112):
# if this is the first point with skin colors in the whole image, we save i,j coordinate
if(first_point[0] == -1):
# save first skin color occurrence
first_point[0] = i
first_point[1] = j
# here angle is calculated, with width skin pixel coordinate, Hor. FOV of camera and constant
angle = (j+1)*91 *0.00390626
# whenever we detect skin colored pixel, we increment the counter value
counter += 1
continue
# funtion returns coordinates of first skin colored pixel, counter of skin colored pixels and calculated angle(from left to right based on j coordinate of first pixel with skin color)
return first_point,counter, angle
功能运行良好,唯一的问题是它的速度!
感谢您的帮助!
解决方案
您可以跳过所有循环并使用 numpy 的广播进行操作。如果将图像从 3D 重塑为 2D,则该过程会变得更加容易,从而为您提供 HxW 行像素以供使用。
def filter(picture):
H,W = picture.shape[0],picture.shape[1]
picture = picture.astype('float').reshape(-1,3)
# A pixel with any r,g,b equalling zero can be removed.
picture[np.prod(picture,axis=1)==0] = 0
# Divide non-zero pixels by their rgb sum
picsum = picture.sum(axis=1)
nz_idx = picsum!=0
picture[nz_idx] /= (picsum[nz_idx].reshape(-1,1))
nonzeros = picture[nz_idx]
# Condition 1: r/g > 1.185
C1 = (nonzeros[:,0]/nonzeros[:,1]) > 1.185
# Condition 2: r*b / (r+g+b)^2 > 0.107
C2 = (nonzeros[:,0]*nonzeros[:,2])/(nonzeros.sum(axis=1)**2) > 0.107
# Condition 3: r*g / (r+g+b)^2 > 0.112
C3 = (nonzeros[:,0]*nonzeros[:,1])/(nonzeros.sum(axis=1)**2) > 0.112
# Combine conditions
C = ((C1*C2*C3)!=0)
picsum[nz_idx] = C
skin_points = np.where(picsum!=0)[0]
first_point = np.unravel_index(skin_points[0],(H,W))
counter = len(skin_points)
angle = (first_point[1]+1) * 91 * 0.00390626
return first_point, counter, angle
推荐阅读
- html - 在 Ajax ActionLink MVC 调用中将输入值作为参数传递
- sql - 我可以在三个 select 语句之间创建多个 Union 吗?
- html - 关键帧动画不执行
- c# - 通过单击按钮获取 ListView 项的值
- vue.js - 为什么引用不存在的静态 nuxt 资产的图像不会触发 @error?
- ruby - 为什么我的绘图方法中存在错误(自动归因?)
- c - 取消引用 int 指针与 char 指针
- html - 冻结在没有 JavaScript 的情况下同时使用水平和垂直滚动的 HTML 表格的前两列和最后一列
- c# - 使用 Selenium C# 测试经过身份验证的网站
- android - 如何将 MutableMap 从活动发送到另一个有意图的活动