高品质黑白摄影的作业案例,觉得比较有进一步研究的意义,故在blog同步一份作业草稿
|DA?ZE|
请注意,这可能不是一个「完美严谨」的实验
不过从数据上出发,至少比张口用Bit Depth来判断宽容度的键摄们靠谱一些
数字测试实验报告
现场使用可控光源,相机白平衡已经经过校准

拍摄:
拍摄时选择ISO100,曝光范围-10Stop - +5Stop,步长为0.3Stops进行曝光变换拍摄,得到原始RAW文件。
为了绕过相机内部以及图像处理软件自带的DRT(显示渲染变换)对图像的干预,以至于影响宽容度测量,使用直接解码RAW的方式。
预处理
解码RAW具体步骤如下
img = img.postprocess(
output_bps=16, #解码精度为16bit
use_camera_wb=True, #使用相机白平衡设定
no_auto_bright=False, #不使用自动曝光增益
exp_shift=1.0, #曝光增益设置为1,即不做更改
half_size=True #半尺寸图像
)
上述设定中,我使用16bit精度进行解码,并保存为16bit TIFF,用于后续分析,这一步目的是让后续步骤更加精准,这样一来,实验不会由于位深度不够导致测量误差。最后再标准化到8bit的数值即可得出结果。
除上述设定,解码RAW时,设定Gamma=1.0 (Scene-Linear场景线性),这样可以获得真实传感器获得的线性光信息,后续可以将Gamma再度进行变换,例如摄影师大多在sRGB (Gamma=2.2)下处理图像,即可再对结果图像进行Gamma转换并进行新的计算。

获取用户划定的ROI区域
def on_mouse(event, x, y, flags, param):
global img, point1, point2
img2 = img.copy()
if event == cv2.EVENT_LBUTTONDOWN: # 左键点击
point1 = (x, y)
cv2.circle(img2, point1, 10, (0, 255, 0), 5)
cv2.imshow('image', img2)
print('LBD')
elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON): # 按住左键拖曳
cv2.rectangle(img2, point1, (x, y), (255, 0, 0), 5)
cv2.imshow('image', img2)
elif event == cv2.EVENT_LBUTTONUP: # 左键释放
point2 = (x, y)
cv2.rectangle(img2, point1, point2, (0, 0, 255), 5)
cv2.imshow('image', img2)
min_x = min(point1[0], point2[0])
min_y = min(point1[1], point2[1])
width = abs(point1[0] - point2[0])
height = abs(point1[1] - point2[1])
cut_img = img[min_y:min_y + height, min_x:min_x + width]
cv2.imwrite('lena3.jpg', cut_img)
测量
获得了不同曝光结果的「线性光」图像,我们对每组图像的灰板区域进行均值统计。
通过划定一块ROI(感兴趣区域)矩形,并对这之内所有的像素值取平均值,以排除噪声对测量结果的影响
实际测量时,划定了一块约400x400的灰版干净区域
计算
解码RAW生成的TIF为16bit,数值区间0-65535,为了计算精确,我们进一步提升精度到32bit浮点。
将像素值除以65535,这步将画面中所有像素码值「标准化」到0.0 - 1.0。
img = cv2.imread(os.path.join(dirpath, i), cv2.IMREAD_UNCHANGED)
img = np.array(img) / 65535 # 标准化到0-1
img = img.astype('Float32') # 设置精度为32位浮点
img = img[img != 0.0] # 去除0值
如图所示
接下来只需要对之前划定的「目标区域」进行「均值统计」即可得出编码值
avgnum = np.average(img)
数据分析
样本统计实际使用了 53 张 14bit RAW 图像,中间处理共耗时 42 秒,计算ROI区域共耗时 2 秒,得到 Gamma=1.0 时的响应曲线
并获得了如下的「 曝光档位-码值 」数据表

制图
直接由以上数据制图,可以得到Gamma=1.0的线性光响应图像

观察图像,发现在ISO100时,高光区域的宽容度约为3挡,超过3挡后出现白切(White Clamp)
初步观察图像容易以为-2.0档下的信息不足,但由于Gamma=1.0,因此其实在暗部区域依然「挤了」大量信息,将Gamma转换到摄影师处理图像常用的sRGB标准-Gamma约为2.2,并标准化到8bit,获得以下图像:

在对数坐标轴下,能够更好的评估传感器的极限响应

观察图像发现,曝光为-9档时,码值变化趋于平缓,可以近似认为这是传感器的弱光响应阈值
-
进一步思考
使用该方法测量,传感器的响应能力极限接近12档,但实际这12档是否都可用?
我们知道,当传感器接收到的光照严重不足时,噪声将会占领图像的主导,所以即使能够通过后期将画面的曝光重新配准到 0 Stop ,画面的质量也会非常糟糕。
为了进一步了解画面干净程度随着传感器接收到的光照变化,我们增加一步计算,对ROI区域内像素值的「方差」进行计算,得到如下结果,能近似反应噪声水平随着曝光的变化

也就是说,当传感器实际曝光低于-5 Stops,画面的干净程度将会迅速下降,在-6 Stops后几乎为不可用的状态。
用实际图像进行验证
拍摄一张-6 Stop的图像,然后在Photoshop将曝光配准到 ~0 Stops

因此推测该传感器在ISO100时,最佳的可用宽容度(实用宽容度)为6-7档,[ 高光+3 - 暗部-4 ]
完
RAW DATA
-10.0 | 0.00023 | 62.3 | 5.7 | 0.2892308 | |
-9.7 | 0.00023 | 62.8 | 5.7 | 0.27700475 | |
-9.3 | 0.00024 | 63.2 | 5.7 | 0.27086622 | |
-9.0 | 0.00025 | 64.6 | 5.9 | 0.2517439 | |
-8.7 | 0.00028 | 66.6 | 6.2 | 0.21758626 | |
-8.3 | 0.00033 | 70.4 | 6.6 | 0.14211775 | |
-8.0 | 0.00036 | 72.9 | 7.0 | 0.10361197 | |
-7.7 | 0.00044 | 77.4 | 7.6 | 0.082401454 | |
-7.3 | 0.00055 | 82.3 | 8.4 | 0.10961231 | |
-7.0 | 0.00070 | 88.0 | 9.4 | 0.13559353 | |
-6.7 | 0.00093 | 94.4 | 10.7 | 0.13570395 | |
-6.3 | 0.00123 | 100.9 | 12.1 | 0.102633685 | |
-6.0 | 0.00158 | 106.7 | 13.6 | 0.059583493 | |
-5.7 | 0.00199 | 112.0 | 15.1 | 0.022942163 | |
-5.3 | 0.00248 | 117.1 | 16.7 | 0.012010948 | |
-5.0 | 0.00312 | 122.3 | 18.5 | 0.011867664 | |
-4.7 | 0.00395 | 127.8 | 20.6 | 0.010038988 | |
-4.3 | 0.00494 | 132.9 | 22.8 | 0.005481495 | |
-4.0 | 0.00628 | 138.5 | 25.4 | 0.0047046957 | |
-3.7 | 0.00790 | 143.7 | 28.2 | 0.0027132255 | |
-3.3 | 0.00996 | 149.1 | 31.4 | 0.0021490718 | |
-3.0 | 0.01251 | 154.3 | 34.8 | 0.0014286381 | |
-2.7 | 0.01567 | 159.5 | 38.6 | 0.0014590789 | |
-2.3 | 0.01978 | 164.8 | 42.9 | 0.0010625005 | |
-2.0 | 0.02506 | 170.3 | 47.7 | 0.00082777767 | |
-1.7 | 0.03164 | 175.7 | 53.1 | 0.0006198432 | |
-1.3 | 0.03983 | 180.9 | 58.9 | 0.0005162238 | |
-1.0 | 0.06388 | 191.8 | 73.0 | 0.0004276487 | |
-0.7 | 0.06528 | 192.3 | 73.8 | 0.0003652612 | |
-0.3 | 0.07995 | 197.0 | 80.9 | 0.00028825534 | |
0.0 | 0.10081 | 202.3 | 89.9 | 0.0002481517 | |
0.3 | 0.12681 | 207.6 | 99.7 | 0.0002322236 | |
0.7 | 0.16012 | 212.9 | 110.9 | 0.0001931208 | |
1.0 | 0.19847 | 217.9 | 122.3 | 0.10792131 | |
1.3 | 0.25383 | 223.5 | 136.7 | 0.004079156 | |
1.7 | 0.32104 | 228.9 | 152.1 | 0.0052663633 | |
2.0 | 0.40515 | 234.3 | 169.1 | 0.0011798091 | |
2.3 | 0.51071 | 239.6 | 187.9 | 0.00021078068 | |
2.7 | 0.64501 | 245.0 | 208.9 | 0.00016942676 | |
3.0 | 0.81359 | 250.3 | 232.2 | 0.00028660803 | |
3.3 | 0.99953 | 255.1 | 254.9 | 1.4080001E-05 | |
3.7 | 0.99998 | 255.1 | 255.0 | 4.7159956E-09 | |
4.0 | 0.99998 | 255.1 | 255.0 | 4.7159956E-09 | |
4.3 | 0.99998 | 255.1 | 255.0 | 4.7159956E-09 | |
4.7 | 0.99835 | 255.0 | 254.8 | 0.0015111227 | |
5.0 | 0.99905 | 255.1 | 254.9 | 0.0006000461 | |
5.3 | 0.99924 | 255.1 | 254.9 | 0.00038734142 | |
5.7 | 0.99964 | 255.1 | 255.0 | 0.00010429707 | |
6.0 | 0.99998 | 255.1 | 255.0 | 4.7159956E-09 | |
6.3 | 0.99998 | 255.1 | 255.0 | 4.7159956E-09 | |
6.7 | 0.99998 | 255.1 | 255.0 | 4.7159956E-09 | |
7.0 | 0.99998 | 255.1 | 255.0 | 4.7159956E-09 |