Issue
I am trying to display .tif images using the ipywidgets in jupyter-notebooks. The below code works for .png and .jpg files
from ipywidgets import Image
png_image_path = r"C:\Users\xxxxxxxx\Work\Exercises\images\000000000.png"
file = open(png_image_path, "rb")
im = file.read()
Image(
value=im,
width=300,
height=400,
)
type(im) # <class 'bytes'>
The ipywidget from the above code renders the desired image. For reading a tif
file I am using gdal
.
img = gdal.Open(tif_img_path).ReadAsArray()
print(img.shape) # (3, 1024, 1024)
print(img.transpose(1,2, 0).shape) # (1024, 1024, 3)
type(img.transpose(1,2,0).tobytes()) # <class 'bytes'>
Image(
value=img.transpose(1,2,0).tobytes(),
width=300,
height=400,
)
I get the following output, the image is not properly displayed in the ipywidget
Solution
The fact that you just do file.read()
on the PNG image implies to me that Jupyter widgets expect a PNG or JPEG-encoded image, with a header and compressed pixel data.
If you open your TIFF with GDAL you will have a Numpy array, so you will need to encode it into an "in-memory" PNG or JPEG before passing to Jupyter widgets. You can do that with OpenCV like this:
import cv2
# Open TIFF image into Numpy array
img = gdal.Open(tif_img_path).ReadAsArray()
# Encode into in-memory PNG for Jupyter
_, PNG = cv2.imencode('.png', img)
As you rightly note in the comments, OpenCV uses BGR ordering so you would need to reverse the order of the colour channels with:
RGBimage = cv2.cvtColor(BGRimage, cv2.COLOR_BGR2RGB)
As an alternative to introducing the OpenCV dependency and its weird channel ordering, you could use PIL/Pillow which uses regular RGB ordering. In that case, you would convert a Numpy array you got from GDAL into a PNG with:
from io import BytesIO
im = ... read from GDAL ...
# Write Numpy array to in-memory PNG
membuf = BytesIO()
Image.fromarray(im).save(membuf, format="png")
... you can now use membuf.getvalue()
Note also, that in general TIFFs may contain float or float64 values that cannot be expressed in an 8-bit JPEG, so you may need to re-scale your data to fit the smaller range.
Answered By - Mark Setchell
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.