@@ -5,18 +5,12 @@ | |||
# To run the program call the following command in terminal | |||
# python main.py | |||
# To change the image being used, modify code on line 208 | |||
import sys | |||
import logging | |||
import cv2 | |||
import logging | |||
import numpy as np | |||
import random as rd | |||
import os | |||
from functools import partial | |||
import mods | |||
from datetime import datetime | |||
from vaporwave import vaporize | |||
ESCAPE_KEY = 27 | |||
@@ -28,86 +22,7 @@ logger = logging.getLogger("main") | |||
logger.setLevel(logging.INFO) | |||
# The following function is used to determine the placement of | |||
# text, at the moment it is incomplete | |||
# function takes corners and text | |||
# and resturns top left corner that | |||
# centers text and the angle needed | |||
def pos_and_angle(pts): | |||
# find left top most coordinate | |||
dist = np.inf | |||
# left = pts[0] | |||
for cr in pts: | |||
if (cr[0] ** 2 + cr[1] ** 2) ** 0.5 < dist: | |||
dist = (cr[0] ** 2 + cr[1] ** 2) ** 0.5 | |||
# left = cr | |||
# first find angle | |||
return 1 | |||
def add_elements(img): | |||
min_elements = 2 | |||
max_elements = 4 | |||
base_dir = "elements/black/" | |||
all_files = os.listdir(base_dir) | |||
rd.shuffle(all_files) | |||
# randomize number of elements added | |||
num_elements = rd.randint(min_elements, max_elements) | |||
# create a set to prevent element repetition | |||
added_counter = 0 | |||
logger.info("Adding %d elements" % (num_elements, )) | |||
for file_name in map(partial(os.path.join, base_dir), all_files): | |||
if added_counter == num_elements: | |||
return | |||
success = add_single_element(img, file_name) | |||
if success: | |||
added_counter += 1 | |||
def add_single_element(img, file_name): | |||
imh, imw, imd = img.shape | |||
element = cv2.imread(file_name, -1) | |||
if element is None: | |||
logger.warning("Could not read file %s" % (file_name,)) | |||
return False | |||
original_height, original_width, original_depth = element.shape | |||
# adjust size if too big | |||
if original_height > imh * .5 or original_width > imw * .5: | |||
element = cv2.resize(element, (int(.5 * original_width), int(.5 * original_height))) | |||
resized_height, resized_width, _ = element.shape | |||
# refuse to use this image, if this failed | |||
if resized_height > imh or resized_width > imw: | |||
logger.warning("Element %s too big, moving on" % (file_name,)) | |||
return False | |||
# get x coord and y coord on the image | |||
from_x_pos = rd.randint(1, imw - resized_width - 1) | |||
from_y_pos = rd.randint(1, imh - resized_height - 1) | |||
# make alpha channel | |||
alpha_s = element[:, :, 2] / 255.0 | |||
alpha_1 = 1.0 - alpha_s | |||
for c in range(0, 3): | |||
to_y_pos = from_y_pos + resized_height | |||
to_x_pos = from_x_pos + resized_width | |||
with_alpha_s = alpha_s * element[:, :, c] | |||
with_alpha_1 = alpha_1 * img[from_y_pos:to_y_pos, from_x_pos:to_x_pos, c] | |||
img[from_y_pos:to_y_pos, from_x_pos:to_x_pos, c] = with_alpha_s + with_alpha_1 | |||
return True | |||
def main(): | |||
# seed the random generator | |||
rd.seed(datetime.now()) | |||
# load files for facial and eye cascade | |||
img = vaporize() | |||
@@ -130,82 +45,5 @@ def main(): | |||
sys.exit() | |||
def vaporize(image_path="testImgs/testface9.png"): | |||
face_cascade = cv2.CascadeClassifier('cascade/haarcascade_frontalface_default.xml') | |||
eye_cascade = cv2.CascadeClassifier('cascade/haarcascade_eye.xml') | |||
# load main image from local file | |||
img = cv2.imread(image_path) | |||
# height, width, depth = img.shape | |||
# turn image gray for detecting face and eyes | |||
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |||
# find all the faces in the image | |||
faces = face_cascade.detectMultiScale(gray, 1.3, 5) | |||
# go through each face | |||
for face in faces: | |||
y = face[1] | |||
x = face[0] | |||
w = face[2] | |||
h = face[3] | |||
roi_gray = gray[y:y + h, x:x + w] | |||
# roi_color = img[y:y + h, x:x + w] | |||
# find each eye. Modify second and third parameter if | |||
# feature detection is poor | |||
eyes = eye_cascade.detectMultiScale(roi_gray, 1.2, 6) | |||
for eye in eyes: | |||
eye[0] += face[0] | |||
eye[1] += face[1] | |||
# randomize which face modification will be performed | |||
eyes_present = len(eyes) >= 2 | |||
mod_function, operates_on = mods.determine_face_mod(eyes_present) | |||
if operates_on == mods.EYES: | |||
mod_function(img, eyes) | |||
elif operates_on == mods.FACE: | |||
mod_function(img, face) | |||
# Add elements to image | |||
add_elements(img) | |||
# if there are no faces, just add more elements! | |||
if len(faces) < 1: | |||
add_elements(img) | |||
# randomize if high contrast is used | |||
choice = rd.randint(0, 1) | |||
if choice == 1: | |||
# edit alpha and beta to adjust contrast levels | |||
img = cv2.convertScaleAbs(img, alpha=1.2, beta=35) | |||
# randomize if high noise is used | |||
choice = rd.randint(0, 1) | |||
if choice == 1: | |||
row, col, ch = img.shape | |||
mean = 0 | |||
# edit var to modify the amount of noise in the image | |||
var = 15 | |||
sigma = var ** 1 | |||
gauss = np.random.normal(mean, sigma, (row, col, ch)) | |||
gauss = gauss.reshape(row, col, ch) | |||
noisy = (img + gauss) | |||
cv2.normalize(noisy, noisy, 0, 1, cv2.NORM_MINMAX) | |||
img = noisy | |||
# The following code is useful to determine if faces and eyes | |||
# are being read correctly. Uncommenting will draw boxes around | |||
# found features. | |||
# for (x,y,w,h) in faces: | |||
# cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) | |||
# roi_gray = gray[y:y+h, x:x+w] | |||
# roi_color = img[y:y+h, x:x+w] | |||
# #edit the second and third parameter if feature detection is poor | |||
# eyes = eye_cascade.detectMultiScale(roi_gray, 1.2, 6) | |||
# for (ex,ey,ew,eh) in eyes: | |||
# cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2) | |||
return img | |||
if __name__ == "__main__": | |||
main() |
@@ -0,0 +1,84 @@ | |||
import random as rd | |||
import cv2 | |||
import numpy as np | |||
from .elements import add_single_element, add_elements | |||
from . import mods | |||
def vaporize(image_path="testImgs/testface9.png"): | |||
face_cascade = cv2.CascadeClassifier('cascade/haarcascade_frontalface_default.xml') | |||
eye_cascade = cv2.CascadeClassifier('cascade/haarcascade_eye.xml') | |||
# load main image from local file | |||
img = cv2.imread(image_path) | |||
# height, width, depth = img.shape | |||
# turn image gray for detecting face and eyes | |||
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |||
# find all the faces in the image | |||
faces = face_cascade.detectMultiScale(gray, 1.3, 5) | |||
# go through each face | |||
for face in faces: | |||
y = face[1] | |||
x = face[0] | |||
w = face[2] | |||
h = face[3] | |||
roi_gray = gray[y:y + h, x:x + w] | |||
# roi_color = img[y:y + h, x:x + w] | |||
# find each eye. Modify second and third parameter if | |||
# feature detection is poor | |||
eyes = eye_cascade.detectMultiScale(roi_gray, 1.2, 6) | |||
for eye in eyes: | |||
eye[0] += face[0] | |||
eye[1] += face[1] | |||
# randomize which face modification will be performed | |||
eyes_present = len(eyes) >= 2 | |||
mod_function, operates_on = mods.determine_face_mod(eyes_present) | |||
if operates_on == mods.EYES: | |||
mod_function(img, eyes) | |||
elif operates_on == mods.FACE: | |||
mod_function(img, face) | |||
# Add elements to image | |||
add_elements(img) | |||
# if there are no faces, just add more elements! | |||
if len(faces) < 1: | |||
add_elements(img) | |||
# randomize if high contrast is used | |||
choice = rd.randint(0, 1) | |||
if choice == 1: | |||
# edit alpha and beta to adjust contrast levels | |||
img = cv2.convertScaleAbs(img, alpha=1.2, beta=35) | |||
# randomize if high noise is used | |||
choice = rd.randint(0, 1) | |||
if choice == 1: | |||
row, col, ch = img.shape | |||
mean = 0 | |||
# edit var to modify the amount of noise in the image | |||
var = 15 | |||
sigma = var ** 1 | |||
gauss = np.random.normal(mean, sigma, (row, col, ch)) | |||
gauss = gauss.reshape(row, col, ch) | |||
noisy = (img + gauss) | |||
cv2.normalize(noisy, noisy, 0, 1, cv2.NORM_MINMAX) | |||
img = noisy | |||
# The following code is useful to determine if faces and eyes | |||
# are being read correctly. Uncommenting will draw boxes around | |||
# found features. | |||
# for (x,y,w,h) in faces: | |||
# cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) | |||
# roi_gray = gray[y:y+h, x:x+w] | |||
# roi_color = img[y:y+h, x:x+w] | |||
# #edit the second and third parameter if feature detection is poor | |||
# eyes = eye_cascade.detectMultiScale(roi_gray, 1.2, 6) | |||
# for (ex,ey,ew,eh) in eyes: | |||
# cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2) | |||
return img |
@@ -0,0 +1,67 @@ | |||
import logging | |||
import os | |||
import random as rd | |||
from functools import partial | |||
import cv2 | |||
logger = logging.getLogger("elements") | |||
def add_elements(img): | |||
min_elements = 2 | |||
max_elements = 4 | |||
base_dir = "elements/black/" | |||
all_files = os.listdir(base_dir) | |||
rd.shuffle(all_files) | |||
# randomize number of elements added | |||
num_elements = rd.randint(min_elements, max_elements) | |||
# create a set to prevent element repetition | |||
added_counter = 0 | |||
logger.info("Adding %d elements" % (num_elements, )) | |||
for file_name in map(partial(os.path.join, base_dir), all_files): | |||
if added_counter == num_elements: | |||
return | |||
success = add_single_element(img, file_name) | |||
if success: | |||
added_counter += 1 | |||
def add_single_element(img, file_name): | |||
imh, imw, imd = img.shape | |||
element = cv2.imread(file_name, -1) | |||
if element is None: | |||
logger.warning("Could not read file %s" % (file_name,)) | |||
return False | |||
original_height, original_width, original_depth = element.shape | |||
# adjust size if too big | |||
if original_height > imh * .5 or original_width > imw * .5: | |||
element = cv2.resize(element, (int(.5 * original_width), int(.5 * original_height))) | |||
resized_height, resized_width, _ = element.shape | |||
# refuse to use this image, if this failed | |||
if resized_height > imh or resized_width > imw: | |||
logger.warning("Element %s too big, moving on" % (file_name,)) | |||
return False | |||
# get x coord and y coord on the image | |||
from_x_pos = rd.randint(1, imw - resized_width - 1) | |||
from_y_pos = rd.randint(1, imh - resized_height - 1) | |||
# make alpha channel | |||
alpha_s = element[:, :, 2] / 255.0 | |||
alpha_1 = 1.0 - alpha_s | |||
for c in range(0, 3): | |||
to_y_pos = from_y_pos + resized_height | |||
to_x_pos = from_x_pos + resized_width | |||
with_alpha_s = alpha_s * element[:, :, c] | |||
with_alpha_1 = alpha_1 * img[from_y_pos:to_y_pos, from_x_pos:to_x_pos, c] | |||
img[from_y_pos:to_y_pos, from_x_pos:to_x_pos, c] = with_alpha_s + with_alpha_1 | |||
return True |
@@ -17,6 +17,23 @@ FACE = 101 | |||
logger = logging.getLogger("mods") | |||
# The following function is used to determine the placement of | |||
# text, at the moment it is incomplete | |||
# function takes corners and text | |||
# and resturns top left corner that | |||
# centers text and the angle needed | |||
def pos_and_angle(pts): | |||
# find left top most coordinate | |||
dist = np.inf | |||
# left = pts[0] | |||
for cr in pts: | |||
if (cr[0] ** 2 + cr[1] ** 2) ** 0.5 < dist: | |||
dist = (cr[0] ** 2 + cr[1] ** 2) ** 0.5 | |||
# left = cr | |||
# first find angle | |||
return 1 | |||
def determine_face_mod(eyes_present): | |||
function_list = [ | |||
(lambda x, y: x, FACE), |