이민호

upload 보고서, codes

Showing 156 changed files with 1547 additions and 0 deletions
*.pyc
__pycache__/
/data/
\ No newline at end of file
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
from functools import partial
from multiprocessing import Pool
import os
import re
import cropper
import numpy as np
import tqdm
# ==============================================================================
# = param =
# ==============================================================================
parser = argparse.ArgumentParser()
# main
parser.add_argument('--img_dir', dest='img_dir', default='./data/img_celeba')
parser.add_argument('--save_dir', dest='save_dir', default='./data/aligned')
parser.add_argument('--landmark_file', dest='landmark_file', default='./data/landmark.txt')
parser.add_argument('--standard_landmark_file', dest='standard_landmark_file', default='./data/standard_landmark_68pts.txt')
parser.add_argument('--crop_size_h', dest='crop_size_h', type=int, default=572)
parser.add_argument('--crop_size_w', dest='crop_size_w', type=int, default=572)
parser.add_argument('--move_h', dest='move_h', type=float, default=0.25)
parser.add_argument('--move_w', dest='move_w', type=float, default=0.)
parser.add_argument('--save_format', dest='save_format', choices=['jpg', 'png'], default='jpg')
parser.add_argument('--n_worker', dest='n_worker', type=int, default=8)
# others
parser.add_argument('--face_factor', dest='face_factor', type=float, help='The factor of face area relative to the output image.', default=0.45)
parser.add_argument('--align_type', dest='align_type', choices=['affine', 'similarity'], default='similarity')
parser.add_argument('--order', dest='order', type=int, choices=[0, 1, 2, 3, 4, 5], help='The order of interpolation.', default=3)
parser.add_argument('--mode', dest='mode', choices=['constant', 'edge', 'symmetric', 'reflect', 'wrap'], default='edge')
args = parser.parse_args()
# ==============================================================================
# = opencv first =
# ==============================================================================
_DEAFAULT_JPG_QUALITY = 95
try:
import cv2
imread = cv2.imread
imwrite = partial(cv2.imwrite, params=[int(cv2.IMWRITE_JPEG_QUALITY), _DEAFAULT_JPG_QUALITY])
align_crop = cropper.align_crop_opencv
print('Use OpenCV')
except:
import skimage.io as io
imread = io.imread
imwrite = partial(io.imsave, quality=_DEAFAULT_JPG_QUALITY)
align_crop = cropper.align_crop_skimage
print('Importing OpenCv fails. Use scikit-image')
# ==============================================================================
# = run =
# ==============================================================================
# count landmarks
with open(args.landmark_file) as f:
line = f.readline()
n_landmark = len(re.split('[ ]+', line)[1:]) // 2
# load standard landmark
standard_landmark = np.genfromtxt(args.standard_landmark_file, dtype=np.float).reshape(n_landmark, 2)
standard_landmark[:, 0] += args.move_w
standard_landmark[:, 1] += args.move_h
# data dir
save_dir = os.path.join(args.save_dir, 'align_size(%d,%d)_move(%.3f,%.3f)_face_factor(%.3f)_%s' % (args.crop_size_h, args.crop_size_w, args.move_h, args.move_w, args.face_factor, args.save_format))
data_dir = os.path.join(save_dir, 'data')
if not os.path.isdir(data_dir):
os.makedirs(data_dir)
def work(name, landmark) -> str: # a single work
for _ in range(3): # try three times
try:
img = imread(os.path.join(args.img_dir, name))
img_crop, tformed_landmarks = align_crop(img,
landmark,
standard_landmark,
crop_size=(args.crop_size_h, args.crop_size_w),
face_factor=args.face_factor,
align_type=args.align_type,
order=args.order,
mode=args.mode)
name = os.path.splitext(name)[0] + '.' + args.save_format
path = os.path.join(data_dir, name)
if not os.path.isdir(os.path.split(path)[0]):
os.makedirs(os.path.split(path)[0])
imwrite(path, img_crop)
tformed_landmarks.shape = -1
name_landmark_str = ('%s' + ' %.1f' * n_landmark * 2) % ((name, ) + tuple(tformed_landmarks))
return name_landmark_str
except:
print('%s fails!' % name)
if __name__ == "__main__":
img_names = np.genfromtxt(args.landmark_file, dtype=np.str, usecols=0)
landmarks = np.genfromtxt(args.landmark_file, dtype=np.float,
usecols=range(1, n_landmark * 2 + 1)).reshape(-1, n_landmark, 2)
n_pics = len(img_names)
landmarks_path = os.path.join(save_dir, 'landmark.txt')
f = open(landmarks_path, 'w')
pool = Pool(args.n_worker)
bar = tqdm.tqdm(total=n_pics)
tasks = []
for i in range(n_pics):
tasks.append(pool.apply_async(work, (img_names[i], landmarks[i]), callback=lambda _: bar.update()))
try:
result = tasks.pop(0).get()
if result is not None and result != "":
f.write(result + '\n')
except:
pass
pool.close()
pool.join()
bar.close()
f.close()
\ No newline at end of file
import numpy as np
def align_crop_opencv(img,
src_landmarks,
standard_landmarks,
crop_size=512,
face_factor=0.7,
align_type='similarity',
order=3,
mode='edge'):
"""Align and crop a face image by landmarks.
Arguments:
img : Face image to be aligned and cropped.
src_landmarks : [[x_1, y_1], ..., [x_n, y_n]].
standard_landmarks : Standard shape, should be normalized.
crop_size : Output image size, should be 1. int for (crop_size, crop_size)
or 2. (int, int) for (crop_size_h, crop_size_w).
face_factor : The factor of face area relative to the output image.
align_type : 'similarity' or 'affine'.
order : The order of interpolation. The order has to be in the range 0-5:
- 0: INTER_NEAREST
- 1: INTER_LINEAR
- 2: INTER_AREA
- 3: INTER_CUBIC
- 4: INTER_LANCZOS4
- 5: INTER_LANCZOS4
mode : One of ['constant', 'edge', 'symmetric', 'reflect', 'wrap'].
Points outside the boundaries of the input are filled according
to the given mode.
"""
# set OpenCV
import cv2
inter = {0: cv2.INTER_NEAREST, 1: cv2.INTER_LINEAR, 2: cv2.INTER_AREA,
3: cv2.INTER_CUBIC, 4: cv2.INTER_LANCZOS4, 5: cv2.INTER_LANCZOS4}
border = {'constant': cv2.BORDER_CONSTANT, 'edge': cv2.BORDER_REPLICATE,
'symmetric': cv2.BORDER_REFLECT, 'reflect': cv2.BORDER_REFLECT101,
'wrap': cv2.BORDER_WRAP}
# check
assert align_type in ['affine', 'similarity'], 'Invalid `align_type`! Allowed: %s!' % ['affine', 'similarity']
assert order in [0, 1, 2, 3, 4, 5], 'Invalid `order`! Allowed: %s!' % [0, 1, 2, 3, 4, 5]
assert mode in ['constant', 'edge', 'symmetric', 'reflect', 'wrap'], 'Invalid `mode`! Allowed: %s!' % ['constant', 'edge', 'symmetric', 'reflect', 'wrap']
# crop size
if isinstance(crop_size, (list, tuple)) and len(crop_size) == 2:
crop_size_h = crop_size[0]
crop_size_w = crop_size[1]
elif isinstance(crop_size, int):
crop_size_h = crop_size_w = crop_size
else:
raise Exception('Invalid `crop_size`! `crop_size` should be 1. int for (crop_size, crop_size) or 2. (int, int) for (crop_size_h, crop_size_w)!')
# estimate transform matrix
trg_landmarks = standard_landmarks * max(crop_size_h, crop_size_w) * face_factor + np.array([crop_size_w // 2, crop_size_h // 2])
if align_type == 'affine':
tform = cv2.estimateAffine2D(trg_landmarks, src_landmarks, ransacReprojThreshold=np.Inf)[0]
else:
tform = cv2.estimateAffinePartial2D(trg_landmarks, src_landmarks, ransacReprojThreshold=np.Inf)[0]
# warp image by given transform
output_shape = (crop_size_h, crop_size_w)
img_crop = cv2.warpAffine(img, tform, output_shape[::-1], flags=cv2.WARP_INVERSE_MAP + inter[order], borderMode=border[mode])
# get transformed landmarks
tformed_landmarks = cv2.transform(np.expand_dims(src_landmarks, axis=0), cv2.invertAffineTransform(tform))[0]
return img_crop, tformed_landmarks
def align_crop_skimage(img,
src_landmarks,
standard_landmarks,
crop_size=512,
face_factor=0.7,
align_type='similarity',
order=3,
mode='edge'):
"""Align and crop a face image by landmarks.
Arguments:
img : Face image to be aligned and cropped.
src_landmarks : [[x_1, y_1], ..., [x_n, y_n]].
standard_landmarks : Standard shape, should be normalized.
crop_size : Output image size, should be 1. int for (crop_size, crop_size)
or 2. (int, int) for (crop_size_h, crop_size_w).
face_factor : The factor of face area relative to the output image.
align_type : 'similarity' or 'affine'.
order : The order of interpolation. The order has to be in the range 0-5:
- 0: INTER_NEAREST
- 1: INTER_LINEAR
- 2: INTER_AREA
- 3: INTER_CUBIC
- 4: INTER_LANCZOS4
- 5: INTER_LANCZOS4
mode : One of ['constant', 'edge', 'symmetric', 'reflect', 'wrap'].
Points outside the boundaries of the input are filled according
to the given mode.
"""
raise NotImplementedError("'align_crop_skimage' is not implemented!")
This diff could not be displayed because it is too large.
# Auto detect text files and perform LF normalization
* text=auto
*.pyc
docs
data
lfw
lfw_40
.idea
loss
vgg_face_dataset
saved_network
loss
z_detect_face.py
z_main.py
*.npy
*.Lnk
data1
data1_masked
scratch.py
subset
subset_masked
vgg_face_dataset
*.mp4
ML_examples
*.pptx
datasets
*.dat
*.docx
theme: jekyll-theme-cayman
\ No newline at end of file
# Author: aqeelanwar
# Created: 27 April,2020, 10:22 PM
# Email: aqeel.anwar@gatech.edu
import argparse
import dlib
from utils.aux_functions import *
# Command-line input setup
parser = argparse.ArgumentParser(
description="MaskTheFace - Python code to mask faces dataset"
)
parser.add_argument(
"--path",
type=str,
default="",
help="Path to either the folder containing images or the image itself",
)
parser.add_argument(
"--mask_type",
type=str,
default="surgical",
choices=["surgical", "N95", "KN95", "cloth", "gas", "inpaint", "random", "all"],
help="Type of the mask to be applied. Available options: all, surgical_blue, surgical_green, N95, cloth",
)
parser.add_argument(
"--pattern",
type=str,
default="",
help="Type of the pattern. Available options in masks/textures",
)
parser.add_argument(
"--pattern_weight",
type=float,
default=0.5,
help="Weight of the pattern. Must be between 0 and 1",
)
parser.add_argument(
"--color",
type=str,
default="#0473e2",
help="Hex color value that need to be overlayed to the mask",
)
parser.add_argument(
"--color_weight",
type=float,
default=0.5,
help="Weight of the color intensity. Must be between 0 and 1",
)
parser.add_argument(
"--code",
type=str,
# default="cloth-masks/textures/check/check_4.jpg, cloth-#e54294, cloth-#ff0000, cloth, cloth-masks/textures/others/heart_1.png, cloth-masks/textures/fruits/pineapple.png, N95, surgical_blue, surgical_green",
default="",
help="Generate specific formats",
)
parser.add_argument(
"--verbose", dest="verbose", action="store_true", help="Turn verbosity on"
)
parser.add_argument(
"--write_original_image",
dest="write_original_image",
action="store_true",
help="If true, original image is also stored in the masked folder",
)
parser.set_defaults(feature=False)
args = parser.parse_args()
args.write_path = args.path + "_masked"
# Set up dlib face detector and predictor
args.detector = dlib.get_frontal_face_detector()
path_to_dlib_model = "dlib_models/shape_predictor_68_face_landmarks.dat"
if not os.path.exists(path_to_dlib_model):
download_dlib_model()
args.predictor = dlib.shape_predictor(path_to_dlib_model)
# Extract data from code
mask_code = "".join(args.code.split()).split(",")
args.code_count = np.zeros(len(mask_code))
args.mask_dict_of_dict = {}
for i, entry in enumerate(mask_code):
mask_dict = {}
mask_color = ""
mask_texture = ""
mask_type = entry.split("-")[0]
if len(entry.split("-")) == 2:
mask_variation = entry.split("-")[1]
if "#" in mask_variation:
mask_color = mask_variation
else:
mask_texture = mask_variation
mask_dict["type"] = mask_type
mask_dict["color"] = mask_color
mask_dict["texture"] = mask_texture
args.mask_dict_of_dict[i] = mask_dict
# Check if path is file or directory or none
is_directory, is_file, is_other = check_path(args.path)
display_MaskTheFace()
if is_directory:
path, dirs, files = os.walk(args.path).__next__()
file_count = len(files)
dirs_count = len(dirs)
if len(files) > 0:
print_orderly("Masking image files", 60)
# Process files in the directory if any
for f in tqdm(files):
image_path = path + "/" + f
write_path = path + "_masked"
if not os.path.isdir(write_path):
os.makedirs(write_path)
if is_image(image_path):
# Proceed if file is image
if args.verbose:
str_p = "Processing: " + image_path
tqdm.write(str_p)
split_path = f.rsplit(".")
masked_image, mask, mask_binary_array, original_image = mask_image(
image_path, args
)
for i in range(len(mask)):
w_path = (
write_path
+ "/"
+ split_path[0]
+ "_"
+ "masked"
+ "."
+ split_path[1]
)
img = masked_image[i]
binary_img = mask_binary_array[i]
cv2.imwrite(w_path, img)
cv2.imwrite(
path + "_binary/" + split_path[0] + "_binary" + "." + split_path[1],
binary_img,
)
cv2.imwrite(
path + "_original/" + split_path[0] + "." + split_path[1],
original_image,
)
print_orderly("Masking image directories", 60)
# Process directories withing the path provided
for d in tqdm(dirs):
dir_path = args.path + "/" + d
dir_write_path = args.write_path + "/" + d
if not os.path.isdir(dir_write_path):
os.makedirs(dir_write_path)
_, _, files = os.walk(dir_path).__next__()
# Process each files within subdirectory
for f in files:
image_path = dir_path + "/" + f
if args.verbose:
str_p = "Processing: " + image_path
tqdm.write(str_p)
write_path = dir_write_path
if is_image(image_path):
# Proceed if file is image
split_path = f.rsplit(".")
masked_image, mask, mask_binary, original_image = mask_image(
image_path, args
)
for i in range(len(mask)):
w_path = (
write_path
+ "/"
+ split_path[0]
+ "_"
+ "masked"
+ "."
+ split_path[1]
)
w_path_original = write_path + "/" + f
img = masked_image[i]
binary_img = mask_binary[i]
cv2.imwrite(
path
+ "_binary/"
+ split_path[0]
+ "_binary"
+ "."
+ split_path[1],
binary_img,
)
# Write the masked image
cv2.imwrite(w_path, img)
if args.write_original_image:
# Write the original image
cv2.imwrite(w_path_original, original_image)
if args.verbose:
print(args.code_count)
# Process if the path was a file
elif is_file:
print("Masking image file")
image_path = args.path
write_path = args.path.rsplit(".")[0]
if is_image(image_path):
# Proceed if file is image
# masked_images, mask, mask_binary_array, original_image
masked_image, mask, mask_binary_array, original_image = mask_image(
image_path, args
)
for i in range(len(mask)):
w_path = write_path + "_" + "masked" + "." + args.path.rsplit(".")[1]
img = masked_image[i]
binary_img = mask_binary_array[i]
cv2.imwrite(w_path, img)
cv2.imwrite(write_path + "_binary." + args.path.rsplit(".")[1], binary_img)
else:
print("Path is neither a valid file or a valid directory")
print("Processing Done")
[surgical]
template: masks/templates/surgical.png
mask_a: 21, 97
mask_b: 307, 22
mask_c: 600, 99
mask_d: 25, 322
mask_e: 295, 470
mask_f: 600, 323
[surgical_left]
template: masks/templates/surgical_left.png
mask_a: 39, 27
mask_b: 130, 9
mask_c: 567, 20
mask_d: 87, 207
mask_e: 168, 302
mask_f: 568, 202
[surgical_right]
template: masks/templates/surgical_right.png
mask_a: 3, 20
mask_b: 440, 9
mask_c: 531, 27
mask_d: 2, 202
mask_e: 402, 302
mask_f: 483, 207
[surgical_green]
template: masks/templates/surgical_green.png
mask_a: 21, 97
mask_b: 307, 22
mask_c: 600, 99
mask_d: 25, 322
mask_e: 295, 470
mask_f: 600, 323
[surgical_green_left]
template: masks/templates/surgical_green_left.png
mask_a: 39, 27
mask_b: 130, 9
mask_c: 567, 20
mask_d: 87, 207
mask_e: 168, 302
mask_f: 568, 202
[surgical_green_right]
template: masks/templates/surgical_green_right.png
mask_a: 3, 20
mask_b: 440, 9
mask_c: 531, 27
mask_d: 2, 202
mask_e: 402, 302
mask_f: 483, 207
[surgical_blue]
template: masks/templates/surgical_blue.png
mask_a: 21, 97
mask_b: 307, 22
mask_c: 600, 99
mask_d: 25, 322
mask_e: 295, 470
mask_f: 600, 323
[surgical_blue_left]
template: masks/templates/surgical_blue_left.png
mask_a: 39, 27
mask_b: 130, 9
mask_c: 567, 20
mask_d: 87, 207
mask_e: 168, 302
mask_f: 568, 202
[surgical_blue_right]
template: masks/templates/surgical_blue_right.png
mask_a: 3, 20
mask_b: 440, 9
mask_c: 531, 27
mask_d: 2, 202
mask_e: 402, 302
mask_f: 483, 207
[N95]
template: masks/templates/N95.png
mask_a: 15, 119
mask_b: 327, 5
mask_c: 640, 93
mask_d: 13, 285
mask_e: 351, 518
mask_f: 645, 285
;[N95_left]
;template: masks/N95_left.png
;mask_a: 176, 121
;mask_b: 313, 46
;mask_c: 799, 135
;mask_d: 97, 438
;mask_e: 329, 627
;mask_f: 791, 401
[N95_right]
template: masks/templates/N95_right.png
mask_c: 979, 331
mask_b: 806, 172
mask_a: 12, 222
mask_f: 907, 762
mask_e: 577, 875
mask_d: -4, 632
[N95_left]
template: masks/templates/N95_left.png
mask_a: 193, 331
mask_b: 366, 172
mask_c: 1160, 222
mask_d: 265, 762
mask_e: 595, 875
mask_f: 1176, 632
[cloth_left]
template: masks/templates/cloth_left.png
mask_a: 65, 93
mask_b: 162, 15
mask_c: 672, 75
mask_d: 114, 296
mask_e: 207, 443
mask_f: 671, 341
[cloth_right]
template: masks/templates/cloth_right.png
mask_a: 98, 93
mask_b: 608, 15
mask_c: 705, 75
mask_d: 99, 296
mask_e: 563, 443
mask_f: 656, 341
[cloth]
template: masks/templates/cloth.png
mask_a: 122, 90
mask_b: 405, 7
mask_c: 686, 79
mask_d: 165, 323
mask_e: 406, 509
mask_f: 653, 311
[gas]
template: masks/templates/gas.png
mask_a: 330, 431
mask_b: 873, 117
mask_c: 1494, 434
mask_d: 430, 754
mask_e: 869, 1100
mask_f: 1400, 710
[gas_left]
template: masks/templates/gas_left.png
mask_a: 239, 238
mask_b: 317, 42
mask_c: 965, 239
mask_d: 224, 404
mask_e: 337, 502
mask_f: 963, 406
[gas_right]
template: masks/templates/gas_right.png
mask_c: 621, 238
mask_b: 543, 60
mask_a: -105, 239
mask_f: 636, 404
mask_e: 523, 502
mask_d: -103, 406
[KN95]
template: masks/templates/KN95.png
mask_a: 20, 47
mask_b: 410, 5
mask_c: 760, 55
mask_d: 75, 340
mask_e: 398, 600
mask_f: 671, 320
[KN95_left]
template: masks/templates/KN95_left.png
mask_a: 52, 258
mask_b: 207, 100
mask_c: 730, 80
mask_d: 210, 408
mask_e: 335, 604
mask_f: 770, 270
[KN95_right]
template: masks/templates/KN95_right.png
mask_c: 664, 258
mask_b: 509, 100
mask_a: -14, 80
mask_f: 506, 408
mask_e: 381, 604
mask_d: -54, 270
[empty]
[empty_left]
[empty_right]
[inpaint]
[inpaint_left]
[inpaint_right]
certifi==2020.4.5.1
click==7.1.2
dlib==19.19.0
dotmap==1.3.14
face-recognition==1.3.0
face-recognition-models==0.3.0
numpy==1.18.4
opencv-python==4.2.0.34
Pillow==7.1.2
tqdm==4.46.0
wincertstore==0.2
imutils==0.5.3
requests==2.24.0
# Author: Aqeel Anwar(ICSRL)
# Created: 7/30/2020, 7:43 AM
# Email: aqeel.anwar@gatech.edu
\ No newline at end of file
This diff is collapsed. Click to expand it.
# Author: aqeelanwar
# Created: 6 July,2020, 12:14 AM
# Email: aqeel.anwar@gatech.edu
from PIL import ImageColor
import cv2
import numpy as np
COLOR = [
"#fc1c1a",
"#177ABC",
"#94B6D2",
"#A5AB81",
"#DD8047",
"#6b425e",
"#e26d5a",
"#c92c48",
"#6a506d",
"#ffc900",
"#ffffff",
"#000000",
"#49ff00",
]
def color_the_mask(mask_image, color, intensity):
assert 0 <= intensity <= 1, "intensity should be between 0 and 1"
RGB_color = ImageColor.getcolor(color, "RGB")
RGB_color = (RGB_color[2], RGB_color[1], RGB_color[0])
orig_shape = mask_image.shape
bit_mask = mask_image[:, :, 3]
mask_image = mask_image[:, :, 0:3]
color_image = np.full(mask_image.shape, RGB_color, np.uint8)
mask_color = cv2.addWeighted(mask_image, 1 - intensity, color_image, intensity, 0)
mask_color = cv2.bitwise_and(mask_color, mask_color, mask=bit_mask)
colored_mask = np.zeros(orig_shape, dtype=np.uint8)
colored_mask[:, :, 0:3] = mask_color
colored_mask[:, :, 3] = bit_mask
return colored_mask
def texture_the_mask(mask_image, texture_path, intensity):
assert 0 <= intensity <= 1, "intensity should be between 0 and 1"
orig_shape = mask_image.shape
bit_mask = mask_image[:, :, 3]
mask_image = mask_image[:, :, 0:3]
texture_image = cv2.imread(texture_path)
texture_image = cv2.resize(texture_image, (orig_shape[1], orig_shape[0]))
mask_texture = cv2.addWeighted(
mask_image, 1 - intensity, texture_image, intensity, 0
)
mask_texture = cv2.bitwise_and(mask_texture, mask_texture, mask=bit_mask)
textured_mask = np.zeros(orig_shape, dtype=np.uint8)
textured_mask[:, :, 0:3] = mask_texture
textured_mask[:, :, 3] = bit_mask
return textured_mask
# cloth_mask = cv2.imread("masks/templates/cloth.png", cv2.IMREAD_UNCHANGED)
# # cloth_mask = color_the_mask(cloth_mask, color=COLOR[0], intensity=0.5)
# path = "masks/textures"
# path, dir, files = os.walk(path).__next__()
# first_frame = True
# col_limit = 6
# i = 0
# # img_concat_row=[]
# img_concat = []
# # for f in files:
# # if "._" not in f:
# # print(f)
# # i += 1
# # texture_image = cv2.imread(os.path.join(path, f))
# # m = texture_the_mask(cloth_mask, texture_image, intensity=0.5)
# # if first_frame:
# # img_concat_row = m
# # first_frame = False
# # else:
# # img_concat_row = cv2.hconcat((img_concat_row, m))
# #
# # if i % col_limit == 0:
# # if len(img_concat) > 0:
# # img_concat = cv2.vconcat((img_concat, img_concat_row))
# # else:
# # img_concat = img_concat_row
# # first_frame = True
#
# ## COlor the mask
# thresholds = np.arange(0.1,0.9,0.05)
# for intensity in thresholds:
# c=COLOR[2]
# # intensity = 0.5
# if "._" not in c:
# print(intensity)
# i += 1
# # texture_image = cv2.imread(os.path.join(path, f))
# m = color_the_mask(cloth_mask, c, intensity=intensity)
# if first_frame:
# img_concat_row = m
# first_frame = False
# else:
# img_concat_row = cv2.hconcat((img_concat_row, m))
#
# if i % col_limit == 0:
# if len(img_concat) > 0:
# img_concat = cv2.vconcat((img_concat, img_concat_row))
# else:
# img_concat = img_concat_row
# first_frame = True
#
#
# cv2.imshow("k", img_concat)
# cv2.imwrite("combine_N95_left.png", img_concat)
# cv2.waitKey(0)
# cc = 1
__ __ _ _______ _ ______
| \/ | | |__ __| | | ____|
| \ / | __ _ ___| | _| | | |__ ___| |__ __ _ ___ ___
| |\/| |/ _` / __| |/ / | | '_ \ / _ \ __/ _` |/ __/ _ \
| | | | (_| \__ \ <| | | | | | __/ | | (_| | (_| __/
|_| |_|\__,_|___/_|\_\_| |_| |_|\___|_| \__,_|\___\___|
# Author: Aqeel Anwar(ICSRL)
# Created: 7/30/2020, 1:44 PM
# Email: aqeel.anwar@gatech.edu
# Code resued from https://stackoverflow.com/questions/38511444/python-download-files-from-google-drive-using-url
# Make sure you run this from parent folder and not from utils folder i.e.
# python utils/fetch_dataset.py
import requests, os
from zipfile import ZipFile
import argparse
import urllib
parser = argparse.ArgumentParser(
description="Download dataset - Python code to download associated datasets"
)
parser.add_argument(
"--dataset",
type=str,
default="mfr2",
help="Name of the dataset - Details on available datasets can be found at GitHub Page",
)
args = parser.parse_args()
def download_file_from_google_drive(id, destination):
URL = "https://docs.google.com/uc?export=download"
session = requests.Session()
response = session.get(URL, params={"id": id}, stream=True)
token = get_confirm_token(response)
if token:
params = {"id": id, "confirm": token}
response = session.get(URL, params=params, stream=True)
save_response_content(response, destination)
def get_confirm_token(response):
for key, value in response.cookies.items():
if key.startswith("download_warning"):
return value
return None
def save_response_content(response, destination):
CHUNK_SIZE = 32768
print(destination)
with open(destination, "wb") as f:
for chunk in response.iter_content(CHUNK_SIZE):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
def download(t_url):
response = urllib.request.urlopen(t_url)
data = response.read()
txt_str = str(data)
lines = txt_str.split("\\n")
return lines
def Convert(lst):
it = iter(lst)
res_dct = dict(zip(it, it))
return res_dct
if __name__ == "__main__":
# Fetch the latest download_links.txt file from GitHub
link = "https://raw.githubusercontent.com/aqeelanwar/MaskTheFace/master/datasets/download_links.txt"
links_dict = Convert(
download(link)[0]
.replace(":", "\n")
.replace("b'", "")
.replace("'", "")
.replace(" ", "")
.split("\n")
)
file_id = links_dict[args.dataset]
destination = "datasets\_.zip"
print("Downloading: ", args.dataset)
download_file_from_google_drive(file_id, destination)
print("Extracting: ", args.dataset)
with ZipFile(destination, "r") as zipObj:
# Extract all the contents of zip file in current directory
zipObj.extractall(destination.rsplit(os.path.sep, 1)[0])
os.remove(destination)
# Author: aqeelanwar
# Created: 4 May,2020, 1:30 AM
# Email: aqeel.anwar@gatech.edu
import numpy as np
from numpy.linalg import eig, inv
def fitEllipse(x,y):
x = x[:,np.newaxis]
y = y[:,np.newaxis]
D = np.hstack((x*x, x*y, y*y, x, y, np.ones_like(x)))
S = np.dot(D.T,D)
C = np.zeros([6,6])
C[0,2] = C[2,0] = 2; C[1,1] = -1
E, V = eig(np.dot(inv(S), C))
n = np.argmax(np.abs(E))
a = V[:,n]
return a
def ellipse_center(a):
b,c,d,f,g,a = a[1]/2, a[2], a[3]/2, a[4]/2, a[5], a[0]
num = b*b-a*c
x0=(c*d-b*f)/num
y0=(a*f-b*d)/num
return np.array([x0,y0])
def ellipse_angle_of_rotation( a ):
b,c,d,f,g,a = a[1]/2, a[2], a[3]/2, a[4]/2, a[5], a[0]
return 0.5*np.arctan(2*b/(a-c))
def ellipse_axis_length( a ):
b,c,d,f,g,a = a[1]/2, a[2], a[3]/2, a[4]/2, a[5], a[0]
up = 2*(a*f*f+c*d*d+g*b*b-2*b*d*f-a*c*g)
down1=(b*b-a*c)*( (c-a)*np.sqrt(1+4*b*b/((a-c)*(a-c)))-(c+a))
down2=(b*b-a*c)*( (a-c)*np.sqrt(1+4*b*b/((a-c)*(a-c)))-(c+a))
res1=np.sqrt(up/down1)
res2=np.sqrt(up/down2)
return np.array([res1, res2])
def ellipse_angle_of_rotation2( a ):
b,c,d,f,g,a = a[1]/2, a[2], a[3]/2, a[4]/2, a[5], a[0]
if b == 0:
if a > c:
return 0
else:
return np.pi/2
else:
if a > c:
return np.arctan(2*b/(a-c))/2
else:
return np.pi/2 + np.arctan(2*b/(a-c))/2
# a = fitEllipse(x,y)
# center = ellipse_center(a)
# #phi = ellipse_angle_of_rotation(a)
# phi = ellipse_angle_of_rotation2(a)
# axes = ellipse_axis_length(a)
#
# print("center = ", center)
# print("angle of rotation = ", phi)
# print("axes = ", axes)
# Author: aqeelanwar
# Created: 2 May,2020, 2:49 AM
# Email: aqeel.anwar@gatech.edu
from tkinter import filedialog
from tkinter import *
import cv2, os
mouse_pts = []
def get_mouse_points(event, x, y, flags, param):
global mouseX, mouseY, mouse_pts
if event == cv2.EVENT_LBUTTONDOWN:
mouseX, mouseY = x, y
cv2.circle(mask_im, (x, y), 10, (0, 255, 255), 10)
if "mouse_pts" not in globals():
mouse_pts = []
mouse_pts.append((x, y))
# print("Point detected")
# print((x,y))
root = Tk()
filename = filedialog.askopenfilename(
initialdir="/",
title="Select file",
filetypes=(("PNG files", "*.PNG"), ("png files", "*.png"), ("All files", "*.*")),
)
root.destroy()
filename_split = os.path.split(filename)
folder = filename_split[0]
file = filename_split[1]
file_split = file.split(".")
new_filename = folder + "/" + file_split[0] + "_marked." + file_split[-1]
mask_im = cv2.imread(filename)
cv2.namedWindow("Mask")
cv2.setMouseCallback("Mask", get_mouse_points)
while True:
cv2.imshow("Mask", mask_im)
cv2.waitKey(1)
if len(mouse_pts) == 6:
cv2.destroyWindow("Mask")
break
first_frame_display = False
points = mouse_pts
print(points)
print("----------------------------------------------------------------")
print("Copy the following code and paste it in masks.cfg")
print("----------------------------------------------------------------")
name_points = ["a", "b", "c", "d", "e", "f"]
mask_title = "[" + file_split[0] + "]"
print(mask_title)
print("template: ", filename)
for i in range(len(mouse_pts)):
name = (
"mask_"
+ name_points[i]
+ ": "
+ str(mouse_pts[i][0])
+ ","
+ str(mouse_pts[i][1])
)
print(name)
cv2.imwrite(new_filename, mask_im)
# Author: Aqeel Anwar(ICSRL)
# Created: 9/20/2019, 12:43 PM
# Email: aqeel.anwar@gatech.edu
from configparser import ConfigParser
from dotmap import DotMap
def ConvertIfStringIsInt(input_string):
try:
float(input_string)
try:
if int(input_string) == float(input_string):
return int(input_string)
else:
return float(input_string)
except ValueError:
return float(input_string)
except ValueError:
return input_string
def read_cfg(config_filename="masks/masks.cfg", mask_type="surgical", verbose=False):
parser = ConfigParser()
parser.optionxform = str
parser.read(config_filename)
cfg = DotMap()
section_name = mask_type
if verbose:
hyphens = "-" * int((80 - len(config_filename)) / 2)
print(hyphens + " " + config_filename + " " + hyphens)
# for section_name in parser.sections():
if verbose:
print("[" + section_name + "]")
for name, value in parser.items(section_name):
value = ConvertIfStringIsInt(value)
if name != "template":
cfg[name] = tuple(int(s) for s in value.split(","))
else:
cfg[name] = value
spaces = " " * (30 - len(name))
if verbose:
print(name + ":" + spaces + str(cfg[name]))
return cfg
This diff is collapsed. Click to expand it.
from .config import Config
\ No newline at end of file
import yaml
class Config():
def __init__(self, yaml_path):
yaml_file = open(yaml_path)
self._attr = yaml.load(yaml_file, Loader=yaml.FullLoader)['settings']
def __getattr__(self, attr):
try:
return self._attr[attr]
except KeyError:
return None
settings:
root_dir: "./datasets/celeba/images/"
checkpoint_path: "weights"
sample_folder: "sample"
cuda: True
lr: 0.001
batch_size: 2
num_workers: 4
step_iters: [10000, 15000, 20000]
gamma: 0.1
d_num_layers: 3
visualize_per_iter: 500
save_per_iter: 500
print_per_iter: 10
num_epochs: 100
lambda_G: 1.0
lambda_rec_1: 100.0
lambda_rec_2: 100.0
lambda_per: 10.0
img_size: 512
settings:
root_dir: "./datasets/places365_10classes"
checkpoint_path: "/content/drive/MyDrive/weights/Places365 Inpainting/phase 3"
sample_folder: "/content/drive/MyDrive/results/Places365 Inpainting/phase 3"
cuda: True
lr: 0.0001
batch_size: 8
num_workers: 4
step_iters: [50000, 75000, 100000]
gamma: 0.1
d_num_layers: 3
visualize_per_iter: 500
save_per_iter: 500
print_per_iter: 10
num_epochs: 100
lambda_G: 0.3
lambda_rec_1: 10.0
lambda_rec_2: 10.0
lambda_per: 1.0
img_size: 256
max_angle: 4
max_len: 50
max_width: 30
times: 15
settings:
root_dir: "./datasets/celeba/images/"
train_anns: "./datasets/celeba/annotations/train.csv"
val_anns: "./datasets/celeba/annotations/val.csv"
checkpoint_path: "weights" #"/content/drive/MyDrive/weights/Places365 Inpainting/unet/phase 1"
sample_folder: "sample" #"/content/drive/MyDrive/results/Places365 Inpainting/unet/phase 1"
cuda: True
lr: 0.001
batch_size: 4
num_workers: 4
step_iters: [50000, 75000, 100000]
gamma: 0.1
visualize_per_iter: 1000
save_per_iter: 1000
print_per_iter: 10
num_epochs: 100
img_size: 512
from .dataset import Places365Dataset, FacemaskDataset
from .dataset_seg import FacemaskSegDataset
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
import os
import csv
f = open("./datasets/celeba/annotations/train.csv", "w", newline="")
wr = csv.writer(f)
wr.writerow(["_", "img_name", "mask_name"])
for i in range(23304):
wr.writerow(
[
i,
"celeba512_30k_masked/"
+ os.listdir("./datasets/celeba/images/celeba512_30k_masked")[i],
"celeba512_30k_binary/"
+ os.listdir("./datasets/celeba/images/celeba512_30k_binary")[i],
]
)
f.close()
f = open("./datasets/celeba/annotations/val.csv", "w", newline="")
wr = csv.writer(f)
wr.writerow(["_", "img_name", "mask_name"])
for i in range(23304, 29131):
wr.writerow(
[
i,
"celeba512_30k_masked/"
+ os.listdir("./datasets/celeba/images/celeba512_30k_masked")[i],
"celeba512_30k_binary/"
+ os.listdir("./datasets/celeba/images/celeba512_30k_binary")[i],
]
)
f.close()
import os
import torch
import torch.nn as nn
import torch.utils.data as data
import cv2
import numpy as np
from tqdm import tqdm
class Places365Dataset(data.Dataset):
def __init__(self, cfg):
self.root_dir = cfg.root_dir
self.cfg = cfg
self.load_images()
def load_images(self):
self.fns =[]
idx = 0
img_paths = os.listdir(self.root_dir)
for cls_id in img_paths:
paths = os.path.join(self.root_dir, cls_id)
file_paths = os.listdir(paths)
for img_name in file_paths:
filename = os.path.join(paths, img_name)
self.fns.append(filename)
def __getitem__(self, index):
img_path = self.fns[index]
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (self.cfg.img_size, self.cfg.img_size))
mask = self.random_ff_mask(
shape = self.cfg.img_size,
max_angle = self.cfg.max_angle,
max_len = self.cfg.max_len,
max_width = self.cfg.max_width,
times = self.cfg.times)
img = torch.from_numpy(img.astype(np.float32) / 255.0).permute(2, 0, 1).contiguous()
mask = torch.from_numpy(mask.astype(np.float32)).contiguous()
return img, mask
def collate_fn(self, batch):
imgs = torch.stack([i[0] for i in batch])
masks = torch.stack([i[1] for i in batch])
return {
'imgs': imgs,
'masks': masks
}
def __len__(self):
return len(self.fns)
def random_ff_mask(self, shape = 256 , max_angle = 4, max_len = 50, max_width = 20, times = 15):
"""Generate a random free form mask with configuration.
Args:
config: Config should have configuration including IMG_SHAPES,
VERTICAL_MARGIN, HEIGHT, HORIZONTAL_MARGIN, WIDTH.
Returns:
tuple: (top, left, height, width)
"""
height = shape
width = shape
mask = np.zeros((height, width), np.float32)
times = np.random.randint(10, times)
for i in range(times):
start_x = np.random.randint(width)
start_y = np.random.randint(height)
for j in range(1 + np.random.randint(5)):
angle = 0.01 + np.random.randint(max_angle)
if i % 2 == 0:
angle = 2 * 3.1415926 - angle
length = 10 + np.random.randint(max_len)
brush_w = 5 + np.random.randint(max_width)
end_x = (start_x + length * np.sin(angle)).astype(np.int32)
end_y = (start_y + length * np.cos(angle)).astype(np.int32)
cv2.line(mask, (start_y, start_x), (end_y, end_x), 1.0, brush_w)
start_x, start_y = end_x, end_y
return mask.reshape((1, ) + mask.shape).astype(np.float32)
class FacemaskDataset(data.Dataset):
def __init__(self, cfg):
self.root_dir = cfg.root_dir
self.cfg = cfg
self.mask_folder = os.path.join(self.root_dir, 'celeba512_30k_binary')
self.img_folder = os.path.join(self.root_dir, 'celeba512_30k')
self.load_images()
def load_images(self):
self.fns = []
idx = 0
img_paths = sorted(os.listdir(self.img_folder))
for img_name in img_paths:
mask_name = img_name.split('.')[0]+'_binary.jpg'
img_path = os.path.join(self.img_folder, img_name)
mask_path = os.path.join(self.mask_folder, mask_name)
if os.path.isfile(mask_path):
self.fns.append([img_path, mask_path])
def __getitem__(self, index):
img_path, mask_path = self.fns[index]
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (self.cfg.img_size, self.cfg.img_size))
mask = cv2.imread(mask_path, 0)
mask[mask>0]=1.0
mask = np.expand_dims(mask, axis=0)
img = torch.from_numpy(img.astype(np.float32) / 255.0).permute(2, 0, 1).contiguous()
mask = torch.from_numpy(mask.astype(np.float32)).contiguous()
return img, mask
def collate_fn(self, batch):
imgs = torch.stack([i[0] for i in batch])
masks = torch.stack([i[1] for i in batch])
return {
'imgs': imgs,
'masks': masks
}
def __len__(self):
return len(self.fns)
\ No newline at end of file
import os
import torch
import torch.nn as nn
import torch.utils.data as data
import cv2
import numpy as np
from tqdm import tqdm
import pandas as pd
from PIL import Image
class FacemaskSegDataset(data.Dataset):
def __init__(self, cfg, train=True):
self.root_dir = cfg.root_dir
self.cfg = cfg
self.train = train
if self.train:
self.df = pd.read_csv(cfg.train_anns)
else:
self.df = pd.read_csv(cfg.val_anns)
self.load_images()
def load_images(self):
self.fns = []
for idx, rows in self.df.iterrows():
_, img_name, mask_name = rows
img_path = os.path.join(self.root_dir, img_name)
mask_path = os.path.join(self.root_dir, mask_name)
img_path = img_path.replace("\\", "/")
mask_path = mask_path.replace("\\", "/")
if os.path.isfile(mask_path):
self.fns.append([img_path, mask_path])
def __getitem__(self, index):
img_path, mask_path = self.fns[index]
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (self.cfg.img_size, self.cfg.img_size))
mask = cv2.imread(mask_path, 0)
mask[mask > 0] = 1.0
mask = np.expand_dims(mask, axis=0)
img = (
torch.from_numpy(img.astype(np.float32) / 255.0)
.permute(2, 0, 1)
.contiguous()
)
mask = torch.from_numpy(mask.astype(np.float32)).contiguous()
return img, mask
def collate_fn(self, batch):
imgs = torch.stack([i[0] for i in batch])
masks = torch.stack([i[1] for i in batch])
return {"imgs": imgs, "masks": masks}
def __len__(self):
return len(self.fns)
import torch
import torch.nn as nn
from torchvision.utils import save_image
import numpy as np
from PIL import Image
import cv2
from models import UNetSemantic, GatedGenerator
import argparse
from configs import Config
class Predictor():
def __init__(self, cfg):
self.cfg = cfg
self.device = torch.device('cuda:0' if cfg.cuda else 'cpu')
self.masking = UNetSemantic().to(self.device)
self.masking.load_state_dict(torch.load('weights\model_segm_19_135000.pth', map_location='cpu'))
#self.masking.eval()
self.inpaint = GatedGenerator().to(self.device)
self.inpaint.load_state_dict(torch.load('weights/model_6_100000.pth', map_location='cpu')['G'])
self.inpaint.eval()
def save_image(self, img_list, save_img_path, nrow):
img_list = [i.clone().cpu() for i in img_list]
imgs = torch.stack(img_list, dim=1)
imgs = imgs.view(-1, *list(imgs.size())[2:])
save_image(imgs, save_img_path, nrow = nrow)
print(f"Save image to {save_img_path}")
def predict(self, image, outpath='sample/results.png'):
outpath=f'sample/results_{image}.png'
image = 'sample/'+image
img = cv2.imread(image+'_masked.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (self.cfg.img_size, self.cfg.img_size))
img = torch.from_numpy(img.astype(np.float32) / 255.0).permute(2, 0, 1).contiguous()
img = img.unsqueeze(0).to(self.device)
img_ori = cv2.imread(image+'.jpg')
img_ori = cv2.cvtColor(img_ori, cv2.COLOR_BGR2RGB)
img_ori = cv2.resize(img_ori, (self.cfg.img_size, self.cfg.img_size))
img_ori = torch.from_numpy(img_ori.astype(np.float32) / 255.0).permute(2, 0, 1).contiguous()
img_ori = img_ori.unsqueeze(0)
with torch.no_grad():
outputs = self.masking(img)
_, out = self.inpaint(img, outputs)
inpaint = img * (1 - outputs) + out * outputs
masks = img * (1 - outputs) + outputs #torch.cat([outputs, outputs, outputs], dim=1)
self.save_image([img, masks, inpaint, img_ori], outpath, nrow=4)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Training custom model')
parser.add_argument('--image', default=None, type=str, help='resume training')
parser.add_argument('config', default='config', type=str, help='config training')
args = parser.parse_args()
config = Config(f'./configs/{args.config}.yaml')
model = Predictor(config)
model.predict(args.image)
\ No newline at end of file
from .loggers import *
\ No newline at end of file
import os
import numpy as np
from torch.utils.tensorboard import SummaryWriter
from datetime import datetime
class Logger():
"""
Logger for Tensorboard visualization
:param log_dir: Path to save checkpoint
"""
def __init__(self, log_dir=None):
self.log_dir = log_dir
if self.log_dir is None:
self.log_dir = os.path.join('loggers/runs',datetime.now().strftime('%Y-%m-%d_%H-%M-%S'))
if not os.path.exists(self.log_dir):
os.mkdir(self.log_dir)
self.writer = SummaryWriter(log_dir=self.log_dir)
self.iters = {}
def write(self, tags, values):
"""
Write a log to specified directory
:param tags: (str) tag for log
:param values: (number) value for corresponding tag
"""
if not isinstance(tags, list):
tags = list(tags)
if not isinstance(values, list):
values = list(values)
for i, (tag, value) in enumerate(zip(tags,values)):
if tag not in self.iters.keys():
self.iters[tag] = 0
self.writer.add_scalar(tag, value, self.iters[tag])
self.iters[tag] += 1
from .adversarial import GANLoss
from .ssim import SSIM
from .dice import DiceLoss
\ No newline at end of file
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.