Created
June 28, 2020 00:28
-
-
Save Jeffrey-P-McAteer/c0b25c2ebfed8248b79a5d18d5997a5e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # I have a script which runs in the background. | |
| # Every 5 minutes it checks to see if a picture was taken | |
| # for YYYY_MM_DD_HH.jpg. If it does not exist, | |
| # the script takes a photo and checks if faces exist. | |
| # if so it gets saved to YYYY_MM_DD_HH.jpg. | |
| # This is a brief 20-minute excursion into the use of | |
| # perceptual hashes to join 4 months of pictures into | |
| # a video. | |
| # One run is saved at https://youtu.be/9ExS8LDD9BQ | |
| import cv2 | |
| import os, sys | |
| from PIL import Image | |
| import random | |
| # python -m pip install --user ImageHash | |
| import imagehash | |
| # Download from https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml | |
| FACE_CASCADE_F = '/j/.cache/haarcascade_frontalface_default.xml' | |
| image_folder = '/j/res/profiles/dailies/' | |
| video_name = '/tmp/video.avi' | |
| images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")] | |
| frame = cv2.imread(os.path.join(image_folder, images[0])) | |
| vid_height, vid_width, layers = frame.shape | |
| print("vid_height={}, vid_width={}".format(vid_height, vid_width)) | |
| framerate = 8 | |
| video = cv2.VideoWriter(video_name, 0, framerate, (vid_width, vid_height)) | |
| frames = [ | |
| cv2.imread(os.path.join(image_folder, image)) for image in images | |
| ] | |
| # Throw out non-face images | |
| face_cascade = cv2.CascadeClassifier(FACE_CASCADE_F) | |
| def has_face(f): | |
| global face_cascade | |
| gray = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY) | |
| faces = face_cascade.detectMultiScale(gray, 1.1, 5) | |
| if len(faces) < 1: | |
| return False | |
| return True | |
| face_frames = [f for f in frames if has_face(f)] | |
| print("Threw out {} non-face frames...".format(len(frames) - len(face_frames))) | |
| frames = face_frames | |
| for i in range(0, len(frames)): | |
| height, width, layers = frames[i].shape | |
| if height != vid_height or width != vid_width: | |
| frames[i] = cv2.resize(frames[i], (vid_width, vid_height)) | |
| print("Read in frames!") | |
| # First sort frames so similar images are next to eachother | |
| # frames = sorted(frames, key=lambda one_frame: hash(imagehash.phash( | |
| # Image.fromarray( cv2.cvtColor(one_frame, cv2.COLOR_BGR2GRAY) ) | |
| # ))) | |
| frame_phashes = [ | |
| imagehash.phash( Image.fromarray( img ) ) | |
| for img in frames | |
| ] | |
| all_frames_len = len(frames); | |
| some_idx = random.randint(0, len(frames)-1) | |
| print("Started with index {}".format(some_idx)) | |
| similar_frames = [ frames[some_idx] ] | |
| added_frame_i = [ some_idx ] | |
| # Skip last 35% of frames b/c they get erratic | |
| max_similar_frames = all_frames_len - int(0.35 * all_frames_len) | |
| while len(similar_frames) < max_similar_frames: | |
| # Find the most similar frame to similar_frames[-1]... | |
| if len(similar_frames) % 10 == 0: | |
| print("{}/{} sorted...".format(len(similar_frames), max_similar_frames)) | |
| best_frames_i = 0 | |
| while best_frames_i in added_frame_i: | |
| best_frames_i += 1 | |
| for i in range(0, len(frames)): | |
| if i in added_frame_i: | |
| continue | |
| # Compute best diff | |
| diff_best = frame_phashes[added_frame_i[-1]] - frame_phashes[best_frames_i] | |
| # Compute this diff | |
| diff_n = frame_phashes[added_frame_i[-1]] - frame_phashes[i] | |
| if diff_n < diff_best: | |
| best_frames_i = i | |
| # Add best | |
| similar_frames.append( frames[best_frames_i] ) | |
| added_frame_i.append( best_frames_i ) | |
| # Now replace frames with similar_frames | |
| frames = similar_frames | |
| print("Sorted!") | |
| # Now join them all | |
| for frame in frames: | |
| video.write(frame) | |
| cv2.destroyAllWindows() | |
| video.release() | |
| print("Wrote video! ({})".format(video_name)) | |
| os.system("mpv '{}'".format(video_name)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment