# csdn -牧野- 2020-3-20
import rawpy
import imageio
import numpy as np
raw = rawpy.imread('take.dng')
# use_camera_wb 是否执行自动白平衡,如果不执行白平衡,一般图像会偏色
# half_size 是否图像减半
# no_auto_bright 不自动调整亮度
# output_bps bit数据, 8或16
img = raw.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=False, output_bps=16)
# img = np.float32(img / (2**16-1)*255.0)
# img = np.asarray(img,np.uint8)
imageio.imsave('take.jpg', img)
# csdn -牧野- 2020-5-20
import rawpy
import imageio
import numpy as np
import tifffile
raw = rawpy.imread('take.dng')
# use_camera_wb 是否执行自动白平衡,如果不执行白平衡,一般图像会偏色
# half_size 是否图像减半
# no_auto_bright 不自动调整亮度
# output_bps bit数据, 8或16
img = raw.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=True, output_bps=16)
# img = np.float32(img / (2**16-1)*255.0)
# img = np.asarray(img,np.uint8)
tifffile.imwrite('take.tiff', data=img)
利用多张RAW文件查找出错误像素并修复
# csdn -牧野- 2020-3-20
import rawpy
import imageio
import rawpy.enhance
# 具有同样坏点的3~5张图像,最好是不同场景下拍的
# 基本上,图像越多,检测到的坏点会越少
paths = ['1.dng', '2.dng', '3.dng', '4.dng']
bad_pixels = rawpy.enhance.find_bad_pixels(paths)
raw = rawpy.imread('1.dng')
rawpy.enhance.repair_bad_pixels(raw, bad_pixels, method='median')
img = raw.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=False, output_bps=16)
imageio.imsave('1_repair_bed_pixels.jpg', img)
raw = rawpy.imread('1.dng')
img = raw.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=False, output_bps=16)
imageio.imsave('1_without_repair.jpg', img)
拜耳阵列(Bayer pattern)分为GBRG、GRBG、BGGR、RGGB四种模式:
使用rawpy把不同模式下raw解析为四通道:
# csdn -牧野- 2020-3-27
# 参考 https://www.cnblogs.com/thisisajoke/p/10418817.html
import rawpy
import numpy as np
from PIL import Image
import imageio
import exifread
def gray_ps(rgb):
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
def do_HDR(x, curve_ratio):
gray_scale = np.expand_dims(gray_ps(x), axis=-1)
gray_scale_new = np.power(gray_scale, curve_ratio)
return np.minimum(x * gray_scale_new / gray_scale, 1.0)
def adjust_out_matrix(RAW_path, out=None):
raw = open(RAW_path, 'rb')
exif_info = exifread.process_file(raw, details=False, strict=True)
orientation_str = 'EXIF Orientation'
if exif_info.__contains__('Image Orientation'):
orientation_str = 'Image Orientation'
orientation_info = exif_info[orientation_str].printable
if orientation_info == 'Rotated 180':
if out is None:
return True
else:
if out.shape[2] == 3:
out0 = out[:, :, :1]
out1 = out[:, :, 1:2]
out2 = out[:, :, 2:3]
out = np.concatenate((out2, out1, out0), 2)
elif out.shape[2] == 4:
out0 = out[:, :, :1]
out1 = out[:, :, 1:2]
out2 = out[:, :, 2:3]
out3 = out[:, :, 3:4]
out = np.concatenate((out3, out2, out1, out0), 2)
else:
raise
return np.flip(out)
elif orientation_info == 'Horizontal (normal)':
if out is None:
return False
else:
return out
else:
raise
# pack Bayer image to 4 channels
def pack_raw(raw_path, white_balance=True, auto_bright=True, HDR=True, save_JPEG=True):
raw = rawpy.imread(raw_path)
im = raw.raw_image_visible.astype(np.float32)
# subtract the black level
# 16383(2^14) is the camera's maximal pixel value, you can get it by "np.max(raw.raw_image)" . Ensure full exposure!
im = np.maximum(im - raw.black_level_per_channel[0], 0) / (16383 - raw.black_level_per_channel[0])
im = np.expand_dims(im, axis=2)
H = im.shape[0]
W = im.shape[1]
if raw.raw_pattern[0, 0] == 0: # RGGB
out = np.concatenate((im[0:H:2, 0:W:2, :],
im[0:H:2, 1:W:2, :],
im[1:H:2, 1:W:2, :],
im[1:H:2, 0:W:2, :]), axis=2)
elif raw.raw_pattern[0, 0] == 2: # BGGR
out = np.concatenate((im[1:H:2, 1:W:2, :],
im[0:H:2, 1:W:2, :],
im[0:H:2, 0:W:2, :],
im[1:H:2, 0:W:2, :]), axis=2)
elif raw.raw_pattern[0, 0] == 1 and raw.raw_pattern[0, 1] == 0: # GRBG
out = np.concatenate((im[0:H:2, 1:W:2, :],
im[0:H:2, 0:W:2, :],
im[1:H:2, 0:W:2, :],
im[1:H:2, 1:W:2, :]), axis=2)
elif raw.raw_pattern[0, 0] == 1 and raw.raw_pattern[0, 1] == 2: # GBRG
out = np.concatenate((im[1:H:2, 0:W:2, :],
im[0:H:2, 0:W:2, :],
im[0:H:2, 1:W:2, :],
im[1:H:2, 1:W:2, :]), axis=2)
if white_balance:
wb = np.array(raw.camera_whitebalance, np.float32)
wb[3] = wb[1]
wb = wb / wb[1]
out = np.minimum(out * wb, 1.0)
if auto_bright:
mean_G = (out[:, :, 1].mean() + out[:, :, 3].mean()) / 2.0
out = np.minimum(out*0.2/mean_G, 1.0)
out = adjust_out_matrix(raw_path, out)
if save_JPEG:
out0 = out[:, :, 0:1]
out1 = out[:, :, 1:2]
out2 = out[:, :, 2:3]
out3 = out[:, :, 3:4]
out_JPEG = np.concatenate((out0, (out1 + out3) / 2., out2), axis=2)
if HDR:
out_JPEG = do_HDR(out_JPEG, 0.35)
Image.fromarray(np.uint8(out_JPEG * 255)).save('result.jpg')
return out
if __name__ == '__main__':
raw = rawpy.imread('leica.dng')
np_channel = pack_raw('leica.dng', auto_bright=False, HDR=False)
img = raw.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=True, output_bps=16)
imageio.imsave('rawpy.jpg', img)
# csdn -牧野- 2020-6-20
# 参考 https://github.com/letmaik/rawpy/issues/54
import rawpy
import numpy as np
import imageio
def adjust_raw(raw_path):
raw_source = rawpy.imread(raw_path)
raw_adjust = rawpy.imread(raw_path)
H, W = raw_adjust.raw_image_visible.astype(np.float32).shape
raw_adjust.raw_image_visible[:] = raw_adjust.raw_image_visible * 2
img_source = raw_source.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=True, output_bps=16)
img_adjust = raw_adjust.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=True, output_bps=16)
imageio.imsave('raw_source.jpg', img_source)
imageio.imsave('raw_adjust.jpg', img_adjust)
if __name__ == '__main__':
adjust_raw('leica.dng')
# csdn -牧野- 2020-6-12
# 参考 https://github.com/Jiaming-Liu/BayerUnifyAug
import numpy as np
import rawpy
BAYER_PATTERNS = ["RGGB", "BGGR", "GRBG", "GBRG"]
NORMALIZATION_MODE = ["crop", "pad"]
def bayer_unify(raw: np.ndarray, input_pattern: str, target_pattern: str, mode: str) -> np.ndarray:
"""
Convert a bayer raw image from one bayer pattern to another.
Parameters
----------
raw : np.ndarray in shape (H, W)
Bayer raw image to be unified.
input_pattern : {"RGGB", "BGGR", "GRBG", "GBRG"}
The bayer pattern of the input image.
target_pattern : {"RGGB", "BGGR", "GRBG", "GBRG"}
The expected output pattern.
mode: {"crop", "pad"}
The way to handle submosaic shift. "crop" abandons the outmost pixels,
and "pad" introduces extra pixels. Use "crop" in training and "pad" in
testing.
"""
if input_pattern not in BAYER_PATTERNS:
raise ValueError('Unknown input bayer pattern!')
if target_pattern not in BAYER_PATTERNS:
raise ValueError('Unknown target bayer pattern!')
if mode not in NORMALIZATION_MODE:
raise ValueError('Unknown normalization mode!')
if not isinstance(raw, np.ndarray) or len(raw.shape) != 2:
raise ValueError('raw should be a 2-dimensional numpy.ndarray!')
if input_pattern == target_pattern:
h_offset, w_offset = 0, 0
elif input_pattern[0] == target_pattern[2] and input_pattern[1] == target_pattern[3]:
h_offset, w_offset = 1, 0
elif input_pattern[0] == target_pattern[1] and input_pattern[2] == target_pattern[3]:
h_offset, w_offset = 0, 1
elif input_pattern[0] == target_pattern[3] and input_pattern[1] == target_pattern[2]:
h_offset, w_offset = 1, 1
else: # This is not happening in ["RGGB", "BGGR", "GRBG", "GBRG"]
raise RuntimeError('Unexpected pair of input and target bayer pattern!')
if mode == "pad":
out = np.pad(raw, [[h_offset, h_offset], [w_offset, w_offset]], 'reflect')
elif mode == "crop":
h, w = raw.shape
out = raw[h_offset:h - h_offset, w_offset:w - w_offset]
else:
raise ValueError('Unknown normalization mode!')
return out
def pack_raw(raw_path):
raw = rawpy.imread(raw_path)
im = raw.raw_image_visible.astype(np.float32)
# subtract the black level
# 16383(2^14) is the camera's maximal pixel value, you can get it by "np.max(raw.raw_image)" . Ensure full exposure!
im = np.maximum(im - raw.black_level_per_channel[0], 0) / (16383 - raw.black_level_per_channel[0])
return im
if __name__ == '__main__':
raw_pack = pack_raw('0.dng')
print(raw_pack.shape)
raw_pack_new = bayer_unify(raw_pack, 'RGGB', 'GRBG', 'crop')
print(raw_pack_new.shape)
ExifRead安装:
pip install exifread -i https://pypi.mirrors.ustc.edu.cn/simple/
# csdn -牧野- 2020-3-26
import exifread
# 不限于RAW,RGB图片也适用
raw_file = open('take.dng', 'rb')
exif_file = exifread.process_file(raw_file, details=False, strict=True)
for key, value in exif_file.items():
print(key, value)
if exif_file.has_key('EXIF ExposureTime'):
exposure_str = exif_file['EXIF ExposureTime'].printable
else:
exposure_str = exif_file['Image ExposureTime'].printable
if '/' in exposure_str:
fenmu = float(exposure_str.split('/')[0])
fenzi = float(exposure_str.split('/')[-1])
exposure = fenmu / fenzi
else:
exposure = float(exposure_str)
if exif_file.has_key('EXIF ISOSpeedRatings'):
ISO_str = exif_file['EXIF ISOSpeedRatings'].printable
else:
ISO_str = exif_file['Image ISOSpeedRatings'].printable
if '/' in ISO_str:
fenmu = float(ISO_str.split('/')[0])
fenzi = float(ISO_str.split('/')[-1])
ISO = fenmu / fenzi
else:
ISO = float(ISO_str)
# FNumber = float(exif_file['Image FNumber'].printable)
print('曝光时间:', exposure)
# print('光圈:', FNumber)
print('ISO:', ISO)