Passing an image as an argument to a function in python - python

How can I create a function that takes an image file (not image filename) in python. Simply, like the following:
FaceController.py
import cv2
from Computer_Vision import Face_Detector as FD
def detectface():
img = cv2.imread('DSC_1902.JPG')
FD.detect(img)
detectface()
Face_Detector.py
import cv2
def detect(img):
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
cv2.namedWindow('img',cv2.WINDOW_NORMAL)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('messigray.png', img)
return img
Error:
OpenCV Error: Assertion failed (!empty()) in cv::CascadeClassifier::detectMultiScale, file C:\projects\opencv-python\opencv\modules\objdetect\src\cascadedetect.cpp, line 1698
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
cv2.error: C:\projects\opencv-python\opencv\modules\objdetect\src\cascadedetect.cpp:1698: error: (-215) !empty() in function cv::CascadeClassifier::detectMultiScale

You can pass a pointer pointing to the image instead of the image or the filename of the image
EDIT
def image_function(imagePointer):
#DO SOMETHING WITH THE IMAGE
#HERE IS THE IMAGE POINTER
image = open('your_image.png')
#CALLING THE FUNCTION
image_function(image)
Sorry, I don't know opencv so I can not help in your code :(

You can actually pass the image as a tensor.
with cv2.imread() and torch.
Which is easy, useful.
short answer:
load with cv2.imread()
transform to tensor with
img = torch.Tensor(img)/255.
That works for my application.
Yours might be a little different.
Code answer:
from Computer_Vision import Face_Detector as FD
def detectface():
import cv2
import torch
folder = r"This Folder/"
image_file = folder+"image.png"
# or
# file = r"image.png"
# image_file = os.path.join(folder, file)
img = imread(image_file)
img = torch.Tensor(img)/255. # THE KEY LINE HERE.
FDdetect(img):
"""Do stuff with object detection..."""
result =
return result

Related

cv2.error when training image (Overload Resolution Failed)

I'm learning opencv via the following link link link2. And I got error related to image training process for face recognition. Please correct me or help with the problem I'm having. thank you
System Information :
OpenCV 4.5.2.52
Python 3.9.5
Detailed Description
I need to train an images by using the code below and the results was :
- OpenCV/faces-train.py", line 50, in <module>
recognizer.train(x_train, np.array(y_labels))
cv2.error: OpenCV(4.5.2) :-1: error: (-5:Bad argument) in function 'train'
> Overload resolution failed:
> - src is not a numpy array, neither a scalar
> - Expected Ptr<cv::UMat> for argument 'src'
Code
import cv2
import os
import numpy as np
from PIL import Image
import pickle
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
image_dir = os.path.join(BASE_DIR, "images")
face_cascade = cv2.CascadeClassifier('cascade/data/haarcascade_frontalface_alt2.xml')
recognizer = cv2.face.LBPHFaceRecognizer_create()
current_id = 0
label_ids = {}
y_labels = []
x_train = []
for root, dirs, files, in os.walk(image_dir):
for file in files:
if file.endswith("png") or file.endswith("jpg") or file.endswith("jpeg") :
path = os.path.join(root, file)
label = os.path.basename(root).replace(" ", "-").lower()
# print(label, path)
if not label in label_ids:
label_ids[label] = current_id
current_id += 1
id_ = label_ids[label]
# print(label_ids)
y_labels.append(label)
x_train.append(path)
pil_image = Image.open(path).convert("L")
image_array = np.array(pil_image, "uint8")
# print(image_array)
faces = face_cascade.detectMultiScale(image_array, scaleFactor=1.5, minNeighbors=5)
for(x,y,w,h) in faces:
roi = image_array[y:y+h, x:x+w]
x_train.append(roi)
y_labels.append(id_)
# print(y_labels)
# print(x_train)
with open("labels.pickle", 'wb') as f:
pickle.dump(label_ids, f)
recognizer.train(x_train, np.array(y_labels))
recognizer.save("trainner.yml")
remove the following lines:
y_labels.append(label)
x_train.append(path)
you don't really need to append the labels or the paths since you are basically training the face recognizer to recognise/categorise faces. Likewise, you wouldnt need the path to your images as it is also not necessary. Guessing this is what caused the error!
Do let me know if the fix works! Cheers :)

face tracking error: (-215:Assertion failed) !empty() in function 'cv::CascadeClassifier::detectMultiScale

I continue getting this error. I've read that it means the images are not available. I've copied the path and used the proper directory. I've cloned the haarcascade_frontalface_default.xml directly from opencv Github. Not sure what I messed up on here.
I'm following this tutorial for facetracking online: https://www.youtube.com/watch?v=LmEcyQnfpDA&t=7600s
Any help appreciated!
Here are the code and errors:
Code:
import cv2
import numpy as np
def findFace(img):
faceCascade = cv2.CascadeClassifier('Resources/haarcascade_frontalface_default.xml')
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(imgGray,1.1,8)
myFaceListC = []
myFaceListArea = []
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x + w, y + h),(0,0,255),2)
cap = cv2.VideoCapture(0)
while True:
_, img = cap.read()
findFace(img)
cv2.imshow("Output",img)
cv2.waitKey(1)
Errors:
Traceback (most recent call last):
File "C:/Users/zachd/PycharmProjects/droneproject2/venv/Face Tracking.py", line 20, in <module>
findFace(img)
File "C:/Users/zachd/PycharmProjects/droneproject2/venv/Face Tracking.py", line 7, in findFace
faces = faceCascade.detectMultiScale(imgGray,1.1,8)
cv2.error: OpenCV(4.5.1) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-oduouqig\opencv\modules\objdetect\src\cascadedetect.cpp:1689: error: (-215:Assertion failed) !empty() in function 'cv::CascadeClassifier::detectMultiScale'
[ WARN:1] global C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-oduouqig\opencv\modules\videoio\src\cap_msmf.cpp (434) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback
Avoid jiggle or jumpy rectangles for the best results. In line 7, I changed the second and third parameters.
import cv2
import numpy as np
def findFace(img):
faceCascade = cv2.CascadeClassifier('Resources/haarcascade_frontalface_default.xml')
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(imgGray,1.3, 5)
myFaceListC = []
myFaceListArea = []
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x + w, y + h),(0,0,255),2)
cap = cv2.VideoCapture(0)
while True:
_, img = cap.read()
findFace(img)
cv2.imshow("Output", img)
cv2.waitKey(1)
Your error:
(-215:Assertion failed) !empty() in function 'cv::CascadeClassifier::detectMultiScale'
OpenCV uses the empty() method of the CascadeClassifier to test whether the cascade was loaded properly, in each detect() call. It does not refer to image data passed to the detect() call.
Right after instantiation, check:
# faceCascade = cv2.CascadeClassifier('Resources/haarcascade_frontalface_default.xml')
assert not faceCascade.empty(), "it didn't find the XML file"
If that fails, you need to learn about relative paths and the Current Working Directory. print(os.getcwd()) and consider if that is where you expected your program to run.
There are a few ways to fix the issue. The recommended way is:
faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
but that assumes them to be where OpenCV was installed. If you put those files elsewhere, you are responsible for finding them.
Many people have had this error message. Always use the search function. You should have found this previous question with some good answers
Messing with the parameters of the detect call won't do anything at all to fix your issue.

OpenCV Panorama: TypeError: cannot unpack non-iterable NoneType object

I'm trying to make a panorama from a image set. I'm using Spyder, OpenCV 3.4 and Python 3.7. Here's the code:
The main:
from stitches import Stitcher
#from PIL import Image
import os
import glob
import numpy as np
import imutils
import cv2
cap = cv2.VideoCapture('C:/Users/VID_20181208_111037881.mp4')
img_dir = "C:/Users/user/images"
data_path = os.path.join(img_dir, '*g')
files = glob.glob(data_path)
args = []
for f1 in files:
img = cv2.imread(f1)
args.append(img)
def retImg(img):
return img
for i in args:
j = i+1
frame = retImg(i)
frame2 = retImg(j)
#imageA = cv2.imread(frame)
#imageB = cv2.imread(frame2)
imageA = imutils.resize(frame, width=400)
imageB = imutils.resize(frame2, width=400)
# stitch the images together to create a panorama
stitcher = Stitcher()
(result, vis) = stitcher.stitch([imageA, imageB], showMatches=False)
frame = result
# show the images
cv2.imshow("Keypoint Matches", vis)
cv2.imshow("Result", result)
cv2.waitKey(0)
The stitch inside stitches.py:
def stitch(self, images, ratio=0.75, reprojThresh=4.0, showMatches=False):
# unpack the images, then detect keypoints and extract
# local invariant descriptors from them
(imageB, imageA) = images
(kpsA, featuresA) = self.detectAndDescribe(imageA)
(kpsB, featuresB) = self.detectAndDescribe(imageB)
# match features between the two images
M = self.matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh)
# if the match is None, then there aren't enough matched
# keypoints to create a panorama
if M is None:
return None
# together
(matches, H, status) = M
result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))
result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB
# check to see if the keypoint matches should be visualized
if showMatches:
vis = self.drawMatches(imageA, imageB, kpsA, kpsB, matches, status)
# return a tuple of the stitched image and the
# visualization
return (result, vis)
# return the stitched image
return result
When I compile it, the following error is shown:
File "C:/Users/user/panorama.py", line 44, in <module>
(result, vis) = stitcher.stitch([imageA, imageB], showMatches=False)
TypeError: cannot unpack non-iterable NoneType object
And I cannot understand why. I'm new to Python, so maybe this mistake is really simple, but I don't know what to do here. Thanks by advance!

Eigenfaces training image pixel size error

Hello to all senior programmer! I have an error on eigenfaces image training part.
The error is : OpenCV Error: Unsupported format or combination of formats (In the Eigenfaces method all input samples (training images) must be of equal size! Expected 27889 pixels, but was 27556 pixels.) in cv::face::Eigenfaces::train, file C:\projects\opencv-python\opencv_contrib\modules\face\src\eigen_faces.cpp, line 68
Which mean my pictures don't be in equal size. I try cv2.rezise() when I capture picture from camera but it still doesn't work.
here is my capture code :
import cv2
cam = cv2.VideoCapture(0)
detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
Id = input('enter your id: ')
sampleNum = 0
while(True):
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
sampleNum = sampleNum+1
cv2.imwrite("dataSet/user."+Id+'.'+str(sampleNum)+".jpg",cv2.resize
(gray[y:y+h,x:x+w],(70,70)))
cv2.imshow('frame',img)
if cv2.waitKey(100) & 0xFF == ord('q'):#waitKey is for delay in video capture
break
elif sampleNum >= 50:#how many picture capture?
break
cam.release()
cv2.destroyAllWindows()
and here is training part:
import cv2,os
import numpy as np
recognizer = cv2.face.EigenFaceRecognizer_create()
detector= cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
def getImagesAndLabels(path):
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
faceSamples=[]
Ids=[]
for imagePath in imagePaths:
pilImage = Image.open(imagePath).convert('L')
imageNp = np.array(pilImage,'uint8')
Id = int(os.path.split(imagePath)[-1].split(".")[1])
faces = detector.detectMultiScale(imageNp)
for (x,y,w,h) in faces:
faceSamples.append(imageNp[y:y+h,x:x+w])
Ids.append(Id)
return faceSamples,Ids
faces,Ids = getImagesAndLabels('dataSet')
recognizer.train(faces, np.array(Ids))
recognizer.write('trainner/trainnerEi.yml')
PS. I adapt this code from LBPHFaceRecognizer
Thank you!*3
Okay, so EigenFaces only works if the dimension of all the images is same in pixel space
Which means if one image used in training is of size 28x28 then every other image in the training as well as in testing has to be of size 28x28
If the image size is not same then opencv will throw you that error
The error simply says that one of the image was of 27889 dimensions in pixel space and other was 27556 dimensions pixel space.
I would recommend you to use cv2.resize() function to make all images of the same size
Use the below code as a reference for you training part:
import cv2,os
import numpy as np
recognizer = cv2.face.EigenFaceRecognizer_create()
detector= cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
def getImagesAndLabels(path):
width_d, height_d = 280, 280 # Declare your own width and height
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
faceSamples=[]
Ids=[]
for imagePath in imagePaths:
pilImage = Image.open(imagePath).convert('L')
imageNp = np.array(pilImage,'uint8')
Id = int(os.path.split(imagePath)[-1].split(".")[1])
faces = detector.detectMultiScale(imageNp)
for (x,y,w,h) in faces:
########################################
# The line to be changed by cv2.resize()
########################################
faceSamples.append(cv2.resize(imageNp[y:y+h,x:x+w], (width_d, height_d))
Ids.append(Id)
return faceSamples,Ids
faces,Ids = getImagesAndLabels('dataSet')
recognizer.train(faces, np.array(Ids))
recognizer.write('trainner/trainnerEi.yml')
Keep in mind even the test images has to be of same size

Convert CGImageRef to PIL

How could I convert a CGImageRef to PIL without saving the image to disk on osx?
I though about getting the raw pixel data from the CGImageRef and using Image.fromstring() to make the PIL image by doing
import mss
import Quartz.CoreGraphics as CG
from PIL import Image
mss = mss.MSSMac()
for i, monitor in enumerate(mss.enum_display_monitors(0)):
imageRef = mss.get_pixels(monitor)
pixeldata = CG.CGDataProviderCopyData(CG.CGImageGetDataProvider(imageRef))
img = Image.fromstring("RGB", (monitor[b'width'], monitor[b'height']), pixeldata)
img.show()
but this doesn't give me the correct image.
This is the image I expect:
and this is the image I get in PIL:
The screencapture from CG doesn't necessarily use the RGB colorspace. It may use RGBA or something else. Try changing:
img = Image.fromstring("RGB", (monitor[b'width'], monitor[b'height']), pixeldata)
to
img = Image.fromstring("RGBA", (monitor[b'width'], monitor[b'height']), pixeldata)
Here is how I detect which colorspace is actually being captured:
bpp = CG.CGImageGetBitsPerPixel(imageRef)
info = CG.CGImageGetBitmapInfo(imageRef)
pixeldata = CG.CGDataProviderCopyData(CG.CGImageGetDataProvider(imageRef))
img = None
if bpp == 32:
alphaInfo = info & CG.kCGBitmapAlphaInfoMask
if alphaInfo == CG.kCGImageAlphaPremultipliedFirst or alphaInfo == CG.kCGImageAlphaFirst or alphaInfo == CG.kCGImageAlphaNoneSkipFirst:
img = Image.fromstring("RGBA", (CG.CGImageGetWidth(imageRef), CG.CGImageGetHeight(imageRef)), pixeldata, "raw", "BGRA")
else:
img = Image.fromstring("RGBA", (CG.CGImageGetWidth(imageRef), CG.CGImageGetHeight(imageRef)), pixeldata)
elif bpp == 24:
img = Image.fromstring("RGB", (CG.CGImageGetWidth(imageRef), CG.CGImageGetHeight(imageRef)), pixeldata)
It was a bug I fixed some time ago. Here is how to achieve what you want using the latest mss version (2.0.22):
from mss.darwin import MSS
from PIL import Image
with MSS() as mss:
for monitor in mss.enum_display_monitors(0):
pixeldata = mss.get_pixels(monitor)
img = Image.frombytes('RGB', (mss.width, mss.height), pixeldata)
img.show()
Note that pixeldata is just a reference to mss.image, you can use it directly.

Categories