Skip to content

Commit

Permalink
Add basic support for reading face tags
Browse files Browse the repository at this point in the history
  • Loading branch information
derneuere committed Jun 15, 2023
1 parent 96bb1eb commit f048d50
Show file tree
Hide file tree
Showing 7 changed files with 593 additions and 19 deletions.
1 change: 1 addition & 0 deletions api/exif_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ class Tags:
LENS = "EXIF:LensModel"
SUBJECT_DISTANCE = "EXIF:SubjectDistance"
DIGITAL_ZOOM_RATIO = "EXIF:DigitalZoomRatio"
REGION_INFO = "XMP:RegionInfo"
91 changes: 75 additions & 16 deletions api/models/photo.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,11 @@ def _save_captions(self, commit=True, caption=None):
if commit:
self.save()
util.logger.info(
"saved captions for image %s. caption: %s"
% (image_path, caption)
"saved captions for image %s. caption: %s" % (image_path, caption)
)
return True
except Exception:
util.logger.warning(
"could not save captions for image %s" % image_path
)
util.logger.warning("could not save captions for image %s" % image_path)
return False

def _generate_clip_embeddings(self, commit=True):
Expand Down Expand Up @@ -596,23 +593,85 @@ def _extract_rating(self, commit=True):
self.save(save_metadata=False)

def _extract_faces(self, second_try=False):
qs_unknown_person = api.models.person.Person.objects.filter(
Q(name="unknown") | Q(name=api.models.person.Person.UNKNOWN_PERSON_NAME)
)
if qs_unknown_person.count() == 0:
unknown_person = api.models.person.get_unknown_person(owner=self.owner)
else:
unknown_person = qs_unknown_person[0]

unknown_cluster: api.models.cluster.Cluster = (
api.models.cluster.get_unknown_cluster(user=self.owner)
)

(region_info,) = get_metadata(
self.main_file.path, tags=[Tags.REGION_INFO], try_sidecar=True
)

if region_info:
logger.debug(f"Extracted region_info for {self.main_file.path}")
# Log region_info
logger.debug(f"region_info: {region_info}")
# Extract faces
for region in region_info["RegionList"]:
if region["Type"] != "Face":
continue
# Find person with the name of the region with get_or_create
person = api.models.person.get_or_create_person(
name=region["Name"], owner=self.owner
)
person.save()
# Create face from the region infos
image = np.array(PIL.Image.open(self.thumbnail_big.path))
if region["Area"]["Unit"] == "normalized":
top = int(region["Area"]["Y"] * image.shape[0])
right = int(
(region["Area"]["X"] + region["Area"]["W"]) * image.shape[1]
)
bottom = int(
(region["Area"]["Y"] + region["Area"]["H"]) * image.shape[0]
)
left = int(region["Area"]["X"] * image.shape[1])
face_image = image[top:bottom, left:right]
face_image = PIL.Image.fromarray(face_image)

# Figure out which face idx it is, but reading the number of the faces of the person
idx_face = api.models.face.Face.objects.filter(person=person).count()
image_path = self.image_hash + "_" + str(idx_face) + ".jpg"

import face_recognition

face_encodings = face_recognition.face_encodings(
image, known_face_locations=[(top, right, bottom, left)]
)

face = api.models.face.Face(
image_path=image_path,
photo=self,
location_top=top,
location_right=bottom,
location_bottom=left,
location_left=right,
encoding=face_encodings[0].tobytes().hex(),
person=person,
cluster=unknown_cluster,
)
face_io = BytesIO()
face_image.save(face_io, format="JPEG")
face.image.save(face.image_path, ContentFile(face_io.getvalue()))
face_io.close()
face.save()
logger.debug(f"Created face {face} from {self.main_file.path}")
return

import face_recognition

try:
qs_unknown_person = api.models.person.Person.objects.filter(
Q(name="unknown") | Q(name=api.models.person.Person.UNKNOWN_PERSON_NAME)
)
if qs_unknown_person.count() == 0:
unknown_person = api.models.person.get_unknown_person(owner=self.owner)
else:
unknown_person = qs_unknown_person[0]

unknown_cluster: api.models.cluster.Cluster = (
api.models.cluster.get_unknown_cluster(user=self.owner)
)
image = np.array(PIL.Image.open(self.thumbnail_big.path))

face_locations = []
# Create
try:
face_locations = face_recognition.face_locations(image)
except Exception:
Expand Down
Binary file added api/tests/fixtures/niaz.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit f048d50

Please sign in to comment.