PIL loading single channel for tif image data type - matplotlib

I've a satelite image with tiff file format. When i try to open the file using pil and then print size, I get only one channel:
im = Image.open('1989.tif',mode='r')
print(im.size) -- > (687,1091)
If i try to open with matplotlib, it loads all the channel but I get a blank image when I use imshow( r,g,b values of the images are all zero when I print the values) :
im=plt.imread("1989.tif")
print(im.shape) -- > (687,1091,4)
plt.imshow(im) -- > shows blank image
I don't know how to fix either of them.
Adding the link to the image :
https://drive.google.com/open?id=1uNQxyCplD7rYd_ZWfFntP1bN_Qg49ybU

Your image is an uncompressed 32-bit floating point single channel image. PIL/Pillow seems able to read it fine - it will have problems displaying it, but we can work on that next...
from PIL import Image
import numpy as np
# Load image and make into Numpy array
im = Image.open('a.tif')
n = np.array(im)
# Check max value
print(n.max()) # prints 0.54
# Make an 8-bit version for display
Image.fromarray((n*200).astype(np.uint8)).show()
You can inspect the image with tiffinfo that comes with libtiff:
tiffinfo a.tif
Output
TIFFReadDirectory: Warning, Unknown field with tag 33550 (0x830e) encountered.
TIFFReadDirectory: Warning, Unknown field with tag 33922 (0x8482) encountered.
TIFFReadDirectory: Warning, Unknown field with tag 34735 (0x87af) encountered.
TIFFReadDirectory: Warning, Unknown field with tag 34736 (0x87b0) encountered.
TIFFReadDirectory: Warning, Unknown field with tag 34737 (0x87b1) encountered.
TIFFReadDirectory: Warning, Unknown field with tag 42112 (0xa480) encountered.
TIFFReadDirectory: Warning, Unknown field with tag 42113 (0xa481) encountered.
TIFF Directory at offset 0x8 (8)
Image Width: 1091 Image Length: 687
Tile Width: 128 Tile Length: 128
Bits/Sample: 32
Sample Format: IEEE floating point
Compression Scheme: None
Photometric Interpretation: min-is-black
Samples/Pixel: 1
Planar Configuration: single image plane
Tag 33550: 30.000000,30.000000,0.000000
Tag 33922: 0.000000,0.000000,0.000000,357075.000000,2904735.000000,0.000000
Tag 34735: 1,1,0,16,1024,0,1,1,1025,0,1,1,1026,34737,24,0,2048,0,1,4326,2049,34737,84,24,2050,0,1,6326,2051,0,1,8901,2054,0,1,9102,2055,34736,1,0,2056,0,1,7030,2057,34736,1,1,2059,34736,1,2,2061,34736,1,3,3072,0,1,32646,3073,34737,410,108,3076,0,1,9001
Tag 34736: 0.017453,6378137.000000,298.257224,0.000000
Tag 34737: PCS Name = UTM_Zone_46N|GCS Name = GCS_WGS_1984|Datum = D_WGS_1984|Ellipsoid = WGS_1984|Primem = Greenwich||ESRI PE String = PROJCS["UTM_Zone_46N",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",93.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]|
Tag 42112: <GDALMetadata>
<Item name="STATISTICS_EXCLUDEDVALUES" sample="0"></Item>
<Item name="STATISTICS_MAXIMUM" sample="0">0.53153151273727</Item>
<Item name="STATISTICS_MEAN" sample="0">0.14108245105659</Item>
<Item name="STATISTICS_MINIMUM" sample="0">-0.48148149251938</Item>
<Item name="STATISTICS_SKIPFACTORX" sample="0">1</Item>
<Item name="STATISTICS_SKIPFACTORY" sample="0">1</Item>
<Item name="STATISTICS_STDDEV" sample="0">0.15760411626121</Item>
</GDALMetadata>
Tag 42113: -3.4028234663852886e+38

Related

Spectral Python imshow displaying scrambled image

I am learning Spectral Python and using their own documentation and sample image files to display a multispectral image as RGB. However, for some reason, my image appears scrambled up. I have tested the image file by opening it in MultiSpec and it appears as it should, so I do not think the file is damaged. My code is as follows:
import spectral as s
import matplotlib as mpl
path = '/content/92AV3C.lan'
img = s.open_image(path)
print(img)
#Load and display hyperspectral image
arr = img.load()
view = s.imshow(arr, (29, 19, 9))
print(view)
#Load and display Ground truth image
gt = s.open_image('92AV3GT.GIS').read_band(0)
view = s.imshow(classes=gt)
Output is as follows:
I suggest that you try the following command instead of view=imshow(img, (RGB))`. SpectralPython has the smarts, once you identify the image type, i.e., *.lan to display the image in the correct format.

Color issue when saving PDF page Pixmap as PNG using PyMuPDF

I'm running the following bit of Python code from the PyMuPDF 1.16.17 documentation, which save PNG images for every page in a PDF file.
import sys, fitz # import the binding
fname = "test.pdf" # get filename from command line
doc = fitz.open(fname) # open document
for page in doc: # iterate through the pages
pix = page.getPixmap()
pix.writePNG("F:/cynthia/page-%i.png" % page.number) # store image as a PNG
The resulting PNG images' colors are off from the PDF originals (too saturated and high contrast). I know function Page.getPixmap() has a "colorspace" argument, and using Document.getPageImageList I found out that my PDF's colorspace is "DeviceCMYK". But when I try to get a Pixmap using CMYK as colorspace (replacing the pix = page.getPixmap() line with pix = page.getPixmap(colorspace="CMYK") or `pix = page.getPixmap(colorspace=csCMYK)), it doesn't change the resulting colors. Any help is appreciated.
Please upgrade your PyMuPDF version. Then ICC color support will be included which should improve your output.

How to get the Numpy array of file stream of any image

I'm trying to use the imageai python library, and more particularly this function:
detector.detectObjectsFromImage()
The doc says it should be used with a Numpy array of file stream of any image.
https://imageai.readthedocs.io/en/latest/detection/index.html
When I pass it a Numpy array, like this:
detections = detector.detectObjectsFromImage(input_image=anumpyarray,input_type = "array")
I get the error:
detections =
detector.detectObjectsFromImage(input_image=anumpyarray,input_type =
"array") File
"/usr/local/lib/python3.6/site-packages/imageai/Detection/init.py",
line 517, in detectObjectsFromImage raise ValueError("Ensure you
specified correct input image, input type, output type and/or output
image path ") ValueError: Ensure you specified correct input image,
input type, output type and/or output image path
Is it because a Numpy array and a Numpy array of a stream of an image are different things?
I know it's old, but for anyone who needs help:
Try to set 2 additional params:
minimum_percentage_probability=0, output_type='array'
For more info, go into imageai\Detection\__init__.py -> detectObjectsFromImage

PyPdf: split each page in two, pad with blank space

I have a PDF file (A4, portrait layout), each page of which I want to split in a half of height. The output document should also be A4 and portrait layout, but lower half of each page needs to be blank.
I saw https://stackoverflow.com/a/15743413/822789 but did not understand how to add blank space with mediaBox.
I don't really know PyPDF2 all that well, but I am the author of pdfrw and if I understand your question, pdfrw can certainly do what you want quite easily. I need to document it a bit better, but I had a preexisting
unspread.py example that splits pages left and right, to chop down tabloid pages into the original pages. Here is a modified version of that example. This version will split pages top and bottom, and also change the size of the output page so that it matches the input page:
#!/usr/bin/env python
'''
usage: splitv.py my.pdf
Creates splitv.my.pdf
This is similar to unspread.py, in that it creates
a new file that has twice the pages of the old file.
It is different in two ways:
1) It splits pages top and bottom rather than left and right
2) The destination pages are the same size as the source pages,
and the output is placed at the top.
'''
import sys
import os
from pdfrw import PdfReader, PdfWriter, PageMerge
def splitpage(src):
''' Split a page into two (top and bottom)
'''
# Yield a result for each half of the page
for y_pos in (0, 0.5):
# Create a blank, unsized destination page.
page = PageMerge()
# add a portion of the source page to it as
# a Form XObject.
page.add(src, viewrect=(0, y_pos, 1, 0.5))
# By default, the object we created will be
# at coordinates (0, 0), which is the lower
# left corner. To move it up on the page
# to the top, we simply use its height
# (which is half the source page height) as
# its y value.
page[0].y = page[0].h
# When we render the page, the media box will
# encompass (0, 0) and all the objects we have
# placed on the page, which means the output
# page will be the same size as the input page.
yield page.render()
inpfn, = sys.argv[1:]
outfn = 'splitv.' + os.path.basename(inpfn)
writer = PdfWriter()
for page in PdfReader(inpfn).pages:
writer.addpages(splitpage(page))
writer.write(outfn)

Can matplotlib animation output vector sequence?

Is it possible to output sequence of files in vector format through matplotlib animation module?
For example:
...
anim = animation.FuncAnimation(...)
anim.save('animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
outputs mp4 movie (through ffmpeg).
Can I instruct animation class to output sequence of vector files?
To see what writers are available on your system use:
import matplotlib.animation as animation
print animation.writers.list()
You might need to write a new writer for what you want.
Edit
"FileWriters" from Matplotlib animation module seem to support only raster output. For FFMpegFileWriter() that's clear from documentation, and for FileMovieWriter() it can be derived if we initiate this class with unsupported format:
plt.rcParams['animation.frame_format'] = 'svg'
in which case Error is raised printing supported formats:
Unrecognized animation.frame_format string "'svg'": valid strings are
['rgba', 'tiff', 'jpeg', 'png', 'raw']
So Matplotlib animation module seems to work only with raster data.