如何使用优化算法找到可能的最佳参数

Moh*_*dra 7 python optimization mask

我试图为颜色遮罩找到一个很好的颜色间隔,以便从图像中提取皮肤。

我有一个包含图像和蒙版的数据库,可以从这些图像中提取皮肤。这是一个示例示例:

示例图像

我正在为每个图像应用蒙版以获得如下效果:

屏蔽样本结果

我从所有蒙版图像中获取所有像素并删除黑色像素以仅保留包含皮肤的像素。使用这种方法,我能够收集不同的像素,这些像素包含来自不同人的不同皮肤的不同颜色深浅。

这是我为此使用的代码:

for i, (img_color, img_mask) in enumerate ( zip(COLORED_IMAGES, MASKS) ) :

    # masking
    img_masked = cv2.bitwise_and(img_color, img_mask)
    
    # transforming into pixels array
    img_masked_pixels = img_masked.reshape(len(img_masked) * len(img_masked[0]), len(img_masked[0][0]))
 
    # merging all pixels from all samples
    if i == 0:
        all_pixels = img_masked_pixels
    else:
        all_pixels = np.concatenate((all_pixels, img_masked_pixels), axis = 0)

# removing black
all_pixels = all_pixels[ ~ (all_pixels == 0).all(axis = 1) ]

# sorting pixels
all_pixels = np.sort(all_pixels)

# reshape into 1 NB_PIXELSx1 image in order to create histogram
all_pixels = all_pixels.reshape(len(all_pixels), 1, 3)

# creating image NB_PIXELSx1 image containing all skin colors from dataset samples
all_pixels = cv2.cvtColor(all_pixels, cv2.COLOR_BGR2YCR_CB)
Run Code Online (Sandbox Code Playgroud)

从不同的皮肤中提取所有颜色深浅后,我正在创建一个直方图,让我可以看到哪些颜色更常见。代码对于创建直方图来说太长了,但结果如下:

在此处输入图片说明

然后,我使用每个颜色空间图的转折点并为该颜色空间选择一个距离,例如 20。该颜色空间的间隔是通过执行 [ 转折点 - 20,转折点 +20 ] 获得的

在此处输入图片说明

所以假设我们得到了以下内容:

  • 转折点:142
  • 距离:61
  • 间隔:[81, 203]

G :

  • 转折点:155
  • 距离:10
  • 间隔:[145, 165]

乙:

  • 转折点:109
  • 距离:14
  • 间隔:[95, 123]

我将使用这些间隔从数据集中创建彩色图像的蒙版,以提取皮肤(左:我的间隔蒙版,右:ground truth 蒙版):

在此处输入图片说明

使用我的间隔提取的掩码与数据集预先存在的掩码进行比较,并计算准确性,以查看我得到的间隔的有效性和好坏:

precision_moy = 0
accuracy_moy = 0

for i, (image, img) in enumerate ( zip(COLORED, GROUND_TRUTH) ) :
    Min = np.array([81, 145, 95], np.uint8)
    Max = np.array([203, 165, 123], np.uint8)

    mask = cv2.inRange (image, Min, Max)

    TP = 0 # True Positive
    TN = 0 # True Negative
    FP = 0 # False Positive
    FN = 0 # False Negative

    for i in range(mask.shape[0]) :
        for j in range(mask.shape[1]) :
            if mask[i,j] == 255 and img[i,j,0] == 255:
                TP = TP + 1
            if mask[i,j] == 0 and img[i,j,0] == 0:
                TN = TN+1
            if mask[i,j] == 255 and img[i,j,0] == 0:
                FP = FP+1
            if mask[i,j] == 0 and img[i,j,0] == 255:
                FN = FN+1

    precision = TP/(TP+FP)
    accuracy = (TP+TN)/(TP+TN+FP+FN)
    
    precision_moy = precision_moy + precision
    accuracy_moy = accuracy_moy + accuracy

precision_moy = precision_moy / len(COLORED)
accuracy_moy = accuracy_moy / len(COLORED)
Run Code Online (Sandbox Code Playgroud)

我不断改变间隔,测试和计算准确性,以便为每个颜色空间找到最佳间隔。这种变化是通过将距离乘以 0 到 2 之间的数字来完成的。例如:

老R:

  • 转折点:142
  • 距离:61
  • 间隔:[81, 203]

新距离 = 旧距离 * 0.7 = 61 * 0.7 = 43

新 R:

  • 转折点:142
  • 距离:43
  • 间隔:[99, 185]
  • 为了获得更高的间隔,我将乘以一个数字 ]1, 2]
  • 为了获得更小的间隔,我将乘以一个数字 ]0, 1[

现在,我的问题:

我想使用优化方法而不是手动和随机更改间隔来找到每个颜色空间的最佳间隔。我应该使用什么优化方法以及我将如何使用它?

感谢您抽出宝贵时间。感谢您的帮助。

Maj*_*ajo 1

我建议使用遗传优化,它可以轻松地解决像您这样简单的问题。由于问题相对“小”,与 @Leander 建议的 Hillclimb 等局部优化方法相比,找到最佳解决方案应该不会花太长时间。遗传算法是一种元启发式搜索,因此不能保证找到最佳解决方案,但它应该可以让您非常接近。事实上,对于这样一个小问题,找到全局最优值的机会非常高。

首先,我建议您查看 DEAP,这样您就不必自己实现任何内容(https://deap.readthedocs.io/en/master/)。它包含许多遗传算法变体的非常好的实现,并且有带有很好示例的教程。通过一些努力,您应该能够在一两天内编写一个简单的优化算法。

GA为了简单起见,遗传算法从现在起将被表示为

一些从哪里开始的提示:

  • 我建议您从 DEAP 中最简单的变体开始eaSimple。当这不能令人满意时,您总是可以转向更复杂的东西,但我认为这是没有必要的。
  • Individual的 GA 将有 6 个组件 -> [blue_low, blue_high, green_low, green_high, red_low, red_high] 这也将解决 @Leander 在评论中提到的不对称间隔问题
  • mutations将通过随机改变个体的元素来完成
  • 对于fittness函数,您可以使用现在计算时的准确性

这基本上就是为您的问题构建 GA 所需的全部内容。此示例https://deap.readthedocs.io/en/master/examples/ga_onemax.html应该可以帮助您启动并运行。您只需要定义自己的个体、操作员和适应度评估函数,正如我在前面的步骤中提到的那样

关于使用任何通用优化方法的最后说明。据我了解,这是一个 6 维离散问题,因为您有 6 个分量:blue_low、blue_high、green_low、green_high、red_low、red_high,每个分量只有 255 个可能的值。这将阻止使用大多数优化方法,因为它们要求问题是连续的。