Reputation: 7208
I am doing face detection
using python opencv
. For this I am using caffe model
. Below is the code:
import numpy as np
import imutils
import cv2
protoPath = "<path_to_file>\\deploy.prototxt"
modelPath = "<path_to_file>\\res10_300x300_ssd_iter_140000.caffemodel"
detector = cv2.dnn.readNetFromCaffe(protoPath, modelPath)
image = cv2.imread('test.jpg')
image = imutils.resize(image, width=600)
(h, w) = image.shape[:2]
imageBlob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0), swapRB=False, crop=False)
detector.setInput(imageBlob)
detections = detector.forward()
if len(detections) > 0:
i = np.argmax(detections[0, 0, :, 2])
confidence = detections[0, 0, i, 2]
if confidence > 0.5:
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2)
cv2.imshow("Image", image)
cv2.waitKey(0)
Above code is working perfectly fine for almost all images. For example below:
As you can see the face is detected with confidence of 96%
. But there are many cases for which the code is detecting false faces as well like below:
Above face is detected but also has false detections and the shocking part is that confidence in both the detections was more than 90%
Whenever I have these type of false detections, I use some online face detector to quickly verify, like this one and the results looks good:
and because of this I sometime feels weather the model I am using for face detection
is good enough or not.
Can anyone please help me here and please tell me what I am doing wrong due to which its giving false detections and how can I remove these false detections. Please help. Thanks
EDIT:
Even after doing Non-maximum suppression, its not seems to be working:
def non_max_suppression_fast(self, boxes, overlapThresh):
try:
self.dummy = ''
if len(boxes) == 0:
return []
if boxes.dtype.kind == "i":
boxes = boxes.astype("float")
pick = []
x1 = boxes[:, 0]
y1 = boxes[:, 1]
x2 = boxes[:, 2]
y2 = boxes[:, 3]
area = (x2 - x1 + 1) * (y2 - y1 + 1)
idxs = np.argsort(y2)
while len(idxs) > 0:
last = len(idxs) - 1
i = idxs[last]
pick.append(i)
xx1 = np.maximum(x1[i], x1[idxs[:last]])
yy1 = np.maximum(y1[i], y1[idxs[:last]])
xx2 = np.minimum(x2[i], x2[idxs[:last]])
yy2 = np.minimum(y2[i], y2[idxs[:last]])
w = np.maximum(0, xx2 - xx1 + 1)
h = np.maximum(0, yy2 - yy1 + 1)
overlap = (w * h) / area[idxs[:last]]
idxs = np.delete(idxs, np.concatenate(([last],
np.where(overlap > overlapThresh)[0])))
return boxes[pick].astype("int")
except Exception as e:
print("Exception occurred in non_max_suppression : {}".format(e))
###
SOME CODE
###
rects = []
for i in range(0, detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence > 0.5:
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
rects.append(box)
boundingboxes = np.array(rects)
boundingboxes = boundingboxes.astype(int)
rects = non_max_suppression_fast(boundingboxes, 0.3)
boundingBoxes
before passing it to non_max_suppression_fast
is [[311 280 644 719], [131 114 419 475]]
and after suppressions its still the same rects = [[311 280 644 719], [131 114 419 475]]
Upvotes: 0
Views: 1518
Reputation: 7208
I have resolved this. Although the approach I have used has given me 99% accuracy but I am not sure if the approach is correct or not.
So whenever I get false detections in face images just like below:
In the above image, we can see that the 2nd bounding box which bottom right corner is quite bigger than the actual height and width of the image. Thus I have put a simple check that if bounding box is greater that height/width of the image, ignore it. Below is the code:
res = check_false_detections(h, w, startX, startY, endX, endY)
if not res:
print("Got false detection")
continue
and here is the code for check_false_detections
:
def check_false_detections(ih, iw, fsx, fsy, fex, fey):
if ih > iw:
if fsx > ih:
return False
elif fsy > ih:
return False
elif fex > ih:
return False
elif fey > ih:
return False
else:
return True
else:
if fsx > iw:
return False
elif fsy > iw:
return False
elif fex > iw:
return False
elif fey > iw:
return False
else:
return True
This is working fine for my use case. I have tested with more than 150 images. It might not work for anyone else but its worth a try.
Thanks
Upvotes: 1