OpenCV Face Recognition grayscale conversion error while training my classifier - python

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

Related

Scikit inpainting returning error: Input arrays have to be the same shape

I have the following two images. One is the original, and the other is the mask. I am attempting to use inpainting to REMOVE everything but the drawn writing on the page.
Image
Mask
I am using the following code to do this:
import cv2
from skimage.restoration import inpaint
image_orig = cv2.imread('R.jpg')
# Create mask with six block defect regions
mask = cv2.imread('InkedR.jpg')
image_result = inpaint.inpaint_biharmonic(image_orig, mask, channel_axis=-1)
I am returned the following error:
ValueError: Input arrays have to be the same shape
I have confirmed that both the image and the mask are the same shape by using:
image_orig. shape == mask.shape
and do not know what is causing this error.
I have tried to use different images, and also convert the images to black and white with no help.
You need to provide the function with a binary mask which can be achieved by extracting the mask from the provided images and then converting it to the binary scale.
Solution:
import cv2
import numpy as np
from skimage.restoration import inpaint_biharmonic
# Load Images
Original_Image = cv2.imread("2.png")
Color_Mask = cv2.imread("1.jpg")
# Subtract Mask
Sub_Mask = np.array(Color_Mask.astype(float)-Original_Image.astype(float))
Sub_Mask = np.float32(Sub_Mask/255).astype('uint8')
# Binary Mask
Mask = cv2.cvtColor(Sub_Mask, cv2.COLOR_BGR2GRAY)
# Apply Inpaint Biharmonic Function
Restored_Image = inpaint_biharmonic(Original_Image, Mask, channel_axis=-1)
# Display Images
cv2.imshow("Display - Mask", Mask)
cv2.imshow("Display - Restored Image", Restored_Image)
cv2.waitKey(0)
Output:
Mask Restored Image

Want to append colored images to a list and convert that list to grayscale using OpenCV

So basically I'm trying to convert a set of RGB images to grayscale using cv2.cvtColor and python is throwing the following error:
Traceback (most recent call last):
File "MCG.py", line 53, in
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
TypeError: src is not a numpy array, neither a scalar.
This here is the code:
import numpy as np
import cv2
import dlib
import sys
import skimage
from PIL import Image
import os
import glob
folderpath = sys.argv[1]
cascPath = sys.argv[2]
imageformat = ".tif"
path = folderpath
imfilelist = [os.path.join(path,f) for f in os.listdir(path) if f.endswith(imageformat)]
data = []
for IMG in imfilelist:
print IMG
image = cv2.imread(IMG)
data.append(image)
cv2.imshow('Image', image)
cv2.waitKey(0)
faceCascade = cv2.CascadeClassifier(cascPath)
predictor = dlib.shape_predictor(PREDICTOR_PATH)
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.05,
minNeighbors=5,
minSize=(100,100)
)
As you can see, I'm trying to append all these images to a list, which will then be converted using the cv2.cvtColor function. However, that error is thrown. What am I doing wrong? Thank you.
P.S if anyone is wondering why I imported modules that don't seem to be used in this code, this code is just a segment of the whole thing and all of those modules have are being utilized in one way or the other.
If you read the cv2.cvtColor documentation, you can see that the first parameter is the Src 8-bit single channel image. However, in your case you are giving an entire list of images.
So change the code as
gray = []
for j in range(0,len(data)):
gray.append(cv2.cvtColor(np.array(data[j]), cv2.COLOR_BGR2GRAY))
I guess this should work.
You are collecting the images into a list with
data = []
for IMG in imfilelist:
...
data.append(image)
....
and then trying to convert the list with
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
This is why you are getting the error - the error is telling you that data is not an image (numpy array) but is a list. You need to convert one image at a time with cv2.cvtColor().
You could try
gray = []
for img in data:
gray.append(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))
This would give you a list of greyscaled images, which is what I think you want to do.

Error in OpenCV color conversion from BGR to grayscale

I am trying to convert an image from BGR to grayscale format using this code:
img = cv2.imread('path//to//image//file')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
This seems to be working fine: I checked the data type of the img variable which turns out to be numpy ndarray and shape to be (100,80,3). However if I give an image of a native numpy ndarray data type with same dimensions of the input of the cvtColor function, it gives me the following error:
Error: Assertion failed (depth == 0 || depth == 2 || depth == 5) in cv::cvtColor, file D:\Build\OpenCV\opencv-3.4.1\modules\imgproc\src\color.cpp, line 11109
cv2.error: OpenCV(3.4.1) D:\Build\OpenCV\opencv-3.4.1\modules\imgproc\src\color.cpp:11109: error: (-215) depth == 0 || depth == 2 || depth == 5 in function cv::cvtColor
The code for the second case is (making a custom np.ndarray over here):
img = np.full((100,80,3), 12)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Can anyone clarify what is the reason for this error and how to rectify it?
This is because your numpy array is not made up of the right data type. By default makes an array of type np.int64 (64 bit), however, cv2.cvtColor() requires 8 bit (np.uint8) or 16 bit (np.uint16). To correct this change your np.full() function to include the data type:
img = np.full((100,80,3), 12, np.uint8)
It may be easier to initialize new numpy array with initial image as source and dtype=np.uint8:
import numpy as np
img = cv2.imread('path//to//image//file')
img = np.array(img, dtype=np.uint8)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
The error occured because the datatype of numpy array returned by cv2.imread is uint8, which is different from the datatype of numpy array returned by np.full(). To make the data-type as uint8, add the dtype parameter-
img = np.full((100,80,3), 12, dtype = np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imagine you have a function called preprocessing() that preprocess your images with cv2,
if you try to apply it as:
data = np.array(list(map(preprocessing,data)))
it won't work and that because np.array creates int64and you are trying to assign np.uint8 to it, what you should do instead is adding dtype parameter as follow:
data = np.array(list(map(preprocessing,data)), dtype = np.uint8)

openCV not accept numpy array?

I want to do a matchTemplate from a screenshot (with mss)
from mss import mss
import cv2
import numpy
with mss() as sct:
screenshot_numpy = numpy.array(sct.shot())
template = cv2.imread('./templates/player.png')
result = cv2.matchTemplate(screenshot_numpy,template,cv2.TM_CCOEFF_NORMED)
Error message:
Traceback (most recent call last):
File "main.py", line 14, in <module>
result = cv2.matchTemplate(screenshot_numpy,template,cv2.TM_CCOEFF_NORMED)
TypeError: image data type = 18 is not supported
From the mss examples page:
img = numpy.array(sct.grab(monitor))
So here we can see the .grab() method to get the raw pixel data from the image. In this case sct.grab() returns a PIL Image, and numpy.array(Image) will thus convert the PIL Image object into a numpy ndarray.
Check the numpy ndarray dtype after you convert; for e.g. if your code is ndarray_img = numpy.array(sct.grab()), then check ndarray_img.dtype. If it's np.uint8 then you're done. If it's np.uint16, then you'll have to divide by 256 and convert to np.uint8 with ndarray_img = (ndarray_img/255).astype(np.uint8).
Further down you'll see another example which flips the R and B channels of the image:
cv2.imshow(title, cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
except this is actually backwards. It really doesn't matter because either way it's just swapping the first and third channel, so BGR2RGB and RGB2BGR do exactly the same thing, but PIL (and other libraries) give you RGB order while you need BGR order to display with OpenCV, so technically it should be
cv2.imshow(title, cv2.cvtColor(img, cv2.COLOR_RGB2BGR))

OpenCV Python copying certain portion of image to another

I want to calculate the difference betwwn two images. I'm only interested in the difference value for a certain portion of image. For that i am copying the required portion of image to a temp images, and operating on those images. However using the pixel allocation using as specified on http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_core/py_basic_ops/py_basic_ops.html. Here it is given,
ball = img[280:340, 330:390]
img[273:333, 100:160] = ball
Using the similar logic, i have written a python program,
import cv2
import numpy as np
img_file = 'carparking2_1.jpg'
img = cv2.imread(img_file, cv2.IMREAD_COLOR)
img_withoutcar = 'carparking2_1.jpg'
img_withcar = 'carparking2.jpg'
img1 = img_withoutcar[47:151, 106:157]
img2 = img_withcar[47:151, 106:157]
diff1 = cv2.absdiff(img1, img2)
diff2 = cv2.absdiff(img1, img1)
print 'RGB shape: ', img.shape # Rows, cols, channels
print 'Difference with car and without: ', diff1
print 'Difference with car and with car: ', diff2
However, im getting the output message:
File "D:/Projects/IoT Smart Parking/differenceinframes.py", line 8, in <module>
img1 = img_withoutcar[47:151, 106:157]
TypeError: string indices must be integers, not tuple
I am running Python 2.7 with OpenCV 3.1.0 on Windows 10.
You are getting the error because your command is trying to slice the string 'carparking2_1.jpg' as if it were the image data.
#First assign the file names:
file_name_without_car='carparking2_1.jpg'
file_name_with_car='carparking2.jpg'
#load the images
img_withoutcar= cv2.imread(file_name_without_car, cv2.IMREAD_COLOR)
img_withcar= cv2.imread(file_name_with_car, cv2.IMREAD_COLOR)
#now you can slice regions of the images
#note that color images have a third dimension for color channel.
img1 = img_withoutcar[47:151, 106:157,:]
img2 = img_withcar[47:151, 106:157,:]

Categories