Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
698 additions
and
1 deletion.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import rawpy | ||
import numpy as np | ||
import math | ||
import sys | ||
from scipy import signal | ||
|
||
""" Process RAW file into a image file. | ||
Example usage: | ||
raw = read("sample.ARW") | ||
rgb = process(raw) | ||
write(rgb, "output.ARW") | ||
""" | ||
|
||
|
||
def read(filename): | ||
""" | ||
Read RAW data from specified file. Currently supported formats are | ||
ARW (Sony RAW format) | ||
:param filename: path to the target RAW file | ||
""" | ||
return rawpy.imread(filename) | ||
|
||
|
||
def process(raw, color_matrix=[1024, 0, 0, 0, 1024, 0, 0, 0, 1024]): | ||
""" | ||
This processes RAW data that was read by read() method. | ||
Must be called after read() operation. No error is checked. | ||
""" | ||
raw_array = get_raw_array(raw) | ||
blc_raw = black_level_correction(raw, raw_array) | ||
dms_img = simple_demosaic(raw, blc_raw) | ||
img_wb = white_balance(raw, dms_img) | ||
img_ccm = color_correction_matrix(img_wb, color_matrix) | ||
img_gamma = gamma_correction(img_ccm) | ||
return img_gamma | ||
|
||
|
||
def write(rgb_image, output_filename): | ||
""" | ||
Write the processed RGB image to a specified file as PNG format. | ||
Thsi must be called after process(). No error is checked. | ||
:param output_filename: path to the output file. Extension must be png. | ||
""" | ||
import imageio | ||
outimg = rgb_image.copy() | ||
outimg[outimg < 0] = 0 | ||
outimg = outimg / outimg.max() * 255 | ||
imageio.imwrite(output_filename, outimg.astype('uint8')) | ||
|
||
|
||
def get_raw_array(raw): | ||
h, w = raw.sizes.raw_height, raw.sizes.raw_width | ||
raw_array = np.array(raw.raw_image).reshape((h, w)).astype('float') | ||
return raw_array | ||
|
||
|
||
def black_level_correction(raw, raw_array): | ||
blc = raw.black_level_per_channel | ||
bayer_pattern = raw.raw_pattern | ||
blc_raw = raw_array.copy() | ||
h, w = raw.sizes.raw_height, raw.sizes.raw_width | ||
for y in range(0, h, 2): | ||
for x in range(0, w, 2): | ||
blc_raw[y + 0, x + 0] -= blc[bayer_pattern[0, 0]] | ||
blc_raw[y + 0, x + 1] -= blc[bayer_pattern[0, 1]] | ||
blc_raw[y + 1, x + 0] -= blc[bayer_pattern[1, 0]] | ||
blc_raw[y + 1, x + 1] -= blc[bayer_pattern[1, 1]] | ||
return blc_raw | ||
|
||
|
||
def preview_demosaic(raw, raw_array): | ||
bayer_pattern = raw.raw_pattern | ||
h, w = raw.sizes.raw_height, raw.sizes.raw_width | ||
dms_img = np.zeros((h // 2, w // 2, 3)) | ||
for y in range(0, h, 2): | ||
for x in range(0, w, 2): | ||
colors = [0, 0, 0, 0] | ||
colors[bayer_pattern[0, 0]] += raw_array[y + 0, x + 0] | ||
colors[bayer_pattern[0, 1]] += raw_array[y + 0, x + 1] | ||
colors[bayer_pattern[1, 0]] += raw_array[y + 1, x + 0] | ||
colors[bayer_pattern[1, 1]] += raw_array[y + 1, x + 1] | ||
dms_img[y // 2, x // 2, 0] = colors[0] | ||
dms_img[y // 2, x // 2, 1] = (colors[1] + colors[3]) / 2 | ||
dms_img[y // 2, x // 2, 2] = colors[2] | ||
return dms_img | ||
|
||
def simple_demosaic(raw, raw_array): | ||
h, w = raw_array.shape | ||
dms_img2 = np.zeros((h, w, 3)) | ||
|
||
green = raw_array.copy() | ||
green[(raw.raw_colors == 0) | (raw.raw_colors == 2)] = 0 | ||
g_flt = np.array([[0, 1 / 4, 0], [1 / 4, 1, 1 / 4], [0, 1 / 4, 0]]) | ||
dms_img2[:, :, 1] = signal.convolve2d(green, g_flt, boundary='symm', mode='same') | ||
|
||
red = raw_array.copy() | ||
red[raw.raw_colors != 0] = 0 | ||
rb_flt = np.array([[1 / 4, 1 / 2, 1 / 4], [1 / 2, 1, 1 / 2], [1 / 4, 1 / 2, 1 / 4]]) | ||
dms_img2[:, :, 0] = signal.convolve2d(red, rb_flt, boundary='symm', mode='same') | ||
|
||
blue = raw_array.copy() | ||
blue[raw.raw_colors != 2] = 0 | ||
rb_flt = np.array([[1 / 4, 1 / 2, 1 / 4], [1 / 2, 1, 1 / 2], [1 / 4, 1 / 2, 1 / 4]]) | ||
dms_img2[:, :, 2] = signal.convolve2d(blue, rb_flt, boundary='symm', mode='same') | ||
return dms_img2 | ||
|
||
def white_balance(raw, rgb_array): | ||
wb = np.array(raw.camera_whitebalance) | ||
img_wb = np.zeros_like(rgb_array).reshape((-1, 3)) | ||
for index, pixel in enumerate(rgb_array.reshape(-1, 3)): | ||
pixel = pixel * wb[:3] / 1024 | ||
img_wb[index] = pixel | ||
return img_wb.reshape(rgb_array.shape) | ||
|
||
|
||
def color_correction_matrix(rgb_array, color_matrix): | ||
img_ccm = np.zeros_like(rgb_array).reshape((-1, 3)) | ||
ccm = np.array(color_matrix).reshape((3, 3)) | ||
for index, pixel in enumerate(rgb_array.reshape((-1, 3))): | ||
pixel = np.dot(ccm, pixel) | ||
img_ccm[index] = pixel | ||
return img_ccm.reshape(rgb_array.shape) | ||
|
||
|
||
def gamma_correction(rgb_array): | ||
img_gamma = rgb_array.copy().flatten() | ||
img_gamma[img_gamma < 0] = 0 | ||
img_gamma = img_gamma / img_gamma.max() | ||
for index, val in enumerate(img_gamma): | ||
img_gamma[index] = math.pow(val, 1 / 2.4) | ||
return img_gamma.reshape(rgb_array.shape) | ||
|
||
|
||
def main(argv): | ||
if (len(argv) < 2): | ||
print("Usage: {} input_filename [output_filename] [color_matrix]".format(argv[0])) | ||
print("\tDefault output_filename is output.png") | ||
print("\tDefault matrix is identity matrix ([1024, 0, 0, 0, 1024, 0, 0, 0, 1024]") | ||
print("\tExample: python3 {} sample.ARW sample.png \"1141, -205, 88, -52, 1229, -154, 70, -225, 1179\"".format(argv[0])) | ||
print("\tSupported RAW format is ARW (Sony RAW)") | ||
return | ||
|
||
filename = argv[1] | ||
output_filename = "output.png" | ||
color_matrix = [1024, 0, 0, 0, 1024, 0, 0, 0, 1024] | ||
if len(argv) > 2: | ||
output_filename = argv[2] | ||
if len(argv) > 3: | ||
color_matrix = [int(value) for value in (argv[3]).split(',')] | ||
|
||
color_matrix = [1024, 0, 0, 0, 1024, 0, 0, 0, 1024] | ||
raw = read(filename) | ||
raw_array = get_raw_array(raw) | ||
blc_raw = black_level_correction(raw, raw_array) | ||
dms_img = simple_demosaic(raw, blc_raw) | ||
img_wb = white_balance(raw, dms_img) | ||
img_ccm = color_correction_matrix(img_wb, color_matrix) | ||
rgb_image = gamma_correction(img_ccm) | ||
write(rgb_image, output_filename) | ||
|
||
|
||
if __name__ == "__main__": | ||
main(sys.argv) |
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.