Refactor and allow reapplying of vaporizationmaster
@@ -0,0 +1,2 @@ | |||
[flake8] | |||
max-line-length = 120 |
@@ -0,0 +1,13 @@ | |||
[[source]] | |||
name = "pypi" | |||
url = "https://pypi.org/simple" | |||
verify_ssl = true | |||
[dev-packages] | |||
[packages] | |||
numpy = "==1.16.2" | |||
opencv-python = "==4.0.0.21" | |||
[requires] | |||
python_version = "3.7" |
@@ -1 +1 @@ | |||
No Sleep;NO SLEEP;Sorry;sorry;SORRY;!!!;UwU;^__^;-__-;SEE FULL IMAGE;OLD JOY;censor;CENSOR;censor.;meme;feel;feeling;Fuck This.;home.;HOME;Goodbye;goodbye.;Alone;alone.;lonely;vaporwave.;Vaporwave;Burn Me;burn me.;BURN;Fragile;STOP;stop.;tired.;tired;stop;TIRED;delete;DELETE;EXIT;exit;exit.;paradise;hide me;death;DEATH;empty;empty.;EMPTY;troll;REC;Integrity;10011010;AI;EDIT; | |||
No Sleep;NO SLEEP;Sorry;sorry;SORRY;!!!;UwU;^__^;-__-;SEE FULL IMAGE;OLD JOY;censor;CENSOR;censor.;meme;feel;feeling;Fuck This.;home.;HOME;Goodbye;goodbye.;Alone;alone.;lonely;vaporwave.;Vaporwave;Burn Me;burn me.;BURN;Fragile;STOP;stop.;tired.;tired;stop;TIRED;delete;DELETE;EXIT;exit;exit.;paradise;hide me;death;DEATH;empty;empty.;EMPTY;troll;REC;Integrity;10011010;AI;EDIT; |
@@ -5,299 +5,45 @@ | |||
# 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 cv2 | |||
import numpy as np | |||
import random as rd | |||
import os | |||
from datetime import datetime | |||
#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 posAndAngle(pts,text): | |||
#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 addElements(img): | |||
#get the number of elements | |||
allfiles = os.listdir("elements/black/") | |||
numFiles = len(allfiles) | |||
#get dimensions of main image | |||
imh,imw,imd = img.shape | |||
#randomize number of elements added | |||
numElements = rd.randint(2,4) | |||
#create a set to prevent element repetition | |||
usedels = set({}) | |||
for num in range(numElements): | |||
file_name = "elements/black/ele_b" | |||
choice = rd.randint(1,numFiles) | |||
usedels.add(choice) | |||
#run again if element has been used already | |||
while choice not in usedels: | |||
choice = rd.randint(1,numFiles) | |||
file_name += str(choice) + ".png" | |||
element = cv2.imread(file_name,-1) | |||
if element is None: | |||
print(file_name+ " failed to load image") | |||
continue | |||
h,w,d = element.shape | |||
#adjust size if too big | |||
if h > imh*.5 or w > imw*.5: | |||
element = cv2.resize(element,(int(.5*w),int(.5*h))) | |||
h,w,d = element.shape | |||
#refuse to use this image, if this failed | |||
if h > imh or w > imw: | |||
print("Element too big, moving on") | |||
continue | |||
#get x coord and y coord on the image | |||
xpos = rd.randint(1,imw-w-1) | |||
ypos = rd.randint(1,imh-h-1) | |||
#make alpha channel | |||
alpha_s = element[:,:,2]/255.0 | |||
alpha_1 = 1.0 - alpha_s | |||
for c in range(0,3): | |||
img[ypos:ypos+h,xpos:xpos+w,c] = (alpha_s*element[:,:,c]+alpha_1*img[ypos:ypos+h,xpos:xpos+w,c]) | |||
def faceGlitch(img,face): | |||
height,width,d = img.shape | |||
#pixels segments of 40 | |||
div = rd.randint(10,100) | |||
strp = int(round(face[3]/(div*1.0))) | |||
numGlitches = face[3]/strp | |||
for itr in range(0,numGlitches): | |||
#play with the second parameter to increase "glitchiness" | |||
rng = rd.randint(15,100) | |||
rightExt = face[0]+face[2]+rng | |||
leftExt = face[0]+face[2]-rng | |||
#make sure extremes don't go out of bounds | |||
if leftExt < 0: | |||
leftExt = 0 | |||
if rightExt >= width: | |||
rightExt = width | |||
#randomize static direction | |||
#1 moves left, 2 moves right | |||
dec = rd.randint(1,2) | |||
if dec%2 == 0: | |||
backBound = face[0]+rng | |||
diff = 0 | |||
#make corrections if glitch falls outside of image | |||
if face[0]+face[2]+rng >= width: | |||
diff = face[0]+face[2]+rng - (width) | |||
img[face[1]+(itr*strp):face[1]+(itr*strp+strp),(face[0]+rng):rightExt] = img[face[1]+(itr*strp):face[1]+(itr*strp+strp),face[0]:face[0]+face[2]-diff] | |||
else: | |||
backBound = face[0]-rng | |||
diff = 0 | |||
#make corrections if glitch falls outside of image | |||
if backBound < 0: | |||
diff = abs(backBound) | |||
backBound = 0 | |||
img[face[1]+(itr*strp):face[1]+(itr*strp+strp),(backBound):leftExt] = img[face[1]+(itr*strp):face[1]+(itr*strp+strp),face[0]:face[0]+face[2]-diff] | |||
import sys | |||
import logging | |||
def faceDrag(img,face): | |||
h,w,d = img.shape | |||
#0 is horizontal 1 is veritical | |||
ornt = rd.randint(0,2) | |||
if ornt == 0: | |||
line = rd.randint(face[1]+25,face[1]+face[3]-25) | |||
#0 is up 1 is down | |||
dir = rd.randint(0,2) | |||
if dir == 0: | |||
img[0:line,face[0]:face[0]+face[2]] = img[line,face[0]:face[0]+face[2]] | |||
else: | |||
img[line:h,face[0]:face[0]+face[2]] = img[line,face[0]:face[0]+face[2]] | |||
else: | |||
line = rd.randint(face[0]+25,face[0]+face[2]-25) | |||
#0 is left 1 is right | |||
dir = rd.randint(0,2) | |||
if dir == 0: | |||
img[face[1]:face[1]+face[3],0:line] = img[face[1]:face[1]+face[3],line:line+1] | |||
else: | |||
img[face[1]:face[1]+face[3],line:w] = img[face[1]:face[1]+face[3],line:line+1] | |||
def eyeCensor(img,eyes): | |||
if len(eyes) < 2: | |||
print("Failed to generate censor, less than two eyes present") | |||
return | |||
cenH = 40 | |||
#get centroids of eyes | |||
c1 = np.array([eyes[0][0] + eyes[0][2]/2.0,eyes[0][1] + eyes[0][3]/2.0]) | |||
c2 = np.array([eyes[1][0] + eyes[1][2]/2.0,eyes[1][1] + eyes[1][3]/2.0]) | |||
#find the corners of the bar | |||
#find vector of the two centroids | |||
vec = c1-c2 | |||
#unitize vector | |||
vec = vec/(vec[0]**2.0+vec[1]**2.0)**0.5 | |||
#perpendicular vector | |||
perVec = np.array([vec[1],vec[0]*(-1)]) | |||
#change these value to adjust height and width of | |||
#censor bar | |||
wEx = 40 | |||
mag = 75 | |||
cr1 = perVec*wEx+c1 | |||
cr2 = c1 - perVec*wEx | |||
cr3 = perVec*wEx+c2 | |||
cr4 = c2 - perVec*wEx | |||
cr1 += vec*mag | |||
cr2 += vec*mag | |||
cr3 -= vec*mag | |||
cr4 -= vec*mag | |||
#round all values | |||
pts = np.array([cr1,cr2,cr4,cr3]) | |||
cv2.fillPoly(img,np.array([pts],dtype=np.int32),(0,0,0)) | |||
######################################################### | |||
#The following code is incomplete. It's purpose is to randomly | |||
#add text to the censor bar | |||
#roll to see if to add text | |||
# textc = rd.randint(0,2) | |||
# textc = 1 | |||
# if textc == 1: | |||
# text = open("elements/censor.txt","r") | |||
# allText = text.read() | |||
# possText = allText.split(";") | |||
# dec = rd.randint(0,len(possText)) | |||
# use = possText[dec] | |||
# #calculate text position and angle | |||
# # info = posAndAngle(pts,use) | |||
# font = cv2.FONT_HERSHEY_SIMPLEX | |||
# cv2.putText(img,use,(int(cr1[0]),int(cr1[1])), font, 1,(255,255,255),2,cv2.LINE_AA) | |||
############################################################ | |||
def eyeDrag(img,eyes): | |||
#make sure there are only two eyes per face | |||
if len(eyes) > 2: | |||
eye1 = eyes[0] | |||
eye2 = eyes[0] | |||
size = 0 | |||
for itr in range(0,len(eyes)): | |||
if eyes[itr][2]*eyes[itr][3] > size: | |||
size = eyes[itr][2]*eyes[itr][3] | |||
eye1 = eyes[itr] | |||
size = 0 | |||
for itr in range(0,len(eyes)): | |||
if eyes[itr][2]*eyes[itr][3] > size and not np.array_equal(eyes[itr],eye1): | |||
size = eyes[itr][2]*eyes[itr][3] | |||
eye2 = eyes[itr] | |||
eyes = [eye1,eye2] | |||
#there should only be two eyes now | |||
for eye in eyes: | |||
#find width of eye | |||
iwid = eye[2] | |||
strp = int(round(iwid/20.)) | |||
numGlitches = int(eye[2]/strp) | |||
line = rd.randint(1,eye[3]) | |||
line += eye[1] | |||
line = int(eye[1] + eye[3]/2) | |||
for itr in range(0,numGlitches): | |||
#edit the second parameter to change eye drop chance | |||
drop = rd.randint(10,200) | |||
#if the line drop is too low, shorten it | |||
if line + drop > img.shape[0]: | |||
drop = img.shape[0] - line | |||
img[line:line+drop,eye[0]+itr*strp:eye[0]+itr*strp+strp] = img[line,eye[0]+itr*strp:eye[0]+itr*strp+strp] | |||
import cv2 | |||
from vaporwave import vaporize | |||
if __name__ == "__main__": | |||
#seed the random generator | |||
rd.seed(datetime.now()) | |||
#load files for facial and eye cascade | |||
face_cascade = cv2.CascadeClassifier('cascade/haarcascade_frontalface_default.xml') | |||
eye_cascade = cv2.CascadeClassifier('cascade/haarcascade_eye.xml') | |||
ESCAPE_KEY = 27 | |||
#load main image from local file | |||
img = cv2.imread("testImgs/testface9.png") | |||
height,width,depth = img.shape | |||
logging.basicConfig(level=logging.INFO, | |||
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', | |||
datefmt='%m-%d %H:%M') | |||
#turn image gray for detecting face and eyes | |||
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |||
logger = logging.getLogger("main") | |||
logger.setLevel(logging.INFO) | |||
#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] | |||
def main(): | |||
#randomize which face modification will be performed | |||
faceMod = rd.randint(0,4) | |||
# if there are no eyes, just re-roll | |||
if faceMod >= 3 and len(eyes) == 0: | |||
faceMod = rd.randint(0,2) | |||
img = vaporize() | |||
#0 - no mod | |||
#1 - face glitch | |||
#2 - face drag | |||
#3 - eye censor | |||
#4 - eye drag | |||
if faceMod == 1: | |||
faceGlitch(img,face) | |||
elif faceMod == 2: | |||
faceDrag(img,face) | |||
elif faceMod == 3: | |||
eyeCensor(img,eyes) | |||
elif faceMod == 4: | |||
eyeDrag(img,eyes) | |||
cv2.namedWindow("pic", cv2.WINDOW_NORMAL) | |||
cv2.imshow("pic", img) | |||
# Add elements to image | |||
addElements(img) | |||
#if there are no faces, just add more elements! | |||
if len(faces) < 1: | |||
addElements(img) | |||
while cv2.getWindowProperty("pic", cv2.WND_PROP_VISIBLE): | |||
key_code = cv2.waitKey(100) | |||
#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) | |||
if key_code == ESCAPE_KEY: | |||
break | |||
elif key_code != -1: | |||
import time | |||
start = time.time() | |||
img = vaporize() | |||
cv2.imshow("pic", img) | |||
end = time.time() | |||
logger.info("Vaporizing and rendering took: %f seconds" % (end-start,)) | |||
cv2.destroyAllWindows() | |||
sys.exit() | |||
#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) | |||
cv2.namedWindow("pic",cv2.WINDOW_NORMAL) | |||
cv2.imshow("pic",img) | |||
cv2.waitKey(0) | |||
if __name__ == "__main__": | |||
main() |
@@ -0,0 +1,2 @@ | |||
numpy==1.16.2 | |||
opencv-python==4.0.0.21 |
@@ -0,0 +1,88 @@ | |||
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: | |||
modded_img = mod_function(img, eyes) | |||
if modded_img is not None: | |||
img = modded_img | |||
elif operates_on == mods.FACE: | |||
modded_img = mod_function(img, face) | |||
if modded_img is not None: | |||
img = modded_img | |||
# 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 |
@@ -0,0 +1,248 @@ | |||
import math | |||
import cv2 | |||
import logging | |||
import numpy as np | |||
import random as rd | |||
NO_MOD = 0 | |||
FACE_GLITCH = 1 | |||
FACE_DRAG = 2 | |||
EYE_CENSOR = 3 | |||
EYE_DRAG = 4 | |||
EYES = 100 | |||
FACE = 101 | |||
DEGREES_PER_RADIAN = 57.296 | |||
TOP_LEFT = 0 | |||
TOP_RIGHT = 1 | |||
BOTTOM_RIGHT = 2 | |||
BOTTOM_LEFT = 3 | |||
logger = logging.getLogger("mods") | |||
def sort_corners(corners): | |||
corners = sorted(corners, key=lambda x: x[0]) | |||
top_left, bottom_left = sorted(corners[0:2], key=lambda x: x[1]) | |||
top_right, bottom_right = sorted(corners[2:4], key=lambda x: [1]) | |||
return top_left, top_right, bottom_right, bottom_left | |||
def unit_vector(vector): | |||
return vector / np.linalg.norm(vector) | |||
def angle(first, second, to_degrees=True): | |||
unit_first = unit_vector(first) | |||
unit_second = unit_vector(second) | |||
radians = np.arccos(np.clip(np.dot(unit_first, unit_second), -1.0, 1.0)) | |||
return radians * DEGREES_PER_RADIAN if to_degrees else radians | |||
# 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 | |||
left_upper = pts[TOP_LEFT] | |||
right_upper = pts[TOP_RIGHT] | |||
vector = np.array(left_upper - right_upper) | |||
y_axis = np.array(np.array([0, 0]) - np.array([1, 0])) | |||
return left_upper, angle(vector, y_axis) | |||
def determine_face_mod(eyes_present): | |||
function_list = [ | |||
(lambda x, y: x, FACE), | |||
(face_glitch, FACE), | |||
(face_drag, FACE), | |||
(eye_censor, EYES), | |||
(eye_drag, EYES) | |||
] | |||
function_index = rd.randint(0, 4) if eyes_present else rd.randint(0, 2) | |||
return function_list[function_index] | |||
def eye_drag(img, eyes): | |||
# make sure there are only two eyes per face | |||
if len(eyes) > 2: | |||
eye1 = eyes[0] | |||
eye2 = eyes[0] | |||
size = 0 | |||
for itr in range(0, len(eyes)): | |||
if eyes[itr][2] * eyes[itr][3] > size: | |||
size = eyes[itr][2] * eyes[itr][3] | |||
eye1 = eyes[itr] | |||
size = 0 | |||
for itr in range(0, len(eyes)): | |||
if eyes[itr][2] * eyes[itr][3] > size and not np.array_equal(eyes[itr], eye1): | |||
size = eyes[itr][2] * eyes[itr][3] | |||
eye2 = eyes[itr] | |||
eyes = [eye1, eye2] | |||
# there should only be two eyes now | |||
for eye in eyes: | |||
# find width of eye | |||
iwid = eye[2] | |||
strp = int(round(iwid / 20.)) | |||
num_glitches = int(eye[2] / strp) | |||
line = rd.randint(1, eye[3]) | |||
line += eye[1] | |||
line = int(eye[1] + eye[3] / 2) | |||
for itr in range(0, num_glitches): | |||
# edit the second parameter to change eye drop chance | |||
drop = rd.randint(10, 200) | |||
# if the line drop is too low, shorten it | |||
if line + drop > img.shape[0]: | |||
drop = img.shape[0] - line | |||
img[line:line + drop, eye[0] + itr * strp:eye[0] + itr * strp + strp] = \ | |||
img[line, eye[0] + itr * strp:eye[0] + itr * strp + strp] | |||
def eye_censor(img, eyes): | |||
if len(eyes) < 2: | |||
logger.warning("Failed to generate censor, less than two eyes present") | |||
return | |||
# cenH = 40 | |||
# get centroids of eyes | |||
centroid_right = np.array([eyes[0][0] + eyes[0][2] / 2.0, eyes[0][1] + eyes[0][3] / 2.0]) | |||
centroid_left = np.array([eyes[1][0] + eyes[1][2] / 2.0, eyes[1][1] + eyes[1][3] / 2.0]) | |||
# find the corners of the bar | |||
# find vector of the two centroids | |||
vec = centroid_right - centroid_left | |||
# unitize vector | |||
vec = vec / (vec[0] ** 2.0 + vec[1] ** 2.0) ** 0.5 | |||
# perpendicular vector | |||
per_vec = np.array([vec[1], vec[0] * (-1)]) | |||
# change these value to adjust height and width of | |||
# censor bar | |||
w_ex = 40 | |||
mag = 75 | |||
right_upper = per_vec * w_ex + centroid_right | |||
right_lower = centroid_right - per_vec * w_ex | |||
left_upper = per_vec * w_ex + centroid_left | |||
left_lower = centroid_left - per_vec * w_ex | |||
right_upper += vec * mag | |||
right_lower += vec * mag | |||
left_upper -= vec * mag | |||
left_lower -= vec * mag | |||
# round all values | |||
corners = sort_corners([right_upper, right_lower, left_lower, left_upper]) | |||
print(corners) | |||
cv2.fillPoly(img, np.array([corners], dtype=np.int32), (0, 0, 0)) | |||
should_render_text = rd.randint(0, 2) | |||
if should_render_text: | |||
with open("elements/censor.txt", "r") as text_file: | |||
allText = text_file.read() | |||
possText = allText.split(";") | |||
dec = rd.randint(0, len(possText) - 1) | |||
text = possText[dec] | |||
# calculate text position and angle | |||
return render_text(text, corners, img) | |||
def render_text(text, corners, img): | |||
left_upper, right_upper, right_lower, left_lower = corners | |||
corner, rotation_angle = pos_and_angle(corners) | |||
text_image = np.ones(img.shape) | |||
text_img_rows, text_img_cols, _ = text_image.shape | |||
font = cv2.FONT_HERSHEY_SIMPLEX | |||
text_size = cv2.getTextSize(text, font, 1, 1) | |||
(text_width, text_height), _ = text_size | |||
text_corner_x = left_upper[0] + (right_upper[0] - left_upper[0]) / 2.0 - text_width / 2.0 | |||
text_corner_y = left_upper[1] + (left_lower[1] - left_upper[1]) / 2.0 - text_height / 2.0 | |||
corner_coords = (int(text_corner_x), int(text_corner_y)) | |||
rotation_matrix = cv2.getRotationMatrix2D(corner_coords, rotation_angle, 1) | |||
cv2.putText(text_image, text, corner_coords, font, 1, (255, 255, 255), 2, cv2.LINE_AA) | |||
text_image = cv2.warpAffine(text_image, rotation_matrix, (text_img_cols, text_img_rows)) | |||
img = text_image + img | |||
cv2.imshow("pic", img) | |||
return img | |||
def face_drag(img, face): | |||
h, w, d = img.shape | |||
# 0 is horizontal 1 is veritical | |||
ornt = rd.randint(0, 2) | |||
if ornt == 0: | |||
line = rd.randint(face[1] + 25, face[1] + face[3] - 25) | |||
# 0 is up 1 is down | |||
direction = rd.randint(0, 2) | |||
if direction == 0: | |||
img[0:line, face[0]:face[0] + face[2]] = img[line, face[0]:face[0] + face[2]] | |||
else: | |||
img[line:h, face[0]:face[0] + face[2]] = img[line, face[0]:face[0] + face[2]] | |||
else: | |||
line = rd.randint(face[0] + 25, face[0] + face[2] - 25) | |||
# 0 is left 1 is right | |||
direction = rd.randint(0, 2) | |||
if direction == 0: | |||
img[face[1]:face[1] + face[3], 0:line] = img[face[1]:face[1] + face[3], line:line + 1] | |||
else: | |||
img[face[1]:face[1] + face[3], line:w] = img[face[1]:face[1] + face[3], line:line + 1] | |||
def face_glitch(img, face): | |||
height, width, d = img.shape | |||
# pixels segments of 40 | |||
div = rd.randint(10, 100) | |||
strp = int(round(face[3] / (div * 1.0))) | |||
num_glitches = face[3] / strp | |||
if type(num_glitches) == np.float64: | |||
num_glitches = math.floor(num_glitches) | |||
for itr in range(0, num_glitches): | |||
# play with the second parameter to increase "glitchiness" | |||
rng = rd.randint(15, 100) | |||
right_ext = face[0] + face[2] + rng | |||
left_ext = face[0] + face[2] - rng | |||
# make sure extremes don't go out of bounds | |||
if left_ext < 0: | |||
left_ext = 0 | |||
if right_ext >= width: | |||
right_ext = width | |||
# randomize static direction | |||
# 1 moves left, 2 moves right | |||
dec = rd.randint(1, 2) | |||
back_bound = face[0] + rng | |||
if dec % 2 == 0: | |||
diff = 0 | |||
# make corrections if glitch falls outside of image | |||
if face[0] + face[2] + rng >= width: | |||
diff = face[0] + face[2] + rng - width | |||
img[face[1] + (itr * strp):face[1] + (itr * strp + strp), (face[0] + rng):right_ext] = \ | |||
img[face[1] + (itr * strp):face[1] + (itr * strp + strp), face[0]:face[0] + face[2] - diff] | |||
else: | |||
diff = 0 | |||
# make corrections if glitch falls outside of image | |||
if back_bound < 0: | |||
diff = abs(back_bound) | |||
back_bound = 0 | |||
old = img[face[1] + (itr * strp):face[1] + (itr * strp + strp), back_bound:left_ext] | |||
new = img[face[1] + (itr * strp):face[1] + (itr * strp + strp), face[0]:face[0] + face[2] - diff] | |||
if old.shape != new.shape: | |||
logger.warning("Shape mismatch: %s vs %s" % (old.shape, new.shape,)) | |||
return | |||
img[face[1] + (itr * strp):face[1] + (itr * strp + strp), back_bound:left_ext] = \ | |||
img[face[1] + (itr * strp):face[1] + (itr * strp + strp), face[0]:face[0] + face[2] - diff] |