MNIST Matplotlib: showing color - matplotlib

I am exploring the MNIST dataset which is a collection of gray-scale handwritten digit images. I am using Matplotlib to plot random images from the dataset:
plt.subplot(221)
plt.imshow(X_train[1],cmap='gray')
plt.subplot(222)
plt.imshow(X_train[100])
plt.subplot(223)
plt.imshow(X_train[4559])
plt.subplot(224)
plt.imshow(X_train[50000])
plt.show()
My question is why the images are coming up as colored when I don't explicitly set cmap='gray'.
Shouldn't they all appear as grayscale images by default as that's their true nature?

This is because, by default, imshow() uses 'viridis' as cmap.

Related

Plotting xarray.DataArray and Geopandas together - aspect ratio errors

I am trying to create two images side by side: one satellite image alone, and next to it, the same satellite image with outlines of agricultural fields. My raster data "raster_clip" is loaded into rioxarray (original satellite image from NAIP, converted from .sid to .tif), and my vector data "ag_clip" is in geopandas. My code is as follows:
fig, (ax1, ax2) = plt.subplots(ncols = 2, figsize=(14,8))
raster_clip.plot.imshow(ax=ax1)
raster_clip.plot.imshow(ax=ax2)
ag_clip.boundary.plot(ax=ax1, color="yellow")
I can't seem to figure out how to get the y axes in each plot to be the same. When the vector data is excluded, then the two plots end up the same shape and size.
I have tried the following:
Setting sharey=True in the subplots method. Doesn't affect shape of resulting images, just removes the tic labels on the second image.
Setting "aspect='equal'" in the imshow method, leads to an error, which doesn't make sense because the 'aspect' kwarg is listed in the documentation for xarray.plot.imshow.
plt.imshow's 'aspect' kwarg is not available in xarray
Removing the "figsize" variable, doesn't affect the ratio of the two plots.
not entirely related to your question but i've used cartopy before for overlaying a GeoDataFrame to a DataArray
plt.figure(figsize=(16, 8))
ax = plt.subplot(projection=ccrs.PlateCarree())
ds.plot(ax=ax)
gdf.plot(ax=ax)

XGBoost plot_importance cannot show full feature names

I am running a XGboost regressor on a dataset, and finally plotting the feature importance.
because my feature names are long(20-60 characters), it "trims" their names in the saved image (on the left side of the image).
code:
from xgboost import plot_importance
import matplotlib.pyplot as plt
...
plot_importance(search.best_estimator_)
plt.savefig(f'{os.path.join(self.model_save_directory, "feature_importance.png")}')
I tried to set a wide image with:
plt.rcParams["figure.figsize"] = (28, 7)
Now there are more characters in the image of each feature, but not all. On the other hand, the height of the image has shrunk a lot.
Thanks
I was able to show the full feature names with:
plot_importance(search.best_estimator_, max_num_features=None)
plt.xticks(rotation=90)
plt.savefig(f'{os.path.join(self.model_save_directory, "feature_importance.png")}', bbox_inches='tight')

Blurry XGBClassifier tree plot

I have trained and XGBClassifier called model and then plot the tree as follows:
from xgboost import plot_tree
plot_tree(model); plt.show(dpi=1200)
The resulting plot is really blurry:
Does anyone know how to improve the quality of that plot?
I have tried to include dpi=1200 (see code above) but that doesn't make any difference.

Training a model to be biased to a given background

I am re-training an inception resnet v2 model to recognize a sequence of 3 digit numbers(of a particular font type).The sequence is artificially generated with black lettering on a white background. I am of the opinion that subjecting the model to see only a specific background will help me eliminate false detections(in this case any other 3 digit sequence not on a white background), as the model will not predict(high probabilities) for sequences whose backgrounds are not white.Is it a valid assumption to make?
PS:I have tried using tesseract previously to perform text extraction from an image. I used east text detector for detection, which gave me the bounding boxes for the text. I followed that with OCR using pytesseract, but it always returned an empty string. Furthermore, on rotating of the digits, east-text detector failed to recognize the rotated sequence of digits. I was hence left with no option but to train and perform text detection and extractiion using a Neural Network Model.
code for pytesseract:
import cv2
import numpy as np
import pytesseract
from pytesseract import image_to_string
from PIL import Image
refPt=[(486,302),(540,308),(538,328),(484,323)] #the bbox returned by east
refpt = np.array(refPt,dtype=np.int32)
roi_corners=np.array(refPt[0:4],np.int32).reshape((-1,1,2))
inp_img=cv2.imread("1.jpg")
mask = np.zeros(inp_img.shape, dtype=np.uint8)
channel_count = inp_img.shape[2]
ignore_mask_color = (255,)*channel_count
mask = cv2.fillPoly(mask, np.array(refPt[0:4],np.int32).reshape((-1,1,2))], ignore_mask_color)
masked_image = cv2.bitwise_and(inp_img, mask)
print (image_to_string(Image.fromarray(masked_image),lang='eng'))

Saving an imshow-like image while preserving resolution

I have an (n, m) array that I've been visualizing with matplotlib.pyplot.imshow. I'd like to save this data in some type of raster graphics file (e.g. a png) so that:
The colors are the ones shown with imshow
Each element of the underlying array is exactly one pixel in the saved image -- meaning that if the underlying array is (n, m) elements, the image is NxM pixels. (I'm not interested in interpolation='nearest' in imshow.)
There is nothing in the saved image except for the pixels corresponding to the data in the array. (I.e. there's no white space around the edges, axes, etc.)
How can I do this?
I've seen some code that can kind of do this by using interpolation='nearest' and forcing matplotlib to (grudgingly) turn off axes, whitespace, etc. However, there must be some way to do this more directly -- maybe with PIL? After all, I have the underlying data. If I can get an RGB value for each element of the underlying array, then I can save it with PIL. Is there some way to extract the RGB data from imshow? I can write my own code to map the array values to RGB values, but I don't want to reinvent the wheel, since that functionality already exists in matplotlib.
As you already guessed there is no need to create a figure. You basically need three steps. Normalize your data, apply the colormap, save the image. matplotlib provides all the necessary functionality:
import numpy as np
import matplotlib.pyplot as plt
# some data (512x512)
import scipy.misc
data = scipy.misc.lena()
# a colormap and a normalization instance
cmap = plt.cm.jet
norm = plt.Normalize(vmin=data.min(), vmax=data.max())
# map the normalized data to colors
# image is now RGBA (512x512x4)
image = cmap(norm(data))
# save the image
plt.imsave('test.png', image)
While the code above explains the single steps, you can also let imsave do all three steps (similar to imshow):
plt.imsave('test.png', data, cmap=cmap)
Result (test.png):