Converting a list to np array - python

Im building a image classification model but first i need to read the images used for training and i have 105,392 images, so i read the local images i have downloaded with cv2.imread_grayscale and resized the image to 100x100
train_images = []
img_array = cv2.imread(os.path.join(path,str(train_data.filename[idx])), cv2.IMREAD_GRAYSCALE)
new_array = cv2.resize(img_array,(img_size,img_size))
train_images.append(new_array)
then i add the image data into a list then converted them into nparray and tried to flatten them to 1 dimension so i can save into a text file for easier processing
ndarray = np.array(train_images)
ndarray2 = np.ndarray(ndarray)
flattenarray = ndarray2.flatten(order='C')
flattenarray.tofile('train_images_bitmap.txt')
but im getting this error
Traceback (most recent call last):
File "comp2.py", line 36, in <module>
ndarray2 = np.ndarray(ndarray)
ValueError: maximum supported dimension for an ndarray is 32, found 105392
Any help is appreciated !!

Your array of ndarray has shape of (105392,100,100) to flatten this array.
flatten_array = ndarray.reshape(1,105392*100*100)

Related

Python Pillow Image.load() method has limitations?

I'm trying to do some image processing in python.
I'm using Pillow 8.4.0 for this purpose and I need to work on individual pixels (here I'm just trying to save pixels in a text file), therefore I'm trying to use Image.load() method and looping over it but it is throwing IndexError: image index out of range
Is there a limitation in Image.load() function that is preventing me to do this?
from PIL import Image
with Image.open('nature.jpg') as img:
print("Image size is : " ,img.size)
pixels = img.load()
with open('file.txt', 'w') as file:
for row in range(img.height):
for col in range(img.width):
file.write(str(pixels[row, col])+ ' ')
file.write('\n')
Output is:
Image size is : (1024, 768)
Traceback (most recent call last):
File "main.py", line 13, in <module>
file.write(str(pixels[row, col])+ ' ')
IndexError: image index out of range
Pillow expects (x,y) rather than (y,x). Please try following:
from PIL import Image
img = Image.open('nature.jpg')
pixels = img.load()
print(pixels[img.width-1,img.height-1]) # does provide tuple describing pixel
print(pixels[img.height-1,img.width-1]) # IndexError for non-square image

OpenCV Face Recognition grayscale conversion error while training my classifier

import numpy as np
import cv2
from skimage.io import imread_collection
dataset = r'C:\Users\JasonPC\Documents\CodeVault\Python\FaceRecognition\dataset\*.jpg' # path for images
List = imread_collection(dataset)
faces_list = np.array(List)
def classifier_trainer(faces_list):
img_id = 0
faces = []
faceID = []
for face in np.nditer(faces_list):
gray_face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY) # coverting color image to gray scale
np_face = np.array(gray_face, 'uint8') # converting gray image into numpy array
img_id += 1
faces.append(np_face)
faceID.append(img_id)
faceID = np.array(faceID)
classifier = cv2.face.LBPHFaceRecognizer_create()
classifier.train(faces, faceID)
classifier.write('Classifier.yml')
classifier_trainer(faces_list)
I'm trying to train a classifier to recognize my face. I'm stuck with this really huge error.
Traceback (most recent call last):
File "c:/Users/JasonPC/Documents/CodeVault/Python/FaceRecognition/trainer.py", line 26, in <module>
classifier_trainer(faces_list)
File "c:/Users/JasonPC/Documents/CodeVault/Python/FaceRecognition/trainer.py", line 15, in classifier_trainer
gray_face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY) #
coverting color image to gray scale
cv2.error: OpenCV(4.2.0) c:\projects\opencv-python\opencv\modules\imgproc\src\color.simd_helpers.hpp:92: error: (-2:Unspecified error) in function '__thiscall cv::impl::`anonymous-namespace'::CvtHelper<struct cv::impl::`anonymous namespace'::Set<3,4,-1>,struct cv::impl::A0xe227985e::Set<1,-1,-1>,struct cv::impl::A0xe227985e::Set<0,2,5>,2>::CvtHelper(const class cv::_InputArray &,const class cv::_OutputArray &,int)'
> Invalid number of channels in input image:
> 'VScn::contains(scn)'
> where
> 'scn' is 1
All I want my code to do is seek the images from the numpy array i.e face_list and convert it to grayscale and append it to a list called faces
The problem is in how you're iterating over your images. You're using nditer and in your case as it turns out it flattens the n dimensional array to say 1 dimensional and then iterates over all of it's elements. Think of it as a way of iterating over all elements of an n dimensional array without n nested loops. So here, the face variable in your loop is an integer, float or whatever numerical value and you're passing it to cvtColor and getting this error message.
If you want to iterate over the images I think, you can just iterate over them like this:
for face in faces_list:
# your code goes here

Plot a Numpy Array with (1, 2208, 2752, 3) Dimensions

I have a microscopy array and I want to plot them.
The shape is:
(1, 2208, 2752, 3)
And Im triying it to plot with the following code:
from PIL import Image
im = Image.fromarray(image_array)
im.show()
And get this error:
Traceback (most recent call last):
File "/Users/x/anaconda3/envs/x/lib/python3.6/site-packages/PIL/Image.py", line 2515, in fromarray
mode, rawmode = _fromarray_typemap[typekey]
KeyError: ((1, 1, 2752, 3), '|u1')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/x/Desktop/x/x/test.py", line 21, in <module>
im = Image.fromarray(image_arrays)
File "/Users/x/x/x/x/lib/python3.6/site-packages/PIL/Image.py", line 2517, in fromarray
raise TypeError("Cannot handle this data type")
TypeError: Cannot handle this data type
If I resize the array to (2000,2000,3) this working, but with the 1 in the first dimension I have no Idea how can this work. The filetype is .czi and its a normal image.
You need a x by y by (r,g,b) matrix to display an image. You seem to have a fourth dimension on your matrix, so I'm guessing whatever routine you are using to create the array is actually creating an array of images.
Since you only have one image, you can just remove the first axis using image_array = numpy.squeeze(image_array, axis=0) This returns just the one image array in shape (2208, 2752, 3). Alternately, you can do: im = Image.fromarray(image_array[0])
from PIL import Image
image_array = numpy.squeeze(image_array, axis=0)
im = Image.fromarray(image_array)
im.show()

Can't reshape the numpy array containing PNG images

I've trained a Handwritten image classifier using Keras library in Python. Initially I've used standard MNIST dataset for training and testing purpose. But now I want to use my own data set for testing, in which all the images are size 900*1200*3 instead of 28*28*1
So I need to reshape all the images before testing. I'm using following code to reshape but it give errors.
Code:
bb = lol.reshape(lol.shape[0], 28, 28, 1).astype('float32')
where lol is my numpy array containing 55 images of shape (900,1200,3)
and the Error log is as following:
ValueError Traceback (most recent call last)
<ipython-input-46-87da95da73e9> in <module>()
24 # # you can show every image
25 # img.show()
---> 26 bb = lol.reshape(lol.shape[0], 28, 28, 1).astype('float32')
27 # model = loaded_model
28 # classes = model.predict(bb)
ValueError: cannot reshape array of size 178200000 into shape (55,28,28,1)
So what am I doing wrong? Can I get accurate predictions even after resizing the large images to very small images of 28*28? Thanks for help.
What you are doing is wrong. You can't reshape an array of (55, 900, 1200, 3) into an array of (55, 28, 28, 1), because you are trying to store 55*900*1200*3=178200000 elements in an array that can store only 55*28*28=43120 elements.
You want to do two things:
1) Convert your rgb image (indicated by the last dimension which is the 3 channels) into grayscale (1 channel). The simplest way to do this is (R+B+G)/3. All python libraries that have to do with images (PIL, OpenCV, skimage, tensorflow, keras, etc) have this already implemented. Example:
from skimage.color import rgb2gray
gray = rgb2gray(original)
2) Resize the image from 900x1200 to 28x28. Again you can do this in all major image-related python libraries. Example:
from skimage.transform import resize
resized = resize(gray, (28,28))
Now if you want to do this in all 55 images you can either write a function that transforms one image and map it across your array, or use a simple for loop and populate your new array one image at a time.
In your case the code should look something like this:
num_images = lol.shape[0] # 55 in your case
resized_images = np.zeros(shape=(num_images, 28, 28, 1)) # your final array
for i in range(num_images):
gray = rgb2gray(lol[i,:,:,:]) # gray.shape should be (900,1200,1)
resized = resize(gray, (28,28)) # resized.shape should be (28,28,1)
resized_images[i,:,:,:] = resized # resized_images.shape should be (55,28,28,1)
It would be more intuitive to process each image individually, which would also give you the best chance of preserving some information.
Try using the PIL library:
import numpy
from PIL import Image
lol = numpy.zeros((55,900,1200,3),dtype=numpy.uint8)
new_array = numpy.zeros((lol.shape[0],28,28),dtype=numpy.float32)
for i in range(lol.shape[0]):
img = Image.fromarray(lol[i])
img_resize = img.resize((28,28))
img_mono = img_resize.convert('L')
arr = numpy.array(img_mono,dtype=numpy.uint8)
new_array[i] = arr

Copy a image on a new larger image

I have a color image sourceImage and I would copy this image on a new larger color image destImage: the source image should be centered over the new image. In order to perform this procedure, I wrote the following code:
destHeight: the height of the new larger image
destWidth: the width of the new larger image
sourceFilename: the path of the source image
sourceImage = cv2.imread(sourceFilename,1)
imgHeight, imgWidth, imgChannels = sourceImage.shape[:3]
#print sourceImage.shape[:3]
destImage = np.zeros((destHeight,destWidth,imgChannels), np.uint8)
#print destImage.shape[:3]
yBorder = (destHeight-imgHeight)/2
xBorder = (destWidth-imgWidth)/2
#print yBorder, xBorder
destImage[yBorder:imgHeight,xBorder:imgWidth] = sourceImage
cv2.imshow('dst', destImage)
cv2.waitKey(0)
But when I run the script, the python interpreter displays the following error:
Traceback (most recent call last):
File "examples.py", line 30, in <module>
destImage[yBorder:imgHeight,xBorder:imgWidth] = sourceImage
ValueError: shape mismatch: objects cannot be broadcast to a single shape
What is the reason for this error? How to solve it?
Try this:
destImage[yBorder:yBorder + imgHeight,xBorder:xBorder + imgWidth] = sourceImage
The slice syntax is start:stop, not start:width.

Categories