01_relinear_in_opencv
原始文件为 .py 代码,本文是转换后的 Markdown 文件。
```.py
import os
os.chdir(os.path.dirname(os.path.abspath(file)))
import cv2
import math
import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize
picnum = 16
images = [cv2.imread(f'../data/door_stack/exposure{i}.jpg', -1) for i in range(picnum)]
exptime = np.array([(2**i) for i in range(picnum)], dtype=np.float32)
获取图片宽和高
rows, cols = images[0].shape[0:2]
直接用 opencv 的 API 来做
cv_response = cv2.createCalibrateDebevec().process(images, exptime)
'''
1. 权重函数选择的是 w_tent
2. 没有设置 minv 和 maxv,默认值 -100 和 100 其实就表示不做检查了
3. 之前是 min(z/255, 1-(z/255)),现在改为 min((1+z)/256, 1-(z/256)),但这个影响基本可以忽略
'''
def w_tent(z, minv=-100, maxv=100):
v = 1 + z if z < 128 else 256 - z
return v / 256
def compute_by_matrix(I, my_lambda, w_func):
N, P = I.shape[0:2]
A = np.zeros((N*P+255, 256+N))
b = np.zeros((N*P+255, 1))
for i in range(N):
for j in range(P):
Iij = int(I[i, j])
w = w_func(Iij)
A[i*P+j, Iij] = w
A[i*P+j, 256+i] = -w
'''
4. 计算曝光用 ln 而不是 log2
'''
b[i*P+j] = w * math.log(exptime[j])
A[N*P-1, 128] = 1
for i in range(254):
A[N*P+i, i+0] = my_lambda * w_func((i+1))
A[N*P+i, i+1] = -2 * my_lambda * w_func((i+1))
A[N*P+i, i+2] = my_lambda * w_func((i+1))
x = np.linalg.lstsq(A, b, rcond=None)[0]
return x[0:256, 0]
在 P 张曝光图像上选择 N 个点
P = picnum
N = 100
I 表示选择的点,注意 I(i,j) 中 i 表示像素位置,j 表示第几张图片
I = np.zeros((N, P))
'''
5. 每个通道单独做(之前是所有通道平均取一些点)
'''
每个通道单独做,这里用 绿色 为例
points = np.random.randint([0, 0], [rows, cols], size=(N, 2))
for pidx in range(P):
onepic = images[pidx][..., 1][points[:, 0], points[:, 1]]
I[:, pidx] = onepic
now_lambda = 20
matrix_response = compute_by_matrix(I, my_lambda=now_lambda, w_func=w_tent)
比较结果
plt.figure()
plt.plot(np.log(cv_response[..., 1]), label='Opencv-G')
plt.plot(matrix_response, label=f'My-lambda={now_lambda}')
plt.legend()
plt.show()```