python - 如何使用优化算法找到可能的最佳参数
问题描述
我正在尝试为颜色遮罩找到一个好的颜色间隔,以便从图像中提取皮肤。
我有一个包含图像和蒙版的数据库,可以从这些图像中提取皮肤。这是一个示例:
我正在为每个图像应用蒙版以获得如下效果:
我从所有蒙面图像中获取所有像素并删除黑色像素,以便仅保留包含皮肤的像素。使用这种方法,我能够从不同的人那里收集包含不同肤色的不同颜色的不同像素。
这是我为此使用的代码:
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)
从不同的皮肤中提取所有颜色深浅后,我正在创建一个直方图,让我可以看到哪些颜色更常见。代码太长,无法创建直方图,但结果如下:
然后,我使用每个颜色空间图的转折点,并为该颜色空间选择一个距离,例如 20。该颜色空间的间隔是通过执行 [转折点 - 20,转折点 +20] 获得的
假设我们得到了以下内容:
:
- 转折点:142
- 距离:61
- 间隔:[81, 203]
G :
- 转折点:155
- 距离:10
- 间隔:[145, 165]
乙:
- 转折点:109
- 距离:14
- 间隔:[95, 123]
我将使用这些间隔从数据集中创建彩色图像的蒙版,以提取皮肤(左:我的间隔蒙版,右:真实蒙版):
使用我的间隔提取的掩码与数据集先前存在的掩码进行比较,并计算准确性,以查看我得到的间隔的有效性和良好程度:
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)
我不断更改间隔,测试和计算准确性,以便为每个颜色空间找到最佳间隔。这种变化是通过将距离乘以 0 到 2 之间的数字来完成的。例如:
老R:
- 转折点:142
- 距离:61
- 间隔:[81, 203]
新距离 = 旧距离 * 0.7 = 61 * 0.7 = 43
新R:
- 转折点:142
- 距离:43
- 间隔:[99, 185]
- 为了获得更高的间隔,我将乘以]1, 2] 中的一个数字
- 为了获得更小的间隔,我将乘以 ]0, 1[ 中的一个数字
现在,我的问题:
我想使用优化方法找到每个颜色空间的最佳间隔,而不是手动和随机更改间隔。我应该使用什么优化方法以及如何使用它?
感谢您抽出宝贵时间。感谢您的帮助。
解决方案
实际上,找到给定数据集的全局最优值并不太复杂。为简单起见,我们首先假设您有灰度图像,因为每种颜色都是独立处理的(我相信)。如果您根据落在所需间隔内的所有 3 种颜色对像素进行评分,那会有点复杂,但看起来您不是。
因此,无论如何,您可以根据数据集的大小,彻底检查每个图像的每个间隔。例如,如果每个像素只取 [0,255] 中的整数值,那么您甚至只需要考虑大约 100 个间隔大小。因此,您可以计算每个候选区间大小和每个图像的准确度,并简单地采用产生最高平均准确度的区间。重复所有颜色。这肯定是蛮力方法,但除非您的数据集非常大,否则使用优化的矩阵运算在计算上不应该是昂贵的。如果您的数据集很大,使用此技术的足够大的随机图像样本将产生近似值(尽管不是全局最优解)。
顺便说一句,您目前计算掩码和地面实况之间的准确性的方式非常低效。经验法则几乎是尽可能始终使用 numpy 矩阵运算,因为它们效率更高(有一些很酷的算法技巧可以节省矩阵运算的时间,并且它们是用 C 编写的,因此速度更快,因为出色地。
你可以替换这个:
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
使用等价矩阵运算:
ones = np.ones(img.shape)
zeros = np.zeros(img.shape)
diff = mask - img
TP = sum(np.where(np.multiply(diff,img) == 1,ones,zeros))
TN = sum(np.where(np.multiply(diff,1-img) == 1,ones,zeros))
FP = sum(np.where(diff == -1,ones,zeros))
FN = sum(np.where(diff == 1,ones,zeros))
这将节省您的时间,特别是如果您使用我建议的那种蛮力方法,但通常也是一种很好的做法
推荐阅读
- java - Spring Boot bean创建和依赖注入的顺序是什么?
- algorithm - 双向图中的传递闭包
- ios - 使用 ViewCellRenderer 在 iOS 上的 Xamarin Forms 中自动调整 ViewCell 的高度
- swift - firebase 中的超级简单查询出错(swift)
- c++ - OpenGL:着色/插值不起作用
- javascript - 在整个 Node.js 应用程序中传递依赖项对象与导入相比有什么缺点/缺点?
- javascript - 如何检索 websocket 连接列表?
- javascript - 是否可以使用 javascript 更新节点的 OUTER html?
- karate - 空手道 API:如何使用没有请求正文的 post 方法访问端点 url
- c++ - 使用折叠表达式初始化静态 constexpr 类数据成员无法编译