代码是直接借鉴的Opencv去除高光_SkyrimDragonBorn的博客-CSDN博客
原博客是c++,我这边只是使用python进行翻译了一下
参考的论文应该是这个:
(1)
Real-Time Specular Highlight Removal Using Bilateral Filtering | SpringerLinkIn this paper, we propose a simple but effective specular highlight removal method using a single input image. Our method is based on a key observation - the maximum fraction of the diffuse color component (so called maximum diffuse chromaticity in the literature) in...https://link.springer.com/chapter/10.1007/978-3-642-15561-1_7
(2)Efficient and Robust Specular Highlight Removal | IEEE Journals & Magazine | IEEE Xplorehttps://ieeexplore.ieee.org/abstract/document/6915741
import cv2
import numpy as np
img = cv2.imread('xxx.jpg')
def highlight_remove(img):
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32)#一定要转换成float32,否则会出错
# img = cv2.resize(img, (512, 512)).astype(np.float32)#如图片分辨率较大,直接resize到512会比较快
dst = img.copy()
h, w = img.shape[:2]
for i in range(h):
for j in range(w):
R = img[i, j, 0]
G = img[i, j, 1]
B = img[i, j, 2]
alpha_r = R/(R+G+B)
alpha_g = G/(R+G+B)
alpha_b = B/(R+G+B)
# alpha = max(max(alpha_r, alpha_g), alpha_b)
MaxC = max(max(R, G), B)
minalpha = min(min(alpha_r, alpha_g), alpha_b)
gama_r = (alpha_r - minalpha) / (1 - 3 * minalpha)
gama_g = (alpha_g - minalpha) / (1 - 3 * minalpha)
gama_b = (alpha_b - minalpha) / (1 - 3 * minalpha)
gama = max(max(gama_r, gama_g), gama_b)
temp = (gama * (R + G + B) - MaxC) / (3 * gama - 1)
dst[i, j, 0] = np.clip(R-(temp+0.5), 0, 255)
dst[i, j, 1] = np.clip(G-(temp+0.5), 0, 255)
dst[i, j, 2] = np.clip(B-(temp+0.5), 0, 255)
return dst[:, :, ::-1]
res = highlight_remove(img)
res = np.clip(res, 0, 255)
cv2.imwrite('xxx_remove.jpg', res)
效果如下,基本上可以和原来的c++版对应上
不过亲测这个算法只适合本来原图就是偏暗的图片,我这样的试了几张生活照基本上都失败的,所以这个算法适用范围很有限。