gpt4 book ai didi

python - 合并图像直方图的相似容器

转载 作者:行者123 更新时间:2023-12-05 06:07:34 25 4
gpt4 key购买 nike

我正在使用 Python(没有 AI,只有经典工具)做一个 CV 项目,遇到了一个问题。我正在尝试从手放在白色背景上的已知 ROI 中检测手和皮肤的颜色(因为它是网络摄像头,颜色可能不准确——例如,灰色对我来说可能被认为是白色)。我试着做一个颜色直方图,从那里我会提取手的颜色。为了获取颜色列表,我使用了 Image.getcolors(width*height),并将其放入直方图中。不幸的是,我得到了大量的颜色列表,其中很多颜色与其他颜色相似(例如,(255,0,0)和(255,0,1)在分开的箱子中表示)(由于相机质量差, 照明等..)。我的问题是如何合并这些垃圾箱并获得可靠的直方图,我可以从中提取肤色。这是我写的一些代码:

pilRoi = Image.fromarray(coloredRoi)
w,h = pilRoi.size
colorsInRoi = pilRoi.getcolors(w*h)
sortedColors = sorted(colorsInRoi, key=lambda tup: tup[0])[::-1]

用于对颜色进行排序。并且:

    for idx, color in enumerate(sortedColors):
if(idx<config.NUM_COLORS):
plt.bar(idx, color[0], color=helper.toHex(color[1]),edgecolor=helper.toHex(color[1]))
else:
break
plt.show()

用于直方图。我确实尝试删除白色范围像素的总和,其他颜色仍然存在问题:

    for color in sortedColors:
if isInWhiteRange(color[1]) or color[1] == config.BLUE:
toRemove.append(color)

for color in toRemove:
sortedColors.remove(color)

谢谢!

最佳答案

通常对于直方图,您将颜色放入 bin。例如,如果您有 256 个强度和 32 个箱,这意味着每个箱的宽度为 4。0-3 范围内的强度集中到第一个箱中,4-7 范围内的强度集中到第二个箱中,依此类推. 这就是正式的统一颜色量化,我们对像素进行量化,使其进入一组预定的 bin 中的一个。

在您的特定情况下,您可以为每个颜色 channel 指定多个 bin,然后您可以简单地计算一维直方图,这样对于每个颜色 channel ,您可以找出它属于该 channel 的哪个 bin,然后转换此序列将 3 个 bin 合并为一个值。我提倡一维直方图的原因是为了更容易计算图像之间的相似性度量。

由于您已经将 NumPy 形式的图像存储在 coloredRoi 中,我假设您已经在三个平面中拥有它,因此 channel 是最后一个维度的 3D 数组。我还假设您正在处理每个 channel 的 8 位无符号整数值。像这样简单的东西可以工作:

# Define number of bins per channel
num_red_bins = 8
num_green_bins = 8
num_blue_bins = 8

# Define threshold per bin
thresh_red = 256 // num_red_bins
thresh_green = 256 // num_green_bins
thresh_blue = 256 // num_blue_bins

# Extract planes
red = coloredRoi[..., 0]
green = coloredRoi[..., 1]
blue = coloredRoi[..., 2]

# Calculate bin number per location
bin_red = red // thresh_red
bin_green = green // thresh_green
bin_blue = blue // thresh_blue

# Calculate 1D bin locations
bins = num_red_bins * num_green_bins * bin_blue + num_green_bins * bin_red + bin_green

# Calculate histogram
histo = np.bincount(bins, minlength=num_red_bins * num_green_bins * num_blue_bins)

该代码非常不言自明,但最后两行可能令人困惑。在此之前,我们已经将 RGB 像素转换为它们在红色、绿色和蓝色 channel 中的 bin 位置。这些集合将为我们提供此像素相对于最终 3D bin 的映射位置。这是一个独特的元组,将映射到 1D 直方图中的单个位置。要计算最终的 1D bin 编号,请考虑红色导航该空间的行,绿色导航该空间的列。假设我们只需要处理红色和绿色,每次我们需要去到红色的新空间时,我们都必须跳 num_green_bins 过去,所以这就是为什么我们有 num_green_bins * bin_red。每次我们去一个新的绿色空间,我们只需要偏移列,这样我们就可以将 bin_green 添加到 num_green_bins * bin_red + bin_green。最后,如果我们想要变成蓝色,我们需要为每个我们想要的蓝色空间跳过 num_red_bins * num_green_bins,因为我们现在要变成 3D,因此我们现在还添加了 num_red_bins * num_green_bins * bin_blue。然后我们使用 numpy.bincount根据我们刚刚计算的 1D bins 计算最终的直方图。

现在您有了这个 1D 直方图,您可以使用任何直方图相似性度量来查看您期望从手上看到的颜色分布是否与感兴趣的色 block 相匹配。最后一点,如果您想看看这个量化图像是什么样子,只需取您的 bin 值并将 bin 值乘以我上面概述的每个 bin 的阈值,然后将所有内容叠加到最终图像中。

out_img = np.dstack((thresh_red * bin_red, thresh_green * bin_green, thresh_blue * bin_blue))

numpy.dstack获取 2D 数组并将它们堆叠在三维中以生成合并的 3D 数组。如果你做对了,当你可视化存储在 out_img 中的量化结果时,颜色的微小变化就会消失。请注意,每个颜色 channel 的 bin 数量是您需要调整的参数。 bin 的数量越多,您获得的颜色就越细粒度,从而增加了您所表示的动态范围,但是使用粒度颜色会以将非常相似的 RGB 像素视为不同为代价。同样,bin 的数量越少,在更广泛的值范围内看起来越相似的颜色,这将使您的分类的判别力变弱。我建议更改 bin 的数量,以便您在反射(reflect)人类肤色(红色/绿色)的 bin 上放置更多夸张,并减少对不反射(reflect)人类肤色(蓝色)的颜色的强调。

关于python - 合并图像直方图的相似容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65396310/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com