Writing int16 numpy array as an proper image - python

I am trying to write(save) a int16 numpy array as an image using openCV. Find the numpy file of an image in the link below: https://drive.google.com/file/d/1nEq_CeNmSgacARa2ADr_f_qVaSfJSZZX/view?usp=sharing
The image I saved in bmp or png or tiff format is look like this:
Uint16
I converted the numpy array to uint8 and the image become very dark and the maximum value of the image is just 34 as shown below:
uint8
Please let me know how to properly save and visualize this int16 format image.
Note: plt.imshow of int16 numpy array showing proper visual. matplotlib_imshow

I have saved the image properly using the following syntax
from skimage.util import img_as_ubyte
img=np.load('brain.npy')
img1=img/img.max()
img2=img_as_ubyte(img1)
cv2.imwrite('brain_u8.png', img2)
correct_output

Related

CV2 imwrite not saving as16bit

Hi all I am working on a code which will save a numpy array of dtype=16, However when I am trying to save by cv2.imwrite, it saves as dtype=8.
print(pixel_array.dtype)
im=cv2.imwrite('result.TIFF',pixel_array)
im=cv2.imread('result.TIFF')
print(im.dtype)
The output for this code is
uint16
uint8
I tried with passing dtype for nd array.
pixel_array=ds.pixel_array
print(pixel_array.dtype)
im=cv2.imwrite('result.TIFF',pixel_array.astype(np.uint16))
im=cv2.imread('result.TIFF',)
print(im.dtype)
Unfortunately second code also saving image as 8 bit, Don't know what am I missing here.

Save 16-bit numpy arrays as 16-bit PNG image

I'm trying to save a 16-bit numpy array as a 16-bit PNG but what I obtain is only a black picture. I put here a minimum example of what I'm talking aboout.
im = np.random.randint(low=1, high=6536, size=65536).reshape(256,256) #sample numpy array to save as image
plt.imshow(im, cmap=plt.cm.gray)
Given the above numpy array this is the image I see with matplotlib, but when then I save the image as 16-bit png I obtain the picture below:
import imageio
imageio.imwrite('result.png', im)
Image saved:
where some light grey spots are visible but the image is substantially black. Anyway when I read back the image and visualize it again with matplotlib I see the same starting image. I also tried other libraries instead of imageio (like PIL or PyPNG) but with the same result.
I know that 16-bit image values range from 0 to 65535 and in the array numpy array here there only values from 1 to 6536, but I need to save numpy arrays images similar to this, i.e. where the maximum value represented in the image isn't the maximum representable value. I think that some sort of nornalization is involved in the saving process. I need to save the array exactly as I see them in matplotlib at their maximum resolution and without compression or shrinkage in their values (so division by 255 or conversion to 8-bit array are not suitable).
It looks like imageio.imwrite will do the right thing if you convert the data type of the array to numpy.uint16 before writing the PNG file:
imageio.imwrite('result.png', im.astype(np.uint16))
When I do that, result.png is a 16 bit gray-scale PNG file.
If you want the image to have the full grayscale range from black to white, you'll have to scale the values to the range [0, 65535]. E.g. something like:
im2 = (65535*(im - im.min())/im.ptp()).astype(np.uint16)
Then you can save that array with
imageio.imwrite('result2.png', im2)
For writing a NumPy array to a PNG file, an alternative is numpngw (a package that I created). For example,
from numpngw import write_png
im2 = (65535*(im - im.min())/im.ptp()).astype(np.uint16)
write_png('result2.png', im2)
If you are already using imageio, there is probably no signficant advantage to using numpngw. It is, however, a much lighter dependency than imageio--it depends only on NumPy (no dependence on PIL/Pillow and no dependence on libpng).

Restore grayscale image from jpg file

I have a 2-d numpy array, that I save as .jpg image.
For simplicity, let's assume my numpy array is the numbers between 0...255.
My problem is that once I save this array as .jpg image, I can't restore its values.
So my code is:
import cv2
from scipy.ndimage import imread
arr=np.array(range(256)).reshape(16,16)
cv2.imwrite('arr.jpg',arr)
restored=imread('arr.jpg')
print((arr==restored).sum()) #output is 224 rather than 256, i.e. 32 pixels are different!
So, how can I save the image so that I can see it, and restore the values afterwords?
Any help will be appreciated!

How to convert dtype(uint16) data into a 16bit png image?

I'm trying to encrypt and decrypt an image using RSA algo. For that, I need to read the image as greyscale and then apply the keys and save the uint16 type array into a png or any image format which supports 16bit data. Then I need to read that 16bit data convert it into an array and do the decryption. Now, previously I tried to save the image as .tif and when I read it with
img = sk.imread('image.tiff', plugin = 'tifffile')
it treats the image as RGB, which is not what I want. Now I want to save the uint16 type array to a 16bit png image which will take values between 0 to 65536 and then read it again as a uint16 type data. I tried to save the values to a 16bit png file using
img16 = img.astype(np.uint16)
imgOut = Image.fromarray(img16)
imgOut.save('en.png')
This gives me this error: OSError: cannot write mode I;16 as PNG
I have also tried imgOut = Image.fromarray(img16, 'I') but this yeilds not enough image data
Please help me to save the 16bit data into a .png image. Thank you.
There are a couple of possibilities...
First, using imageio to write a 16-bit PNG:
import imageio
import numpy as np
# Construct 16-bit gradient greyscale image
im = np.arange(65536,dtype=np.uint16).reshape(256,256)
# Save as PNG with imageio
imageio.imwrite('result.png',im)
You can then read the image back from disk and change the first pixel to mid-grey (32768) like this:
# Now read image back from disk into Numpy array
im2 = imageio.imread('result.png')
# Change first pixel to mid-grey
im2[0][0] = 32768
Or, if you don't like imageio, you can use PIL/Pillow and save a 16-bit TIFF:
from PIL import Image
import numpy as np
# Construct 16-bit gradient greyscale image
im = np.arange(65536,dtype=np.uint16).reshape(256,256)
# Save as TIFF with PIL/Pillow
Image.fromarray(im).save('result.tif')
You can then read back the image from disk and change the first pixel to mid-grey like this:
# Read image back from disk into PIL Image
im2 = Image.open('result.tif')
# Convert PIL Image to Numpy array
im2 = np.array(im2)
# Make first pixel mid-grey
im2[0][0] = 32768
Keywords: Image, image processing, Python, Numpy, PIL, Pillow, imageio, TIF, TIFF, PNG, 16 bit, 16-bit, short, unsigned short, save, write.

Finding sunspots on fits image via OpenCV

I am currently working with astronomical data(Images), and my task is to write a program which finds sunspots on given image in fits format.
As I understood, the task is OpenCV related, but I have encountered a huge obstacle with formats. The Image data is 2D float32 numpy array which when given to OpenCV loses all details.
I have tried converting float32 into uint8 as well, however the result was not good.
left: before(matplotlib), right: after(cv2)
As it is seen, details were lost and it is not a good picture to be finding spots on. So, maybe there is alternative way of solving this?
[import cv2
from astropy.io import fits
import matplotlib.pyplot as plt
import numpy as np
img_l = fits.open('hmi.Ic_45s.20170605_000000_TAI.2.continuum.fits')
img = img_l\[0\].data
plt.imshow(img) #Showing Image in matplotlib
cv2.imshow('',img) #The image is white round with black background
image = np.array(img/255, dtype = np.uint8) #Converting float32 to uint8
cv2.imshow('', image) #Getting converted image

Categories

Resources