I am trying to develop a simple application to detect faces as well as eyes in a given image:
from cv2 import *
face_cascade = CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = CascadeClassifier('haarcascade_eye.xml')
img = imread("123.jpg")
gray = cvtColor(img, COLOR_BGR2GRAY)
rows,cols = gray.shape
gray = getRotationMatrix2D((cols/2,rows/2),-90,1)
faces = face_cascade.detectMultiScale(gray, 1.3, 5, 0)
print faces
for (x,y,w,h) in faces:
img = rectangle(img, (x,y), ((x+w),(x+h)), (255,0,0), 2)
#gray = rectangle(gray, (x,y), ((x+w), (x+y)), (0, 255, 0), 4)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_grey)
for (ex,ey, ew, eh) in eyes:
roi_color = rectangle(roi_color, (x,y), ((x+w), (y+h)), (50, 50, 50), 3)
imshow("img", img)
waitKey(9)
destroyAllWindows()
(Note: The rotation is necessary, as after using the cvtColor function, the output image is generated with a rotation of 90 degrees counter clockwise.)
I am getting the following error:
Traceback (most recent call last): File "/home/namit/Codes/wow.py",
line 10, in faces = face_cascade.detectMultiScale(gray, 1.3,
5, 0) error:
/home/namit/OpenCV/opencv-2.4.9/modules/objdetect/src/cascadedetect.cpp:1081:
error: (-215) scaleFactor > 1 && image.depth() == CV_8U in function
detectMultiScale
The cause of the error message was that the image gray was float64 while face_cascade.detectMultiScale requires unisigned integer. The fix for that is to convert the image to uint8 before calling `face_cascade.detectMultiScale``:
import numpy as np
gray = np.array(gray, dtype='uint8')
There were other issues. For one, cv2.rectangle does not return an image; instead it modifies the image that you pass to it. The following works for me:
from cv2 import *
import numpy as np
face_cascade = CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = CascadeClassifier('haarcascade_eye.xml')
fname='123.jpg'
img = imread(fname)
gray = imread(fname, CV_LOAD_IMAGE_GRAYSCALE)
rows,cols = gray.shape
gray = np.array(gray, dtype='uint8')
faces = face_cascade.detectMultiScale(gray, 1.3, 5, 0)
print 'faces=', faces
for (x,y,w,h) in faces:
rectangle(img, (x,y), ((x+w),(x+h)), (255,0,0), 2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex,ey, ew, eh) in eyes:
rectangle(roi_color, (x,y), ((x+w), (y+h)), (50, 50, 50), 3)
imshow('eyes=%s' % (eyes,), roi_color)
imshow("img", img)
waitKey(0)
destroyAllWindows()
I did not observe a problem with image rotation, so I removed the rotation code.
Related
I'm trying to detect camera is out of focus or not, with blurriness. When i'm executing this code the camera is open and live and suppose any moving object comes in focus area then it calculate its blurriness and displays camera is defocused with blurriness %. My problem is suppose i put a transparent glass or plastic on camera then it not detected. How can i do it.
import numpy as np
import cv2
#capturing video frame and applying background subtraction
cap = cv2.VideoCapture(0)
fgbg = cv2.createBackgroundSubtractorMOG2()
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
kernel = np.ones((5, 5), np.uint8)
#calculating laplacian variation
def laplacian_variation(image):
if image.ndim == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur_map = cv2.Laplacian(image, cv2.CV_64F)
score = np.var(blur_map)
return score
while (True):
ret, frame = cap.read()
if (frame is None):
print("camera is blocked")
break
else:
a = 0
bounding_rect = []
fgmask = fgbg.apply(frame)
fgmask = cv2.erode(fgmask, kernel, iterations=5)
fgmask = cv2.dilate(fgmask, kernel, iterations=5)
cv2.imshow('frame', frame)
#taking threshold, calling laplacian_variation and calculating
#contours
ret, thresh = cv2.threshold(frame, 10, 50, cv2.THRESH_BINARY)
fm = laplacian_variation(frame)
_, contours, _ = cv2.findContours(fgmask, cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
for i in range(0, len(contours)):
bounding_rect.append(cv2.boundingRect(contours[i]))
for i in range(0, len(contours)):
if bounding_rect[i][2] >= 40 or bounding_rect[i][3] >= 40:
a = a + (bounding_rect[i][2]) * bounding_rect[i][3]
#check if focus measure(fm) is less than threshold then
#camera is out out of focus or incoming images is blurry
if (fm < thresh.all() or a >= int(frame.shape[0]) *
int(frame.shape[1]) / 3):
cv2.putText(frame, "defocused", (5, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255,
255), 2)
cv2.putText(frame, "{}: {:.2f}".format('blurriness',
fm), (5, 60), cv2.FONT_HERSHEY_SIMPLEX,
0.8, (0, 0, 255),3)
cv2.imshow('frame', frame)
if cv2.waitKey(30) & 0xff == 27:
break
#release the camera and destroy all opened windows
cap.release()
cv2.destroyAllWindows()
I have the following picture
And I try to count all candies, but some of them intersect. And my following code doesn't work. The Code below can only identify candies if they don't intersect. But I can't have any thoughts about what to do if they intersect
int main( int argc, char** argv )
{
Mat src = imread("C:\\data\\Assignment1A.jpg",0); // reads image from file
Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);
cv::Scalar min(245, 0, 0);
cv::Scalar max(255, 255, 255);
cv::inRange( src, min, max, dst);
namedWindow( "Source", 1 );
imshow( "Source", dst );
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( dst, contours, hierarchy,
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
cout <<contours.size();
size_t count = contours.size();
int i = 0;
for(size_t i = 0; i < contours.size(); i++) {
cv::Point2f c;
float r;
cv::minEnclosingCircle( contours[i], c, r);
if (r > 10) {
i++; }
}
cout << i << " candies";
waitKey(0);
return 0;
}
Can anyone help me how to solve this problem?
This is probably not a very good solution (it only works under assumption that candies of the same color never overlap). (There's also this article about using distance transform and watershed, but I couldn't make it fork for this, maybe the candies overlap too much?)
Remove the white background (especially because it has a lot of noise and JPEG artifacts).
Convert to HSV and take the H channel (as suggested in the comments). Hue is useful here, because it sort of represents a color with a single value (hue) instead of three (red, green, blue), ignoring, to a degree, all those surface irregularities. You probably can't distinguish some of the ellipses below from the background, but don't worry, your computer can.
For a narrow range of H (say, [1, 20]), find contours big enough (in terms of their area) to be a single candy, but small enough not to be more than one candy. Repeat for H in range [21, 40], then [41, 60], and so on, until you reach the top hue value of 179. The contours are not too good, but good enough for counting. You can probably improve them by doing dilate/erode at every step to get rid of the junk, or something, if you need to.
The Python code to show how it works:
import cv2
import numpy as np
#get only contours of more or less the single candy size
#noise is not included because its area is too small
#overlapping candies are not included because their area is too big
#probably there are smarter ways (area/circumference ratio, ellipse fitting, etc.)
def get_contours(img):
area_threshold_max = 120*120 #nice hard-coded empirical values
area_threshold_min = 50*50
_, contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(c) for c in contours]
contours = [c for n, c in enumerate(contours) if area_threshold_min < areas[n] < area_threshold_max]
return contours
#remove background
img_g = cv2.imread("candy.jpg", 0) #read as grayscale
_, thresh = cv2.threshold(img_g, 235, 1, cv2.THRESH_BINARY_INV) #mask to include everything that isn't too white
img = cv2.imread("candy.jpg") #read again as a color image
black = np.zeros(img.shape).astype(img.dtype) #black image to combine with
img = cv2.bitwise_or(img, black, mask = thresh)
#convert to HSV and take only the H value
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)[:, :, 0]
#find contours of a more or less appropriate size within a narrow H range,
#remove them from the image, increment H, repeat
contours_all = []
h_step = 20
for h_start in range(0, 180, h_step):
rng = np.zeros(img.shape).astype(np.uint8)
rng = cv2.inRange(img, h_start + 1, h_start + h_step)
contours = get_contours(rng)
contours_all += contours
#draw our contours with their numbers on top of the original image
img_to_draw = cv2.imread("candy.jpg")
cv2.drawContours(img_to_draw, contours_all, -1, (0, 0, 0), 2)
for i, cnt in enumerate(contours_all):
(x, y), radius = cv2.minEnclosingCircle(cnt)
cv2.putText(img_to_draw, "%d" % (i + 1), (int(x-20), int(y+10)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 3)
cv2.putText(img_to_draw, "%d candies" % len(contours_all), (5, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 3)
cv2.imwrite("result2.png", img_to_draw)
I'm trying to detect the upper body using haar cascade.
But still I'm not getting any detection on the image.
import numpy as np
import cv2
cascade = cv2.CascadeClassifier('haarcascade_upperbody.xml');
imgPath = '/home/ayush/Desktop/images.jpeg';
img = cv2.imread(imgPath);
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
body = cascade.detectMultiScale(
gray,
scaleFactor = 1.1,
minNeighbors = 5,
minSize = (30,30),
flags = cv2.CASCADE_SCALE_IMAGE
)
for (x, y, w, h) in body:
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.imshow('Upper Body',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Why is it so?
I'm using OpenCV3.
It is possible that your scaleFactor is too small. I tried running your code exactly (though with my own image) and found no results at 1.1, but found results at 1.01.
See here for a description of how the parameter affects your results.
That's because the file haarcascade_upperbody.xml is trained to be used with pedestrian detection, and very probably your image is not matching to this case.
I want to extract only the rectangular part of the mouth detected by my code how can I do it:
import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml')
mouth_cascade = cv2.CascadeClassifier('/usr/local/share/OpenCV/haarcascades/haarcascade_smile.xml')
img = cv2.imread('Images/image_0033.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.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)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
mouth = mouth_cascade.detectMultiScale(roi_gray,2.0,25)
for (ex,ey,ew,eh) in mouth:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),3)
cv2.imshow('img',nwimg)
cv2.waitKey(0)
cv2.destroyAllWindows()
As seen in the code I just want to extract the rectangular mouth region I have used commands like var = img[y:y+h,x:x+w] but this has not worked.
It is simple, replace this line:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),3) with
cv2.rectangle(img,(ex,ey),(ex+ew,ey+eh),(0,255,0),3)
and display the following:
cv2.imshow('Detected Mouth',img)
In this way you will draw a rectangle over the mouth.
EDIT
You can crop your region of interest (in this case the mouth) using numpy operation as follows:
crop_img = img[ey:ey+eh, ex:ex+ew]
cv2.imshow('Cropped Mouth',crop_img)
This is what I got:
Sample 1:
Sample 2:
Hello I am running the python opencv code below on a raspberry pi 3 and using a usb camera.The program tracks a persons face and overlays a mask image over the face. My program keeps crashing and showing the error below:. Also the image masking the persons face is not removing the background color to just leave the image mask. Hope you can help.
:1036: error : (-215) mask.size == src1.size in function binary_op
import cv2
import numpy as np
face_cascade = cv2.CascadeClassifier('cascade_files/haarcascade_frontalface_alt.xml')
face_mask = cv2.imread('../images/mask_skull.png')
h_mask, w_mask = face_mask.shape[:2]
if face_cascade.empty():
raise IOError('Unable to load the face cascade classifier xml file')
cap = cv2.VideoCapture(0)
scaling_factor = 0.5
while True:
ret, frame = cap.read()
frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
face_rects = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in face_rects:
if h > 0 and w > 0:
h, w = int(1.4*h), int(1.0*w)
y -= 0.1*h
frame_roi = frame[y:y+h, x:x+w]
face_mask_small = cv2.resize(face_mask, (w, h), interpolation=cv2.INTER_AREA)
gray_mask = cv2.cvtColor(face_mask_small, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(gray_mask, 180, 255, cv2.THRESH_BINARY_INV)
mask_inv = cv2.bitwise_not(mask)
masked_face = cv2.bitwise_and(face_mask_small, face_mask_small, mask=mask)
masked_frame = cv2.bitwise_and(frame_roi, frame_roi, mask=mask_inv)
frame[y:y+h, x:x+w] = cv2.add(masked_face, masked_frame)
cv2.imshow('Face Detector', frame)
c = cv2.waitKey(1)
if c == 27:
break
cap.release()
cv2.destroyAllWindows()