不管是作为影视后期还是航拍和各种单反,是离不开lut的,使用lut来进行调色,就是将原图的rgb的数值映射成自己想要的rgb值,这样就能起到调色的作用。
这篇文章js实现影视级滤镜效果,lut3d的前端实现_js 滤镜_不知名前端的博客-CSDN博客讲lut 3d比较清楚,基本上就能知道是怎么回事。
于是在网上找了个lut图来试一试,
这里采样的是16,因此就是16*16*16的尺寸,虽然会比较粗糙一些。
但是计算思路大同小异,如果需要解析其他采样尺寸的,比如64*64*64,也能稍微改一下就行,python代码如下:
import math
import numpy as np
import cv2
def mapping_rgb(lut_img, rgb):
rgb = rgb/255.0 # 归一化到0-1
index_b = rgb[-1]*15 # 找到b的索引
slice0 = math.floor(index_b)
slice1 = math.ceil(index_b)
w_b = index_b-slice0 # 增加一个权重系数来进行加权,越靠近的比例越大
r = int(15*rgb[0]+0.5) # 四舍五入
g = int(15 * rgb[1] + 0.5)
color0 = lut_img[r, 16*slice0+g] # 16*slice0+g代表的是:slice0是表示在第几个蓝色通道里面,因此需要乘以宽度然后加上g才能找到lut图上的位置
color1 = lut_img[r, 16*slice1+g]
return np.clip(color0*(1-w_b)+w_b*color1, 0, 255)
def lut(lut_img,rgb_img):
h, w = rgb_img.shape[:2]
out_img = rgb_img.copy()
for i in range(h):
for j in range(w):
rgb = rgb_img[i, j, :]
out_img[i, j, :] = mapping_rgb(lut_img, rgb)
return out_img
if __name__ == '__main__':
lut_img = cv2.imread('xxx.png')
rgb_img = cv2.imread('demo.jpg')
rgb_img = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2RGB)
res_img = lut(lut_img=lut_img, rgb_img=rgb_img)
cv2.imwrite('lut_p_demo.jpg', res_img)
运行的结果如下:
虽然这个结果存在一些瑕疵,但是使用采样尺寸大一些就能解决掉,16*16*16使用的场景一般是本身分辨率就不太大的,更加常用的采样是64*64*64