State-of-the-art and curated Computer Vision algorithms for AI.

image.png

Face Detection

  1. # !/usr/bin python
  2. # -*- encoding: utf-8 -*-
  3. # @author: xhades
  4. # datetime: 2022-01-07
  5. from PIL import Image
  6. import kornia.geometry as K
  7. import argparse
  8. import cv2
  9. import numpy as np
  10. import torch
  11. import kornia as K
  12. from kornia.contrib import FaceDetector, FaceDetectorResult, FaceKeypoint
  13. def draw_keypoint(img: np.ndarray, det: FaceDetectorResult, kpt_type: FaceKeypoint) -> np.ndarray:
  14. kpt = det.get_keypoint(kpt_type).int().tolist()
  15. return cv2.circle(img, kpt, 2, (255, 0, 0), 2)
  16. def scale_image(img: np.ndarray, size: int) -> np.ndarray:
  17. h, w = img.shape[:2]
  18. scale = 1. * size / w
  19. return cv2.resize(img, (int(w * scale), int(h * scale)))
  20. def apply_blur_face(img: torch.Tensor, img_vis: np.ndarray, det: FaceDetectorResult):
  21. # crop the face
  22. x1, y1 = det.xmin.int(), det.ymin.int()
  23. x2, y2 = det.xmax.int(), det.ymax.int()
  24. roi = img[..., y1:y2, x1:x2]
  25. # apply blurring and put back to the visualisation image
  26. roi = K.filters.gaussian_blur2d(roi, (21, 21), (35., 35.))
  27. roi = K.color.rgb_to_bgr(roi)
  28. img_vis[y1:y2, x1:x2] = K.tensor_to_image(roi)
  29. def my_app(args):
  30. # select the device
  31. device = torch.device('cpu')
  32. if args.cuda and torch.cuda.is_available():
  33. device = torch.device('cuda:0')
  34. # load the image and scale
  35. img_raw = cv2.imread(args.image_file, cv2.IMREAD_COLOR)
  36. img_raw = scale_image(img_raw, args.image_size)
  37. # preprocess
  38. img = K.image_to_tensor(img_raw, keepdim=False).to(device)
  39. img = K.color.bgr_to_rgb(img.float())
  40. # create the detector and find the faces !
  41. face_detection = FaceDetector().to(device)
  42. with torch.no_grad():
  43. dets = face_detection(img)
  44. dets = [FaceDetectorResult(o) for o in dets]
  45. # show image
  46. img_vis = img_raw.copy()
  47. for b in dets:
  48. if b.score < args.vis_threshold:
  49. continue
  50. # draw face bounding box
  51. img_vis = cv2.rectangle(
  52. img_vis, b.top_left.int().tolist(), b.bottom_right.int().tolist(), (0, 255, 0), 4)
  53. if args.blur_faces:
  54. apply_blur_face(img, img_vis, b)
  55. if args.vis_keypoints:
  56. # draw facial keypoints
  57. img_vis = draw_keypoint(img_vis, b, FaceKeypoint.EYE_LEFT)
  58. img_vis = draw_keypoint(img_vis, b, FaceKeypoint.EYE_RIGHT)
  59. img_vis = draw_keypoint(img_vis, b, FaceKeypoint.NOSE)
  60. img_vis = draw_keypoint(img_vis, b, FaceKeypoint.MOUTH_LEFT)
  61. img_vis = draw_keypoint(img_vis, b, FaceKeypoint.MOUTH_RIGHT)
  62. # draw the text score
  63. cx = int(b.xmin)
  64. cy = int(b.ymin + 12)
  65. img_vis = cv2.putText(
  66. img_vis, f"{b.score:.2f}", (cx, cy), cv2.FONT_HERSHEY_DUPLEX, 0.5, (255, 255, 255))
  67. # save and show image
  68. cv2.imwrite(args.image_out, img_vis)
  69. cv2.namedWindow('face_detection', cv2.WINDOW_NORMAL)
  70. cv2.imshow('face_detection', img_vis)
  71. cv2.waitKey(0)
  72. if __name__ == "__main__":
  73. parser = argparse.ArgumentParser(description='Face and Landmark Detection')
  74. parser.add_argument('--image_file', required=True, type=str, help='the image file to be detected.')
  75. parser.add_argument('--image_out', required=True, type=str, help='the file path to write the output.')
  76. parser.add_argument('--image_size', default=320, type=int, help='the image size to process.')
  77. parser.add_argument('--vis_threshold', default=0.8, type=float, help='visualization_threshold')
  78. parser.add_argument('--vis_keypoints', dest='vis_keypoints', action='store_true')
  79. parser.add_argument('--cuda', dest='cuda', action='store_true')
  80. parser.add_argument('--blur_faces', dest='blur_faces', action='store_true')
  81. args = parser.parse_args()
  82. my_app(args)

image.pngimage.png

Data Augmentation

image.png