How do I format a dataset for training in Python? - python

How do I format a dataset for training in Python?
I have 3000 grayscale BMP images of some handwritten digits (just like MNIST). Now I want to train my model with this dataset (I am using the Keras library) and I am using a convolution neural network for training.
I am using this code to convert one of the images into array
`import numpy
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
img = Image.open(open('CMATERdb 3.3.1\Ad02599.bmp')).convert("L")
print(img.format, img.size, img.mode)
img = numpy.asarray(img) / 255.
imgplot = plt.imshow(img)`
and the result from the code was
None (32, 32) L
image from the 3000 image want to convert into dataset
Any help how I can convert all images and put them in the same MNIST datast format that will be highly appreciated.

You can use any library that loads image files into arrays, such as Pillow.
Read Pillow's documentation to learn how to load an image file into an array.
Then, you should usually scale the array into values between 0 and 1. Usually, you just divide the image array by 255 (because they are RGB values between 0 and 255).
Be sure to end up with an array shaped like this: (3000, width, heigth, channels), where channels is usually 3 (Red, green, blue).

Related

How can I take generate mean image of many 32x32 grayscale images in Python?

I have array are which is 50000x32x32. arr[i] stores the i-th grayscale image.
I want to compute the mean image of these images. I tried the following code(I got this code from stack overflow itself). This code was actually meant for RGB images.
I know, these changes of mine have a lot of mistakes, Apologies.
import os, numpy, PIL
from PIL import Image
# Access all PNG files in directory
allfiles=os.listdir(os.getcwd())
imlist=arr
N=len(imlist)
# Assuming all images are the same size, get dimensions of first image
w,h=Image.fromarray(imlist[0]).size
# Create a numpy array of floats to store the average (assume RGB images)
brr=numpy.zeros((h,w),numpy.float)
# Build up average pixel intensities, casting each image as an array of floats
for im in imlist:
imarr=numpy.array(Image.fromarray(im),dtype=numpy.float)
brr=brr+imarr/N
# Round values in array and cast as 8-bit integer
brr=numpy.array(numpy.round(arr),dtype=numpy.uint8)
# Generate, save and preview final image
out=Image.fromarray(brr,mode="L")
out.save("Average.png")
out.show()
Once you have your 5000 × 32 × 32 array, you can compute the mean image by using np.mean() with axis=0 (the first axis, which contains the collection of images). Let's make some random data:
import numpy as np
images = np.random.random((5000, 32, 32))
Now we can compute the mean image:
mean_image = images.mean(axis=0)
We can look at it with:
import matplotlib.pyplot as plt
plt.imshow(mean_image)
Which looks something like:

np.reshape(): Converting an image into a feature array based on rgb intensities

I am trying to segment a colour image using the Mean-Shift algorithm using sklearn.
I have the following code:
import numpy as np
from sklearn.cluster import MeanShift, estimate_bandwidth
from sklearn.datasets.samples_generator import make_blobs
import matplotlib.pyplot as plt
from itertools import cycle
from PIL import Image
image = Image.open('sample_images/fruit_half.png')
image = np.array(image)
#need to convert image into feature array based on rgb intensities
flat_image = np.reshape(image, [-1,3])
I am trying to convert the image into a feature array based on rgb intensities so that I can do the clustering.
However, I get the following error:
ValueError: cannot reshape array of size 3979976 into shape (3)
I am not sure why I am getting this error and how I can resolve this. Any insights are appreciated.
It's because the image you're loading does not have RGB values (if you look at the dimensions, the last one is 4.
You need to first convert it to RGB like this:
image = Image.open('sample_images/fruit_half.png').convert('RGB')
image = np.array(image)
# Now it works
flat_image = np.reshape(image, [-1,3])

How to convert a RGB image (3 channel) to grayscale (1 channel) and save it?

Working with a deep learning project and I have a lot of images, that don't need to have colors. I saved them doing:
import matplotlib.pyplot as plt
plt.imsave('image.png', image, format='png', cmap='gray')
However later when I checked the shape of the image the result is:
import cv2
img_rgb = cv2.imread('image.png')
print(img_rgb.shape)
(196,256,3)
So even though the image I view is in grayscale, I still have 3 color channels. I realized I had to do some algebric operations in order to convert those 3 channels into 1 single channel.
I have tried the methods described on the thread "How can I convert an RGB image into grayscale in Python?" but I'm confused.
For example, when to do the conversion using:
from skimage import color
from skimage import io
img_gray = color.rgb2gray(io.imread('image.png'))
plt.imsave('image_gray.png', img_gray, format='png')
However when I load the new image and check its shape:
img_gr = cv2.imread('image_gray.png')
print(img_gr.shape)
(196,256,3)
I tried the other methods on that thread but the results are the same. My goal is to have images with a (196,256,1) shape, given how much less computationally intensive it will be for a Convolutional Neural Network.
Any help would be appreciated.
Your first code block:
import matplotlib.pyplot as plt
plt.imsave('image.png', image, format='png', cmap='gray')
This is saving the image as RGB, because cmap='gray' is ignored when supplying RGB data to imsave (see pyplot docs).
You can convert your data into grayscale by taking the average of the three bands, either using color.rgb2gray as you have, or I tend to use numpy:
import numpy as np
from matplotlib import pyplot as plt
import cv2
img_rgb = np.random.rand(196,256,3)
print('RGB image shape:', img_rgb.shape)
img_gray = np.mean(img_rgb, axis=2)
print('Grayscale image shape:', img_gray.shape)
Output:
RGB image shape: (196, 256, 3)
Grayscale image shape: (196, 256)
img_gray is now the correct shape, however if you save it using plt.imsave, it will still write three bands, with R == G == B for each pixel. This is because, I believe, a PNG file requires three (or four) bands. Warning: I am not sure about this: I expect to be corrected.
plt.imsave('image_gray.png', img_gray, format='png')
new_img = cv2.imread('image_gray.png')
print('Loaded image shape:', new_img.shape)
Output:
Loaded image shape: (196, 256, 3)
One way to avoid this is to save the images as numpy files, or indeed to save a batch of images as numpy files:
np.save('np_image.npy', img_gray)
new_np = np.load('np_image.npy')
print('new_np shape:', new_np.shape)
Output:
new_np shape: (196, 256)
The other thing you could do is save the grayscale png (using imsave) but then only read in the first band:
finalimg = cv2.imread('image_gray.png',0)
print('finalimg image shape:', finalimg.shape)
Output:
finalimg image shape: (196, 256)
As it turns out, Keras, the deep-learning library I'm using has its own method of converting images to a single color channel (grayscale) in its image pre-processing step.
When using the ImageDataGenerator class the flow_from_directory method takes the color_mode argument. Setting color_mode = "grayscale" will automatically convert the PNG into a single color channel!
https://keras.io/preprocessing/image/#imagedatagenerator-methods
Hope this helps someone in the future.
if you want to just add extra channels that have the same value as the graysacale , maybe to use a specific model that requires 3 channel input_shape .
lets say your pictures are 28 X 28 and so you have a shape of (28 , 28 , 1)
def add_extra_channels_to_pic(pic):
if pic.shape == (28 , 28 , 1):
pic = pic.reshape(28,28)
pic = np.array([pic , pic , pic])
# to make the channel axis in the end
pic = np.moveaxis(pic , 0 , -1)
return pic
Try this method
import imageio
new_data = imageio.imread("file_path", as_gray =True)
imageio.imsave("file_path", new_data)
The optional argument "as_gray = True" in line 2 of the code does the actual conversion.

(Loading .mat file as image in OpenCV) - Reshaping numpy array with 128 channels to 3 channels

I am trying to load .mat image exported from Tensorflow with Scipy.io using OpenCV.
I can modify the Tensorflow code to export the .mat image with only 3 channels directly but I will lose a lot of data and it doesn't look correct even.
And that's why I am trying to export the raw data as it is.
In my case I load the .mat file with scipy.io and get the numpy array which looks like this
(640, 640, 128)
and I want to reshape it because OpenCV cannot load an image with 128 channels.
(640, 640, 3)
I am not fully understanding the concept of reshaping and I think I am doing it wrong.
I am getting this error:
ValueError: cannot reshape array of size 52428800 into shape
(640,640,3)
Thank you and have a good day,
Hesham
Edit 1:
That's the code:
import cv2
import scipy.io as sio
import numpy as np
matfile = 'docia.mat'
img = sio.loadmat(matfile)
img_reshaped = img['embedmap'].reshape(640, 640, 3)
cv2.imshow("segmented_map", img['embedmap'])
cv2.waitKey(0)`
Re-shaping is using when you want to retain all of the data but in a different shape. I believe that you are trying to drop 125 of the 128 channels. To do this you can just use indexing to get the first 3 channels:
img_reshaped = img['embedmap'][:, :, :3]
Also you are passing img['embedmap'], not the reshaped img_reshaped into cv2.imshow().
Although I would recommend looking at them 1 by 1 in grey scale.
for i in range(128):
cv2.imshow("segmented_map", img['embedmap'][:, :, i])
cv2.waitKey(0)

Build the feature matrix and label vector:

I have a dataset “Digit” . The dataset includes 1797 small images (8x8 pixels), each one includes a hand-written digit (0-9). Each image is considered as a data sample with pixels as features. Thus, to build the feature table you have to convert each 8x8 image into a row of the feature matrix with 64 feature columns for 64 pixels. How to build a feature matrix and label vector for it ???
You can follow the scikit-learn tutorial on supervised learning, where they are using the Digit dataset
http://scikit-learn.org/stable/tutorial/basic/tutorial.html#loading-an-example-dataset
with more detail here. If you load the dataset as in the example, you can simple reshape the images:
from sklearn import datasets
digits = datasets.load_digits()
# To apply a classifier on this data, we need to flatten the image, to
# turn the data in a (samples, feature) matrix:
n_samples = len(digits.images)
data = digits.images.reshape((n_samples, -1))
This makes data a 2D matrix, with n_samples rows and as many columns as needed to fit the flattened image.
If you're using numpy and cv2 you can do the following:
import numpy as np
import cv2
fname = "image1.jpg"
image = cv2.imread(fname) # (8, 8, 1)
feature = image.reshape(64) # (64,)
to read a bunch of images and load into a 'feature matrix' (a numpy array) you can do the following:
N = 10 # number of images
data = np.zeros((N, 64))
for index in range(N):
# get the current image and convert to feature, as above
data[index] = np.copy(feature)
Each row of your data matrix is now one example (a 64 dim list of features).
Does this help?
The label vector can just be a 1D numpy array, i.e. labels = np.zeros(N)
EDIT:
There are a number of ways to read images:
(1) img = cv2.imread(filename)
(2) using matplotlib:
import matplotlib.image as mpimg
img = mpimg.imread(filename)
(3) using PIL (or PILLOW):
from PIL import Image
img = Image.open(filename)
It pays to check the shape of the image after it has been read, so that you know it is in the correct channel, width, height order that is appropriate for your application.

Categories

Resources