ERROR: !empty() in function 'detectMultiScale' - python

I have the following little code:
from google.colab import drive
from IPython.display import display
import PIL
from PIL import Image, ImageDraw
import kraken
from kraken import pageseg
import cv2 as cv
img = Image.open("/content/drive/My Drive/images/dropfire.jpg")
face_cascade = cv.CascadeClassifier(cv.data.haarcascades + "/content/drive/My Drive/datas/haarcascade_frontalface_default.xml")
eye_cascade = cv.CascadeClassifier(cv.data.haarcascades + "/content/drive/My Drive/datas/haarcascade_eye.xml")
file_name = "/content/drive/My Drive/images/dropfire.jpg"
img = cv.imread(file_name)
pil_img = Image.open(file_name)
cv_img = pil_img.convert('L')
cv_img = cv.imread(file_name)
faces = face_cascade.detectMultiScale(cv_img)
When I run the last cell (with faces), it raises:
error Traceback (most recent call last)
<ipython-input-23-2bd7582f8a20> in <module>()
----> 1 faces = face_cascade.detectMultiScale(cv_img)
error: OpenCV(4.1.2) /io/opencv/modules/objdetect/src/cascadedetect.cpp:1689: error: (-215:Assertion failed) !empty() in function 'detectMultiScale'
Until this cell everything works fine. According to a Stack Overflow answer, I added cv.data.haarcascades + in the brackets of cv.CascadeClassifier. Although people said this worked for them, it doesn't for me somehow.

imho, that "little code" of yours has too much noise (unnecessary lines of code) already.
I think it makes for you even harder to understand what's going on.
Comment out/delete all the lines except these:
import cv2 as cv
face_cascade = cv.CascadeClassifier(cv.data.haarcascades + "haarcascade_frontalface_default.xml")
eye_cascade = cv.CascadeClassifier(cv.data.haarcascades + "haarcascade_eye.xml")
file_name = "/content/drive/My Drive/images/dropfire.jpg"
img = cv.imread(file_name) # this reads the image already
cv_img = cv.imread(file_name) # this reads same image once more, not sure if intended
faces = face_cascade.detectMultiScale(cv_img)
If your image "dropfire" really exists at that path, this should work without error, but it won't show any results of face detection. You can add these lines at the end to see the result:
for (x, y, w, h) in faces:
cv.rectangle(cv_img, (x, y), (x+w, y+h), (0, 0, 255), 3)
cv.imshow("Nice face", cv_img)
cv.waitKey(0)
cv.data.haarcascades already has path to all those cv2 xml files, so you only need to use file names.

The issue is to check whether XML is loaded or not, use
eye_cascade.empty() to check whether it's loaded or not.

Related

yunet.onnx reading issue in opencv

i would like to detect faces with mask, here is one example of image :
classical side face detector
faceCascade =cv2.CascadeClassifier("haarcascade_profileface.xml")
does not detect faces well, therefore i tried to search a little more and found following documentation :
yunet documentation
i have tried to implement this model in my code :
import numpy as np
import matplotlib.pyplot as plt
import cv2
import math
#faceCascade =cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
#faceCascade =cv2.CascadeClassifier("haarcascade_profileface.xml")
frame =cv2.imread("distance_Measure.jpg")
frame =cv2.resize(frame,(500,500))
gray =cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
face_detector = cv2.FaceDetectorYN_create("yunet.onnx", "", (0, 0))
#faces =faceCascade.detectMultiScale(gray,scaleFactor=1.1,minNeighbors=5,minSize=(20,20))
_, faces = face_detector.detect(gray)
l =[]
lf =[]
i =1
for (x,y,w,h) in faces:
cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
s =str(i)
cv2.putText(frame,s,(x,y),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2)
i+=1
l =[]
l.append(x)
l.append(y)
lf.append(l)
print(l)
print(lf)
close_person =""
for i in range(len(lf)):
for j in range(i+1,len(lf)):
d =math.sqrt((lf[j][1]-lf[i][1])**2+((lf[j][0]-lf[i][0])**2))
print("P",i+1,"-P",j+1,"=",d)
if d <150:
close_person ="Person " +str(i+1)+" and Person "+str(j+1)+";"
cv2.line(frame,(lf[i][0],lf[i][1]),(lf[j][0],lf[j][1]),(0,0,255),2)
close_person+=" are not following social distance"
print(close_person)
cv2.imshow("Displayed_Persons",frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
plt.show()
but it returns following error :
Traceback (most recent call last):
File "C:\Users\User\PycharmProjects\AI_Project\Social_Distance_Measurement_Example.py", line 10, in <module>
face_detector = cv2.FaceDetectorYN_create("yunet.onnx", "", (0, 0))
cv2.error: OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv\modules\dnn\src\onnx\onnx_importer.cpp:194: error: (-5:Bad argument) Can't read ONNX file: yunet.onnx in function 'cv::dnn::dnn4_v20211220::ONNXImporter::ONNXImporter'
i have searched again and found following documentation :
searched solution
but i could not clarify how to solve given problem, please help me

Getting Error: (-215:Assertion failed) When Using seamlessClone

For clarity, I am a beginner in Python. I'm creating a script that replaces the eyes with a robotic one from a series of images in a folder. I'm stuck on the seamlessClone function that keeps throwing this error.
The code is incomplete as far as writing out the entire script (it only clones one eye so far), but everything should be working. I've been stuck on this one for 6 hours and thought I would ask on here.
I've tried checking my filenames, paths, seeing if the image file was corrupt by using print, changing the image files with different dimensions, filetypes (png, jpg) and so on.
I've also tried converting every numpy array(cv2_image, Eye) into a 32bit array to see if that was the issue, but nothing prevailed.
# Import
from PIL import Image, ImageDraw, ImageFilter
from statistics import mean
import face_recognition
import cv2
import glob
import numpy as np
# Open Eye Images
Eye = cv2.imread('eye.jpg')
# Loop Through Images
for filename in glob.glob('images/*.jpg'):
cv2_image = cv2.imread(filename)
image = face_recognition.load_image_file(filename)
face_landmarks_list = face_recognition.face_landmarks(image)
for facemarks in face_landmarks_list:
# Get Eye Data
eyeLPoints = facemarks['left_eye']
eyeRPoints = facemarks['right_eye']
npEyeL = np.array(eyeLPoints)
npEyeR = np.array(eyeRPoints)
# Create Mask
mask = np.zeros(cv2_image.shape, cv2_image.dtype)
mask.fill(0)
poly = np.array([eyeLPoints])
cv2.fillPoly(mask, [poly], (255,255, 255))
# Get Eye Image Centers
npEyeL = np.array(eyeLPoints)
eyeLCenter = npEyeL.mean(axis=0).astype("int")
x1 = (eyeLCenter[0])
x2 = (eyeLCenter[1])
print(x1, x2)
# Get Head Rotation (No code yet)
# Apply Seamless Clone To Main Image
saveImage = cv2.seamlessClone(Eye, cv2_image, mask ,(x1, x2) , cv2.NORMAL_CLONE)
# Output and Save
cv2.imwrite('output/output.png', saveImage)
Here is the full error:
Traceback (most recent call last):
File "stack.py", line 45, in <module>
saveImage = cv2.seamlessClone(Eye, cv2_image, mask ,(x1, x2) , cv2.NORMAL_CLONE)
cv2.error: OpenCV(4.1.1) /io/opencv/modules/core/src/matrix.cpp:466: error: (-215:Assertion failed) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function 'Mat'
The result I'm expecting is for the eye image to be cloned onto the original image, but this error keeps being thrown, preventing me from completing the script. If there were any hint as to what's going on, I feel that the culprit is the "Eye" file, but I could be wrong. Any help would be appreciated.
There are two sets of keypoints:
There is a set of keypoints for the eye in the destination image:
There is a set of keypoints for the eye in the source image:
You are using the wrong set of keypoints to make the mask for the cv2.seamlessClone() function. You should be using the keypoints from the source image. The mask needs to be a TWO channel image, in your code (among the other problems) you are using a THREE channel image.
This is the result. You can see there should also be a resize function to match the sizes of the eyes:
This is the code that I used:
import face_recognition
import cv2
import numpy as np
# Open Eye Images
eye = cv2.imread('eye.jpg')
# Open Face image
face = cv2.imread('face.jpeg')
# Get Keypoints
image = face_recognition.load_image_file('face.jpeg')
face_landmarks_list = face_recognition.face_landmarks(image)
for facemarks in face_landmarks_list:
# Get Eye Data
eyeLPoints = facemarks['left_eye']
eyeRPoints = facemarks['right_eye']
npEyeL = np.array(eyeLPoints)
# These points define the contour of the eye in the EYE image
poly_left = np.array([(51, 228), (100, 151), (233, 102), (338, 110), (426, 160), (373, 252), (246, 284), (134, 268)], np.int32)
# Create a mask for the eye
src_mask = np.zeros(face.shape, face.dtype)
cv2.fillPoly(src_mask, [poly_left], (255, 255, 255))
cv2.imwrite('src_mask.png', src_mask)
# Find where the eye should go
center, r = cv2.minEnclosingCircle(npEyeL)
center = tuple(np.array(center, int))
# Clone seamlessly.
output = cv2.seamlessClone(eye, face, src_mask, center, cv2.NORMAL_CLONE)

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.

Reproducing Python script in R via "reticulate"

I am trying to recreate a working python script using RStudio's reticulate package for python. The working script is an adaption of dlib's face detection script. I have it almost working, I think, but I do not know how to enumerate along an object. In the original script, it reads:
from imutils import face_utils
import numpy as np
import imutils
import dlib
import cv2
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("path/to/shape_predictor_68_face_landmarks.dat")
image = cv2.imread("path/to/defiant2.jpg")
print(image.shape)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
rects = detector(gray, 1)
for (i, rect) in enumerate(rects):
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
bb = face_utils.rect_to_bb(rect)
rect = shape[1]
for rect in shape:
print("{} {}".format(*rect))
print("{} {} {} {}".format(*bb))
When I try and recreate this in R to the best of my ability, I hit a roadblock when it is supposed to enumerate along the dlib detector object. Specifically, I get the following error:
library(reticulate)
cv2 <- import('cv2', convert = FALSE)
dlib <- import('dlib', convert = FALSE)
face_utils <- import('imutils.face_utils')
imutils <- import('imutils')
np <- import('numpy')
main <- import_main()
py <- import_builtins()
shape_predictor = 'shape_predictor_68_face_landmarks.dat'
img = 'defiant2.jpg'
detector = dlib$get_frontal_face_detector()
predictor = dlib$shape_predictor(shape_predictor)
image = cv2$imread(img)
gray = cv2$cvtColor(image, cv2$COLOR_BGR2GRAY)
rects = detector$run(gray)
py$enumerate(rects)
Error: attempt to apply non-function
Any help in transferring the code to R would be greatly appreciated. If it helps, I have uploaded the full script files, as well as a test image and the shape predictor landmarks file to Github.

Python - Writing your own function with opencv giving an error

import numpy as np
import cv2
def resize(image, percentage):
img = image
fy=percentage
fx=percentage
img2 = cv2.resize(img, (0,0), fx, fy)
return cv2.img2
img = cv2.imread('test.png')
img2 = resize(img, 0.45)
cv2.imshow('image',img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Traceback (most recent call last):
File "C:\Users\Jay\Desktop\Portable Python\opencvprogram_ver1.py", line 14, in <module>
img2 = resize(img, 0.45)
File "C:\Users\Jay\Desktop\Portable Python\opencvprogram_ver1.py", line 10, in resize
img2 = cv2.resize(img, (0,0), fx, fy)
error: C:\builds\master_PackSlaveAddon-win32-vc12-static\opencv\modules\imgproc\src\imgwarp.cpp:3209: error: (-215) dsize.area() > 0 || (inv_scale_x > 0 && inv_scale_y > 0) in function cv::resize
Dear Python Council members,
I've been learning Python and OpenCV and I ran into a problem here.
I'm trying to see if it's possible to include an OpenCV function in my own function, but it seems like I'm doing this wrong. The traceback says something something about dsize.area in cv::resize, but this error message means very little too me because I do not know how this works in the smaller picture.
Can someone guide me in the right direction so the program works as I'd expect?
Thank you very much.
What you have looks almost right. Just change the last two lines of the function to:
img2 = cv2.resize(img, (0,0), fx=fx, fy=fy) # enter fx and fy as keyword arguments
return img2 # cv2.img2 was just a typo
Since fx and fy are not the 3rd and 4th arguments of the function, you have to specify them as keyword arguments.

Categories