Expand Sklearn digit size fom 8*8 to 32*32 - python

I have an issue with expanding the size of the Sklearn digit dataset digits from 8*8 to 32*32 pixels.
My approach is to take the 8*8 array and then flatten and expand it. That is, enlarge from 64 to 1024 pixels in total. Therefore I simply want to multiply the values along each row 16 times:
create a new array (=newfeatures) with 1024 NaN values.
Replace every 16. value of the newfeatures array with the values of the original array, that is (0=0),(16=1),(32=2),(...),(1008=64).
3.Replace the remaining NaN values with dropna(ffill) to "expand" the original image to a 32*32 pixels image.
Therefore I use the following code:
#Load in the training dataset
digits=datasets.load_digits()
features=digits.data
targets=digits.target
#Plot original digit
ax[0].imshow(features[0].reshape((8,8)))
#Expand 8*8 image to a 32*32 image (64 to 1024)
newfeatures=np.ndarray((1797,16*len(features[0])))
newfeatures[:]=np.NaN
newfeatures=pd.DataFrame(newfeatures)
for row in range(1797):
for i in range(0,63):
newfeatures.iloc[row,16*i]=features[row][i]
newfeatures.fillna(method="ffill",axis=1,inplace=True)
#Plot expanded image with 32*32 pixels
ax[1].imshow(newfeatures.values[0].reshape((32,32)))
As you can see, the result is not as expected

you can use skimage's resize as shown below
from skimage import transform
new_features = np.array(list
(map
(lambda img: transform.resize(
img.reshape(8,8),#old shape
(32, 32), #new shape
mode='constant',
#flatten the resized image
preserve_range=True).ravel(),
features)))
new_features shape will be (1797, 1024) and displaying the first image will show

Based on the above solution I think the following is a little bit more neater way:
from skimage import transform
newfeatures=[transform.resize(features[i].reshape(8,8),(32,32))for i in
range(len(features))]
plt.imshow(newfeatures[0].reshape((32,32)))

Related

Reshape 4D Numpy Image data

I had 4 RGB images in an array of shape (4,32,32,3). Then I divided these images in 16 equal 8x8 blocks (64 represents the 8x8 block), decoded_imgs.shape = (4,16,64,3) , 3 represents the colour channels. After some processing now I want to reshape them again as (4,32,32,3) by placing each block to its original location. I have tried by using reshape function but it destroys the image data.
data_new = decoded_imgs.transpose(0,2,1,3).reshape(4,32,32,3)

TensorFlow Dataset adding tiled images to batch dimension

If I have a dataset of images which I have created into tiles what is the best way to combine the tile dimension with the batch dimension?
For example my input files are of shape (300,300,3) a typical RGB image with 300x300 pixels.
I do preprocessing and create a tile dataset which creates a new shape: (?,100,128,128,3)
So I have create 100 tiles of size 30x30 from the original image, and reshaped each tile to 128x128 pixels and then cached the dataset and created a batch with dimension ?.
Now I want to combine the tiles into the batch dimension and get a shape of: (?,128,128,3)
I've tried mapping the dataset to this function:
def reshape_image(image_batch):
return tf.reshape(image_batch, (-1,128,128,3))
But this doesn't seem to be working as it is causing the iterator to hang on this call:
image_test = next(iter(image_ds))
As I thought, the answer was fairly simple if you are familiar with the Tensorflow operations, hopefully this question wasn't too confusing and it helps someone out there.
#load/preprocess images from paths
image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE)
#split images into tiles so (X,Y,C) -> (N,X,Y,C) where N is the number of tiles
image_ds = image_ds.map(split_image, num_parallel_calls=AUTOTUNE)
#resize tiled images from 30x30 to 128x128, implementation doesn't really matter
image_ds = image_ds.map(resize_image, num_parallel_calls=AUTOTUNE)
#finally the answer!! use 'flat_map', 'unstack', and 'from_tensor_slices'
#tiled_images is of shape (N,X,Y,C)
def flat_map_impl(tiled_images):
#You return a new Dataset
#Unstack by default creates a list of tensors based on the first dimension
#therefore tf.unstack(tiled_images) is a list of size N with (X,Y,C) shaped elements
#finally from_tensor_slices creates a new dataset where each element is of shape (X,Y,C)
return tf.data.Dataset.from_tensor_slices(tf.unstack(tiled_images))
#call flat_map_impl with flat_map on the dataset
image_ds = image_ds.flat_map(flat_map_impl)

Subtract 2D array from 4D array

I have a greyscale image, represented by a 2D array of integers, shape (1000, 1000).
I then use sklearn.feature_extraction.image.extract_patches_2d() to generate an array of 3x3 'patches' from this image, resulting in an array of shape (1000000, 3, 3), as there are 1 million 3x3 arrays for each pixel value in the original image.
I reshape this to (1000, 1000, 3, 3), which is a 1000x1000 array of 3x3 arrays, one 3x3 array for each pixel in the original image.
I now want to effectively subtract the 2D array from the 4D array. I have already found a method to do this, but I would like to make one using vectorisation.
I currently iterate through each pixel and subtract the value there from the 3x3 array at the same index. This is a little bit slow.
This is what currently loads images, formats the arrays before hand, and then performs this subtraction.
from PIL import Image, ImageOps
from skimage import io
from sklearn.feature_extraction import image
import numpy
jitter = 1
patchsize = (jitter*2)+1
#load image as greyscale image using PIL
original = load_image_greyscale(filename)
#create a padded version of the image so that 1000x1000 patches are made
#instead of 998x998
padded = numpy.asarray(ImageOps.expand(original,jitter))
#extract these 3x3 patches using sklearn
patches = image.extract_patches_2d(padded,(patchsize,patchsize))
#convert image to numpy array
pixel_array = numpy.asarray(original)
#then reshape the array of patches so it matches array_image
patch_array = numpy.reshape(patches, (pixel_array.shape[0],pixel_array.shape[1],patchsize,patchsize))
#create a copy for results
patch_array_copy = numpy.copy(patch_array)
#iterate over each 3x3 array in the patch array and subtract the pixel value
#at the same index in the pixel array
for x in range(pixel_array.shape[0]):
for y in range(pixel_array.shape[1]):
patch_array_copy[x,y] = patch_array[x,y] - pixel_array[x,y]
I would like a way to perform the final step in the for loop using matrix operations.
I would also like to extend this at some point to work with RGB images, effectively making it a subtraction of an array with shape(1000,1000,3) from an array with shape(1000,1000,3,3,3). But i'm trying to go one step at a time here.
Any help or tips or suggestions or links to helpful resources would be greatly appreciated.

How to reshape an matrix of grayscale images in Numpy?

I have a numpy matrix of images with shape (50, 17500). Each image has shape (50, 50), so my matrix is like a long row of 350 grayscale images.
I want to use plt.imshow() to display those images. How do I change the dimension of the concatenated images matrix? Say reshaping the array to shape (1750, 500), which is 35 rows and 10 columns of images.
Some posts suggest to use np.reshape(), but if I use my_array.reshape((1750, 500)) the individual image in the new matrix is broken.
My question is how to reshape while preserving each individual (50,50) image?

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