-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
145 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
""" | ||
Code related to face detection and manipulation | ||
""" | ||
|
||
#pip install facenet_pytorch | ||
|
||
from facenet_pytorch import MTCNN | ||
mtcnn = MTCNN(image_size=256, margin=80) | ||
|
||
# simplest ye olde trustworthy MTCNN for face detection with landmarks | ||
def detect(img): | ||
|
||
# Detect faces | ||
batch_boxes, batch_probs, batch_points = mtcnn.detect(img, landmarks=True) | ||
# Select faces | ||
if not mtcnn.keep_all: | ||
batch_boxes, batch_probs, batch_points = mtcnn.select_boxes( | ||
batch_boxes, batch_probs, batch_points, img, method=mtcnn.selection_method | ||
) | ||
|
||
return batch_boxes, batch_points | ||
|
||
# my version of isOdd, should make a separate repo for it :D | ||
def makeEven(_x): | ||
return _x if (_x % 2 == 0) else _x+1 | ||
|
||
# the actual scaler function | ||
def scale(boxes, _img, max_res=1_500_000, target_face=256, fixed_ratio=0, max_upscale=2, VERBOSE=False): | ||
|
||
x, y = _img.size | ||
|
||
ratio = 2 #initial ratio | ||
|
||
#scale to desired face size | ||
if (boxes is not None): | ||
if len(boxes)>0: | ||
ratio = target_face/max(boxes[0][2:]-boxes[0][:2]); | ||
ratio = min(ratio, max_upscale) | ||
if VERBOSE: print('up by', ratio) | ||
|
||
if fixed_ratio>0: | ||
if VERBOSE: print('fixed ratio') | ||
ratio = fixed_ratio | ||
|
||
x*=ratio | ||
y*=ratio | ||
|
||
#downscale to fit into max res | ||
res = x*y | ||
if res > max_res: | ||
ratio = pow(res/max_res,1/2); | ||
if VERBOSE: print(ratio) | ||
x=int(x/ratio) | ||
y=int(y/ratio) | ||
|
||
#make dimensions even, because usually NNs fail on uneven dimensions due skip connection size mismatch | ||
x = makeEven(int(x)) | ||
y = makeEven(int(y)) | ||
|
||
size = (x, y) | ||
|
||
return _img.resize(size) | ||
|
||
""" | ||
A useful scaler algorithm, based on face detection. | ||
Takes PIL.Image, returns a uniformly scaled PIL.Image | ||
boxes: a list of detected bboxes | ||
_img: PIL.Image | ||
max_res: maximum pixel area to fit into. Use to stay below the VRAM limits of your GPU. | ||
target_face: desired face size. Upscale or downscale the whole image to fit the detected face into that dimension. | ||
fixed_ratio: fixed scale. Ignores the face size, but doesn't ignore the max_res limit. | ||
max_upscale: maximum upscale ratio. Prevents from scaling images with tiny faces to a blurry mess. | ||
""" | ||
|
||
def scale_by_face_size(_img, max_res=1_500_000, target_face=256, fix_ratio=0, max_upscale=2, VERBOSE=False): | ||
boxes = None | ||
boxes, _ = detect(_img) | ||
if VERBOSE: print('boxes',boxes) | ||
img_resized = scale(boxes, _img, max_res, target_face, fix_ratio, max_upscale, VERBOSE) | ||
return img_resized | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
""" | ||
Combining frames into a video, then adding sound from the source video. | ||
frames: a glob-like pattern, for example '/content/out_resized/frame*.jpg' | ||
vid_name: path to the input video | ||
fps: fps :D | ||
out_fname: output video name. Use mp4 container by default. | ||
""" | ||
|
||
ffmpeg -f image2 -r {fps} -pattern_type glob -i "{frames}" -i "{vid_name}" -c:v copy -c:a aac -map 0:v:0 \ | ||
-map 1:a:0 -shortest -vcodec libx264 -r {fps} -crf 18 -pix_fmt yuv420p "{out_fname}" | ||
|
||
""" | ||
The simplest way to combine frames into video | ||
frames: a glob-like pattern, for example '/content/out_resized/frame*.jpg' | ||
fps: fps :D | ||
out_fname: output video name. Use mp4 container by default. | ||
""" | ||
|
||
ffmpeg -pattern_type glob -i "{frames}" -filter:v fps={fps} "{out_fname}" | ||
|
||
""" | ||
The simplest way to split a video into frames | ||
vid_name: input video' | ||
out_dir: output folder. | ||
You can change the pattern if you need more digits (increase the number in %05d pattern), or change the filename. | ||
""" | ||
|
||
ffmpeg -v quiet -i "{vid_name}" "{out_dir}/frame_%05d.jpg" |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
""" | ||
Some of the colab snippets I use on a daily basis. | ||
I've decided to store those as .py for faster access from github and easier imports. | ||
""" | ||
""" | ||
Zips a folder and downloads it. Can also copy the archive to a google drive path (or any other available to your colab instance) | ||
Use to automatically download results after some afk training or inference, before the instance resets. | ||
path: path to a folder to download. Can contain wildcards | ||
prefix: a name of your new archive | ||
drive: a folder to copy the archive to | ||
""" | ||
from google.colab import files | ||
import time | ||
|
||
def download(path, prefix, drive=''): | ||
print('\nCкачиваем...\n') | ||
timestamp = round(time.time()) | ||
!zip -r /content/{prefix}-{timestamp}.zip {path} | ||
files.download(f"/content/{prefix}-{timestamp}.zip") | ||
if drive!='': | ||
!cp "/content/{prefix}-{timestamp}.zip" {drive} | ||
|
||
|
||
""" | ||
It beeps. Use to give yourself a signal. | ||
""" | ||
from google.colab import output | ||
def beep(): | ||
output.eval_js('new Audio("https://upload.wikimedia.org/wikipedia/commons/0/05/Beep-09.ogg").play()') |