皮肤美白
思路一
整体图片变量,可以用非线性拉伸,选择那些把中间值拉高的函数,比如 \(y=log(1+x/\alpha) / log(1+1/\alpha)\),其中 \(\alpha\) 是控制拉伸程度的参数。这是一个常用的非线性函数,它的特点就是中间拉伸程度较高。
思路二
也可以用饱和度和亮度去做,转到 HSL 空间后,把饱和度调低、亮度调高,这样就会变白。
思路三
不是独立的思路。就是先检测出皮肤区域,然后再去使用上面两个思路去把皮肤区域变白。皮肤检测的算法也很简单,根据阈值去做就行,具体在另一个笔记中。
结果实验,肤色检测中选择第三种基于二次项更好一点,不过那个方法不检测偏红色的嘴唇,所以我改了点阈值,具体看下面代码就行。
结果展示
代码如下:
import cv2
import numpy as np
src = cv2.imread('./src.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY).astype(float)
# 方法一:非线性提升,把中间的值拉高,两边弱一点
alpha = 0.1
now = src.astype(float) / 255
now = np.log(1 + now/alpha) / np.log(1 + 1/alpha)
cv2.imwrite('./newimg1.png', (now*255).astype(np.uint8))
# 方法二:调整色调
HSV = cv2.cvtColor(src, cv2.COLOR_BGR2HSV).astype(float)
HSV[..., 1] = (HSV[..., 1] * 0.3).clip(0, 255)
HSV[..., 2] = (HSV[..., 2] * 1.3).clip(0, 255)
now = cv2.cvtColor(HSV.astype(np.uint8), cv2.COLOR_HSV2BGR)
cv2.imwrite('./newimg2.png', now)
# 方法三:检测出皮肤再去调整,这里用的检测方法在肤色检测的文章中,但改了一点阈值,让其能检测出红色的嘴唇
B, G, R = cv2.split(src.astype(float))
r, g, b = R/(R+G+B+1), G/(R+G+B+1), B/(R+G+B+1)
lupper = -1.3767 * r * r + 1.0743 * r + 0.1452
llower = -0.7760 * r * r + 0.5601 * r + 0.1366 # 这里改了一点,让它能检测出红色的嘴唇
Wrg = (r - 0.33) ** 2 + (g - 0.33) ** 2
mask1 = np.bitwise_and(g > llower, g < lupper)
mask2 = (Wrg > 0.0004)
mask3 = np.bitwise_and(R>G, G>B)
mask = np.bitwise_and(np.bitwise_and(mask1, mask2), mask3)
now = src.copy()
now[mask] = now1[mask]
cv2.imwrite('./newimg3.png', now)
结果:
原图 | 方法一 | 方法二 | 方法三(检测皮肤后用方法二变白) |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |