I want to adjust the margin of cropped face image. My current code can detect and crop face. However, the cropped image is too tight as shown in the below output image.
Input image:
Below is my code:
import face_recognition
import cv2
img = face_recognition.load_image_file("test.png")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
face_locations = face_recognition.face_locations(img_rgb)
for top, right, bottom, left in face_locations:
# Draw a box around the face
cv2.rectangle(img, (left, top), (right, bottom), (0, 0, 255), 2)
crop_img = img_rgb[top:bottom, left:right]
cv2.imwrite('test_crop.png', crop_img)
UPDATE: It will not work correctly for out of bound bounding boxes after scaling.
Code:
Use the scale_factor
to control the new rectangle size. Also a different formula can be used for M
. Using abs
may not be necessary.
import face_recognition
import cv2
img = face_recognition.load_image_file("test.png")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_rgb_copy = img_rgb.copy()
## Define scale factor and window size
scale_factor = 1.1
sz1 = img_rgb.shape[1] * 2
sz2 = img_rgb.shape[0] * 2
face_locations = face_recognition.face_locations(img_rgb)
for top, right, bottom, left in face_locations:
# Draw a box around the face
#cv2.rectangle(img, (left, top), (right, bottom), (0, 0, 255), 2)
crop_img = img_rgb[top:bottom, left:right]
#cv2.imwrite('test_crop.png', crop_img)
## Calculate center points and rectangle side length
width = right - left
height = bottom - top
cX = left + width // 2
cY = top + height // 2
M = (abs(width) + abs(height)) / 2
## Get the resized rectangle points
newLeft = max(0, int(cX - scale_factor * M))
newTop = max(0, int(cY - scale_factor * M))
newRight = min(img_rgb.shape[1], int(cX + scale_factor * M))
newBottom = min(img_rgb.shape[0], int(cY + scale_factor * M))
## Draw the circle and bounding boxes
cv2.circle(img_rgb_copy, (cX, cY), radius=0, color=(0, 0, 255), thickness=2)
cv2.rectangle(img_rgb_copy, (left, top), (right, bottom), (0, 0, 255), 2)
cv2.rectangle(img_rgb_copy, (newLeft, newTop), (newRight, newBottom), (255, 0, 0), 2)
## Show the original image in window resized to double
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.resizeWindow('image', sz1, sz2)
cv2.imshow("image", img_rgb_copy)
cv2.waitKey(0)
cv2.destroyAllWindows()
Image:
Method:
Get the center point (cX, cY)
of given region and from that get new left corner of image by subtracting same value from both (cX - M,cY - M)
. So the right corner will be (cX + M, cY + M)
. You can use a scale factor such as, M * p
instead of M
, where p
will control how large or small the new region will be.
Center Point:
width = right - left
height = bottom - top
centerX = left + (width / 2)
centerY = top + (height / 2)
M = (abs(width) + abs(height)) / 2
0 <= p < 1, for smaller crop than given in a side
p > 1, for larger crop margin
Also the new crop may be out of bounds in image. To solve it something like, newTop = max(0, newTop)
, newRight = min(imageWidth, newRight)
can be done and similar for others. You can find a demo here,
DeepFace wraps many face detection libraries. Besides, it applies face alignment in the background. You can detect faces in a line of code.
#!pip install deepface
from deepface import DeepFace
backends = ['opencv', 'ssd', 'dlib', 'mtcnn']
for backend in backends:
detected_face = DeepFace.detectFace("img.jpg", detector_backend = backend)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.