Reading a 4 band image with rasterio - python

I am trying to view a tif satellite image which has 4 bands. I want to remove the last band (NIR) and view the RGB image only, so I am trying to split the NIR from the rest of the image. Here is my code
import rasterio
from rasterio.plot import show
from matplotlib import pyplot as plt
from rasterio import plot
import numpy as np
#to display RGB
dataset = rasterio.open('2.tif')
%matplotlib inline
plot.show(dataset.read([1,2,3]), cmap="gray")
#to display just the red band
%matplotlib inline
plot.show(dataset.read(4), cmap="gray")
I provided a screen shot of the code and the output I am getting
Displaying just 1 band seems fine, but any idea why I keep seeing an image with a yellow and white color scheme when I try to display RGB bands together? I thought it's a cmap issue at the beginning, but even when I add 'cmap="gray"' the color of the image remains the same.

Related

Rendering grayscale image

Using this code :
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
plt.imshow(cv2.imread('badger.jpeg' , cv2.IMREAD_GRAYSCALE))
an image is read as greyscale and plotted to screen.
The image is plotted as :
This does not appear to be grayscale as there is colour that does not range form white to grey contained in the rendered image ?
My code is correct to read the image as grayscale using the IMREAD_GRAYSCALE parameter ?
The image is located at : https://sciencing.com/difference-between-badger-wolverine-8645505.html
The image is indeed flattened to grayscale if you use cv2.IMREAD_GRAYSCALE (you can test this using cv2.imread('im.jpg', cv2.IMREAD_GRAYSCALE).shape and cv2.imread('im.jpg').shape, and see that the former is a 3-d array and the latter is a 2-d array)
The issue is with the way matplotlib chooses to map your pixel values. When using plt.imshow(), it is using the default colormap (which is viridis, for some reason). This means pixel intensities / values will be mapped to the following:
You can change cmap to gray, in order to map them to the following:
plt.imshow(cv2.imread('badger.jpeg', cv2.IMREAD_GRAYSCALE), cmap='gray')
plt.show()

Concatenated images are badly degraded

I am trying to display several pictures on my Jupyter notebook. However, the pixel is really rough like below.
The pixel of original picture is clear. How should I improve this issue ?
This is a certain point of process to have a classification whether the picture is dog or cat. I have a many pictures of dogs and cat in the folder located on same directory and just took them from there. The picture is I just tried to show on the Jupyter notebook with using matplotlib.
Thank you in advance.
To force the resolution of the matplotlib inline images:
import matplotlib as plt
dpi = 300 # Recommended to set between 150-300 for quality image preview
plt.rcParams['figure.dpi'] = dpi
I think it uses a very low setting around 80 dpi by default.
The image quality seems to be degraded in the example picture simply because you are trying to show a 64 pixel large image on 400 pixels or so on screen. Each original pixel thus comprises several pixels on screen.
It seems you do not necessarily want to use matplotlib at all if the aim is to simply show the image in its original size on screen.
%matplotlib inline
import numpy as np
from IPython import display
from PIL import Image
a = np.random.rand(64,64,3)
b = np.random.rand(64,64,3)
c = (np.concatenate((a,b), axis=1)*255).astype(np.uint8)
display.display(Image.fromarray(c))
To achieve a similar result with matplotlib, you need to crop the margin around the axes and make sure the figure size is exactly the size of the array to show.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
a = np.random.rand(64,64,3)
b = np.random.rand(64,64,3)
c = np.concatenate((a,b), axis=1)
fig, ax = plt.subplots(figsize=(c.shape[1]/100.,c.shape[0]/100.), dpi=100)
fig.subplots_adjust(0,0,1,1)
ax.axis("off")
_ = ax.imshow(c)

Display x,y coordinates for loaded image file

I need to load an image file with matplotlib and see the coordinates of points within it, as if it were a simple x,y scatter plot.
I can assume that the x axis extension is [0, 1], and the y axis follows the same scaling. I can load the above image file with
from PIL import Image
im = Image.open("del.png")
im.show()
but this uses ImageMagick (I'm on a Linux system) to display the image, and no coordinates are shown in the bottom left part of the plot window as would for a simple data plot:
Use pyplot for that:
from matplotlib import pyplot as plt
plt.imshow(plt.imread('del.png'))

Python PIL cut off my 16-bit grayscale image at 8-bit

I'm working on an python program to display images of stars. The images are 16-bit grayscale tiffs.
If I try to display them in an extern program, e.g. ImageMagick they are correct but if I load them in python and then use 'show()' or implement them in a canvas in Tkinter they are, unless a few pixel, totally white.
So I estimate python sets every pixel above 255 to white but I don't know why. If I load the image and then save it as tiff again, ImageMagick can show it correct.
Thanks for help.
Try to convert the image to a numpy array and display that:
import Image
import matplotlib.pyplot as plt
import numpy as np
img = Image.open('image.tiff')
arr = np.asarray(img.getdata()).reshape(img.size[1], img.size[0])
plt.imshow(arr)
plt.show()
You can change the color mapping too:
from matplotlib import cm
plt.imshow(arr, cmap=cm.gray)

Invert colors when plotting a PNG file using matplotlib

I'm trying to display a PNG file using matplotlib and of course, python. For this test, I've generated the following image:
Now, I load and transform the image into a multidimensional numpy matrix:
import numpy as np
import cv2
from matplotlib import pyplot as plt
cube = cv2.imread('Graphics/Display.png')
plt.imshow(cube)
plt.ion()
When I try to plot that image in matplotlib, the colors are inverted:
If the matrix does not have any modifications, why the colors in the plot are wrong?
Thanks in advance.
It appears that you may somehow have RGB switched with BGR. Notice that your greens are retained but all the blues turned to red. If cube has shape (M,N,3), try swapping cube[:,:,0] with cube[:,:,2]. You can do that with numpy like so:
rgb = numpy.fliplr(cube.reshape(-1,3)).reshape(cube.shape)
From the OpenCV documentation:
Note: In the case of color images, the decoded images will have the
channels stored in B G R order.
Try:
plt.imshow(cv2.cvtColor(cube, cv2.COLOR_BGR2RGB))
As others have pointed out, the problem is that numpy arrays are in BGR format, but matplotlib expects the arrays to be ordered in a different way.
You are looking for scipy.misc.toimage:
import scipy.misc
rgb = scipy.misc.toimage(cube)
Alternatively, you can use scipy.misc.imshow().
Color image loaded by OpenCV is in BGR mode. However, Matplotlib displays in RGB mode.
So we need to convert the image from BGR to RGB:
plt.imshow(cv2.cvtColor(cube, cv2.COLOR_BGR2RGB))

Categories

Resources