Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

face_recognition_cli.py 4.6 KB

You have to be logged in to leave a comment. Sign In
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  1. # -*- coding: utf-8 -*-
  2. from __future__ import print_function
  3. import click
  4. import os
  5. import re
  6. import face_recognition.api as face_recognition
  7. import multiprocessing
  8. import itertools
  9. import sys
  10. import PIL.Image
  11. import numpy as np
  12. def scan_known_people(known_people_folder):
  13. known_names = []
  14. known_face_encodings = []
  15. for file in image_files_in_folder(known_people_folder):
  16. basename = os.path.splitext(os.path.basename(file))[0]
  17. img = face_recognition.load_image_file(file)
  18. encodings = face_recognition.face_encodings(img)
  19. if len(encodings) > 1:
  20. click.echo("WARNING: More than one face found in {}. Only considering the first face.".format(file))
  21. if len(encodings) == 0:
  22. click.echo("WARNING: No faces found in {}. Ignoring file.".format(file))
  23. else:
  24. known_names.append(basename)
  25. known_face_encodings.append(encodings[0])
  26. return known_names, known_face_encodings
  27. def print_result(filename, name, distance, show_distance=False):
  28. if show_distance:
  29. print("{},{},{}".format(filename, name, distance))
  30. else:
  31. print("{},{}".format(filename, name))
  32. def test_image(image_to_check, known_names, known_face_encodings, tolerance=0.6, show_distance=False):
  33. unknown_image = face_recognition.load_image_file(image_to_check)
  34. # Scale down image if it's giant so things run a little faster
  35. if max(unknown_image.shape) > 1600:
  36. pil_img = PIL.Image.fromarray(unknown_image)
  37. pil_img.thumbnail((1600, 1600), PIL.Image.LANCZOS)
  38. unknown_image = np.array(pil_img)
  39. unknown_encodings = face_recognition.face_encodings(unknown_image)
  40. for unknown_encoding in unknown_encodings:
  41. distances = face_recognition.face_distance(known_face_encodings, unknown_encoding)
  42. result = list(distances <= tolerance)
  43. if True in result:
  44. [print_result(image_to_check, name, distance, show_distance) for is_match, name, distance in zip(result, known_names, distances) if is_match]
  45. else:
  46. print_result(image_to_check, "unknown_person", None, show_distance)
  47. if not unknown_encodings:
  48. # print out fact that no faces were found in image
  49. print_result(image_to_check, "no_persons_found", None, show_distance)
  50. def image_files_in_folder(folder):
  51. return [os.path.join(folder, f) for f in os.listdir(folder) if re.match(r'.*\.(jpg|jpeg|png)', f, flags=re.I)]
  52. def process_images_in_process_pool(images_to_check, known_names, known_face_encodings, number_of_cpus, tolerance, show_distance):
  53. if number_of_cpus == -1:
  54. processes = None
  55. else:
  56. processes = number_of_cpus
  57. # macOS will crash due to a bug in libdispatch if you don't use 'forkserver'
  58. context = multiprocessing
  59. if "forkserver" in multiprocessing.get_all_start_methods():
  60. context = multiprocessing.get_context("forkserver")
  61. pool = context.Pool(processes=processes)
  62. function_parameters = zip(
  63. images_to_check,
  64. itertools.repeat(known_names),
  65. itertools.repeat(known_face_encodings),
  66. itertools.repeat(tolerance),
  67. itertools.repeat(show_distance)
  68. )
  69. pool.starmap(test_image, function_parameters)
  70. @click.command()
  71. @click.argument('known_people_folder')
  72. @click.argument('image_to_check')
  73. @click.option('--cpus', default=1, help='number of CPU cores to use in parallel (can speed up processing lots of images). -1 means "use all in system"')
  74. @click.option('--tolerance', default=0.6, help='Tolerance for face comparisons. Default is 0.6. Lower this if you get multiple matches for the same person.')
  75. @click.option('--show-distance', default=False, type=bool, help='Output face distance. Useful for tweaking tolerance setting.')
  76. def main(known_people_folder, image_to_check, cpus, tolerance, show_distance):
  77. known_names, known_face_encodings = scan_known_people(known_people_folder)
  78. # Multi-core processing only supported on Python 3.4 or greater
  79. if (sys.version_info < (3, 4)) and cpus != 1:
  80. click.echo("WARNING: Multi-processing support requires Python 3.4 or greater. Falling back to single-threaded processing!")
  81. cpus = 1
  82. if os.path.isdir(image_to_check):
  83. if cpus == 1:
  84. [test_image(image_file, known_names, known_face_encodings, tolerance, show_distance) for image_file in image_files_in_folder(image_to_check)]
  85. else:
  86. process_images_in_process_pool(image_files_in_folder(image_to_check), known_names, known_face_encodings, cpus, tolerance, show_distance)
  87. else:
  88. test_image(image_to_check, known_names, known_face_encodings, tolerance, show_distance)
  89. if __name__ == "__main__":
  90. main()
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...