Is there any way to save a numpy array as a 16 bit image (tif, png) using any of the commonly available python packages? This is the only way that I could get to work in the
Created a custom script to do this using just numpy and OpenCV: (Still feels like a huge overkill though...)
import numpy as np
import cv2
def save_gray_deep_bits(filepath, float_array, bitdepth=16):
assert bitdepth in [8,16,24]
arr = np.squeeze(float_array)
assert len(arr.shape) == 2
assert '.png' in filepath
bit_iterations = int(bitdepth/8)
img_bgr = np.zeros((*arr.shape, 3), np.uint8)
encoded = np.zeros(arr.shape, np.uint8)
for i in range(bit_iterations):
residual = float_array - encoded
plane_i = (residual*(256**i)).astype(np.uint8)
img_bgr[:,:,i] = plane_i
encoded += plane_i
cv2.imwrite(filepath, img_bgr)
return img_bgr
def bgr_to_gray_deep_bits(bgr_array, bitdepth=16):
gray = np.zeros((bgr_array.shape[0], bgr_array.shape[1]), dtype = np.float32)
for i in range(int(bitdepth/8)):
gray += bgr_array[:,:,i] / float(256**i)
return gray
def load_gray_deep_bits(filepath, bitdepth=16):
bgr_image = cv2.imread('test.png').astype(np.float64)
gray_reconstructed = bgr_to_gray_deep_bits(bgr_image, bitdepth = bd)
return gray_reconstructed
bd = 24
gray_image_full_precision = np.random.rand(1024, 1024)*255.
save_gray_deep_bits('test.png', gray_image_full_precision, bitdepth = bd)
# Read image and check if our array is restored without losing precision
bgr_image = cv2.imread('test.png').astype(np.float64)
gray_reconstructed = bgr_to_gray_deep_bits(bgr_image, bitdepth = bd)
avg_residual = np.mean(np.abs(gray_reconstructed - gray_image_full_precision))
print("avg pixel residual: %.3f" %avg_residual)