Skip to content

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()```

Comments