為了正確可視化RAW圖像,需要做好:白平衡、提亮以及色彩映射。
1 import numpy as np 2 import struct 3 from PIL import Image 4 import rawpy 5 import glob 6 import os 7 8 9 def conv(v): 10 s = 0 11 for i in range(len(v)): 12 s += i * v[i] 13 v[i] = s 14 return v 15 16 17 def diff(v): 18 n = len(v) 19 v_diff = np.zeros([len(v)]) 20 for i in range(n-1): 21 v_diff[n-1-i] = v[n-1-i] - v[n-1-i-1] 22 return v_diff 23 24 25 def gray_ps(rgb): 26 return np.power(np.power(rgb[:,:,0], 2.2) * 0.2973 + np.power(rgb[:,:,1], 2.2) * 0.6274 + np.power(rgb[:,:,2], 2.2) * 0.0753, 1/2.2) + 1e-7 27 28 29 def HDR(x, curve_ratio): 30 gray_scale = np.expand_dims(gray_ps(x), axis=-1) 31 gray_scale_new = np.power(gray_scale, curve_ratio) 32 return np.minimum(x * gray_scale_new / gray_scale, 1.0) 33 34 35 def gray_world_balance(x): 36 mean_ = np.maximum(np.mean(x, axis=(0, 1)), 1e-6) 37 ratio_ = mean_.mean() / mean_ 38 return np.minimum(x * ratio_, 1.0) 39 40 41 def show_bbf(path): 42 print('====== %s =====' % path) 43 max_level = 1023 44 black_level = 64 45 height = 3024 46 width = 4032 47 if path.endswith('dng') or path.endswith('DNG'): 48 raw = rawpy.imread(path) 49 im = raw.raw_image_visible.astype(np.float32) 50 res_path = str.replace(path, '.dng', '.jpg') 51 elif path.endswith('raw') or path.endswith('RAW'): 52 raw = open(path, 'rb').read() 53 raw = struct.unpack('H'*int(len(raw)/2), raw) 54 im = np.float32(raw) 55 res_path = str.replace(path, '.raw', '.jpg') 56 else: 57 assert False 58 im = im.reshape(height, width) 59 im = np.maximum(im - black_level, 0) / (max_level - black_level) 60 # AMPLIFICATION 61 # n = 256 62 # std = 0.05 63 # sample_rate = 1 64 # extreme_dark_ratio = 13 * std / 0.05 65 # light_scene_ratio = 4.0 * std / 0.05 66 # light_threshold = 0.04 67 # decay_in_light_ratio = 0.3 68 # light_radius = 5 69 # total = height * width / (sample_rate*sample_rate) / 4 70 # 71 # bins = np.arange(n + 1) / (n - 1) 72 # hists = [None] * 5 73 # hists[0], _ = np.histogram(im[0:1512:sample_rate, 0:2016:sample_rate], bins) 74 # hists[1], _ = np.histogram(im[0:1512:sample_rate, 2016:4032:sample_rate], bins) 75 # hists[2], _ = np.histogram(im[1512:3024:sample_rate, 0:2016:sample_rate], bins) 76 # hists[3], _ = np.histogram(im[1512:3024:sample_rate, 2016:4032:sample_rate], bins) 77 # hists[4] = (hists[0] + hists[1] + hists[2] + hists[3])/4 78 # convs = [None] * 5 79 # min_conv = 255 80 # max_conv = 0 81 # final_ratio = 1.0 82 # is_dark = False 83 # 84 # for i in range(5): 85 # hists[i] = hists[i] / total 86 # convs[i] = conv(hists[i][0:n]) 87 # print(convs[i][-1]) 88 # if convs[i][-1]<min_conv: 89 # min_conv = convs[i][-1] 90 # if convs[i][-1]>max_conv: 91 # max_conv = convs[i][-1] 92 # 93 # print('min=%.6f, max=%.6f' % (min_conv, max_conv)) 94 # 95 # hist_conv = convs[4] 96 # hist_diff = diff(hist_conv) 97 # ratio = std / (hist_conv[-1] / n) 98 # print("Normal ratio=%.6f" % ratio) 99 # if ratio < 1: 100 # print("Daylight scene found!") 101 # final_ratio = 1.0 102 # # check if exists high contrast scene 103 # if min_conv < 3 and max_conv/(min_conv + 1e-7) > 2.2: 104 # print('high contrast scene detected!') 105 # final_ratio = min(2.0, ratio) 106 # else: 107 # if max(hist_diff[-light_radius:]) > light_threshold: 108 # print('Light Found') 109 # if ratio > extreme_dark_ratio: 110 # final_ratio = ratio * decay_in_light_ratio 111 # print('Extreme Dark') 112 # else: 113 # final_ratio = min(light_scene_ratio, ratio) 114 # else: 115 # if ratio > extreme_dark_ratio: 116 # print('Extreme Dark') 117 # is_dark = True 118 # final_ratio = extreme_dark_ratio*extreme_dark_ratio*extreme_dark_ratio/(ratio*ratio) 119 # if 4 < final_ratio < 6: 120 # final_ratio = 4 121 # else: 122 # final_ratio = ratio 123 # if ratio < 1.0: 124 # final_ratio = 1.0 125 # if 5 < final_ratio < 12 and not is_dark: 126 # final_ratio *= 0.7 127 # im = np.minimum(im * final_ratio, 1.0) 128 # print('ratio=%.6f' % final_ratio) 129 im = np.expand_dims(im, axis=2) 130 H = im.shape[0] 131 W = im.shape[1] 132 out = np.concatenate(( 133 im[0:H:2, 1:W:2, :], 134 (im[0:H:2, 0:W:2, :] + im[1:H:2, 1:W:2, :])/2.0, 135 im[1:H:2, 0:W:2, :]), 136 axis=2) 137 if path.endswith('dng') or path.endswith('DNG'): 138 wb = np.array(raw.camera_whitebalance[:3], np.float32) 139 wb = wb / wb[1] 140 out = np.minimum(out * wb, 1.0) 141 else: 142 out = gray_world_balance(out) 143 out = np.minimum(out * 0.2 / out[:, :, 1].mean(), 1.0) 144 out = HDR(out, 0.35) 145 Image.fromarray(np.uint8(out*255)).save(res_path) 146 147 148 def dng2raw(path): 149 raw = rawpy.imread(path) 150 im = raw.raw_image_visible.astype(np.ushort) 151 h, w = im.shape 152 res_path = str.replace(path, '.dng', '.raw') 153 with open(res_path, 'wb')as fp: 154 for i in range(h): 155 for j in range(w): 156 a = struct.pack('<H', im[i, j]) 157 fp.write(a) 158 159 160 def decode_sony(path): 161 if os.path.split(path)[-1].split('.')[-1] != 'ARW': 162 print('Error: image type not match!') 163 exit(1) 164 im_ = rawpy.imread(path) 165 data_ = im_.raw_image_visible.astype(np.float32) 166 h_, w_ = data_.shape 167 save_path_ = str.replace(path, '.ARW', '.JPG') 168 data_ = np.maximum(data_ - 512, 0) / (16383 - 512) 169 data_ = np.expand_dims(data_, axis=2) 170 data_ = np.concatenate(( 171 data_[0:h_:2, 0:w_:2, :], 172 (data_[0:h_:2, 1:w_:2, :] + data_[1:h_:2, 0:w_:2, :]) / 2.0, 173 data_[1:h_:2, 1:w_:2, :]), 174 axis=2) 175 # white balance 176 wb = np.array(im_.camera_whitebalance[:3], np.float32) 177 wb = wb / wb[1] 178 data_ = np.minimum(data_ * wb, 1.0) 179 data_ = np.minimum(data_ * 0.2 / data_[:, :, 1].mean(), 1.0) 180 data_ = HDR(data_, 0.35) 181 Image.fromarray(np.uint8(data_ * 255)).save(save_path_) 182 183 184 def decode_sony_rawpy(path): 185 if os.path.split(path)[-1].split('.')[-1] != 'ARW': 186 print('Error: image type not match!') 187 exit(1) 188 im_ = rawpy.imread(path) 189 save_path_ = str.replace(path, '.ARW', '.JPG') 190 Image.fromarray(im_.postprocess(use_camera_wb=True)).save(save_path_) 191 192 193 if __name__ == '__main__': 194 # files = glob.glob('D:/data/report_dng/*.dng') 195 # for i in range(len(files)): 196 # show_bbf(files[i]) 197 198 # files = glob.glob('D:/data/Sony/long/00057_00_10s.ARW') 199 # im = rawpy.imread(files[0]) 200 # Image.fromarray(im.postprocess(use_camera_wb=True)).show() 201 202 # files = glob.glob('D:/data/Sony/long/*.ARW') 203 # for i in range(len(files)): 204 # decode_sony_rawpy(files[i]) 205 206 # files = glob.glob('D:/data/Sony/long/RAW/30s/*.ARW') 207 # for i in range(len(files)): 208 # decode_sony(files[i]) 209 210 # files = glob.glob('D:/data/Sony/dataset/illu_detect/day/*.dng') 211 # for i in range(len(files)): 212 # dng2raw(files[i]) 213 214 # files = glob.glob('C:/Users/Administrator/Desktop/ILLU/*.dng') 215 files = glob.glob('D:/data/LightOnOff/*.dng') 216 for i in range(len(files)): 217 # dng2raw(files[i]) 218 show_bbf(files[i])
展示圖片: