Spaces:
Running
Running
李开祥
commited on
Commit
•
2eacc9a
1
Parent(s):
2f0b579
代码
Browse files- checkpoints/not empty.txt +0 -0
- input/not empty.txt +0 -0
- opencv_transform/__init__.py +0 -0
- opencv_transform/annotation.py +17 -0
- opencv_transform/dress_to_correct.py +64 -0
- opencv_transform/mask_to_maskref.py +41 -0
- opencv_transform/maskdet_to_maskfin.py +519 -0
- opencv_transform/nude_to_watermark.py +28 -0
checkpoints/not empty.txt
ADDED
File without changes
|
input/not empty.txt
ADDED
File without changes
|
opencv_transform/__init__.py
ADDED
File without changes
|
opencv_transform/annotation.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
#Object annotation class:
|
3 |
+
class BodyPart:
|
4 |
+
|
5 |
+
def __init__(self, name, xmin, ymin, xmax, ymax, x, y, w, h):
|
6 |
+
self.name = name
|
7 |
+
#Bounding Box:
|
8 |
+
self.xmin = xmin
|
9 |
+
self.ymin = ymin
|
10 |
+
self.xmax = xmax
|
11 |
+
self.ymax = ymax
|
12 |
+
#Center:
|
13 |
+
self.x = x
|
14 |
+
self.y = y
|
15 |
+
#Dimensione:
|
16 |
+
self.w = w
|
17 |
+
self.h = h
|
opencv_transform/dress_to_correct.py
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import math
|
3 |
+
import numpy as np
|
4 |
+
import os
|
5 |
+
|
6 |
+
# create_correct ===============================================================
|
7 |
+
# return:
|
8 |
+
# (<Boolean> True/False), depending on the transformation process
|
9 |
+
def create_correct(cv_dress):
|
10 |
+
|
11 |
+
#Production dir:
|
12 |
+
return correct_color(cv_dress, 5)
|
13 |
+
|
14 |
+
# correct_color ==============================================================================
|
15 |
+
# return:
|
16 |
+
# <RGB> image corrected
|
17 |
+
def correct_color(img, percent):
|
18 |
+
|
19 |
+
assert img.shape[2] == 3
|
20 |
+
assert percent > 0 and percent < 100
|
21 |
+
|
22 |
+
half_percent = percent / 200.0
|
23 |
+
|
24 |
+
channels = cv2.split(img)
|
25 |
+
|
26 |
+
out_channels = []
|
27 |
+
for channel in channels:
|
28 |
+
assert len(channel.shape) == 2
|
29 |
+
# find the low and high precentile values (based on the input percentile)
|
30 |
+
height, width = channel.shape
|
31 |
+
vec_size = width * height
|
32 |
+
flat = channel.reshape(vec_size)
|
33 |
+
|
34 |
+
assert len(flat.shape) == 1
|
35 |
+
|
36 |
+
flat = np.sort(flat)
|
37 |
+
|
38 |
+
n_cols = flat.shape[0]
|
39 |
+
|
40 |
+
low_val = flat[math.floor(n_cols * half_percent)]
|
41 |
+
high_val = flat[math.ceil( n_cols * (1.0 - half_percent))]
|
42 |
+
|
43 |
+
# saturate below the low percentile and above the high percentile
|
44 |
+
thresholded = apply_threshold(channel, low_val, high_val)
|
45 |
+
# scale the channel
|
46 |
+
normalized = cv2.normalize(thresholded, thresholded.copy(), 0, 255, cv2.NORM_MINMAX)
|
47 |
+
out_channels.append(normalized)
|
48 |
+
|
49 |
+
return cv2.merge(out_channels)
|
50 |
+
|
51 |
+
#Color correction utils
|
52 |
+
def apply_threshold(matrix, low_value, high_value):
|
53 |
+
low_mask = matrix < low_value
|
54 |
+
matrix = apply_mask(matrix, low_mask, low_value)
|
55 |
+
|
56 |
+
high_mask = matrix > high_value
|
57 |
+
matrix = apply_mask(matrix, high_mask, high_value)
|
58 |
+
|
59 |
+
return matrix
|
60 |
+
|
61 |
+
#Color correction utils
|
62 |
+
def apply_mask(matrix, mask, fill_value):
|
63 |
+
masked = np.ma.array(matrix, mask=mask, fill_value=fill_value)
|
64 |
+
return masked.filled()
|
opencv_transform/mask_to_maskref.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
import os
|
4 |
+
|
5 |
+
###
|
6 |
+
#
|
7 |
+
# maskdet_to_maskfin
|
8 |
+
#
|
9 |
+
#
|
10 |
+
###
|
11 |
+
|
12 |
+
# create_maskref ===============================================================
|
13 |
+
# return:
|
14 |
+
# maskref image
|
15 |
+
def create_maskref(cv_mask, cv_correct):
|
16 |
+
|
17 |
+
#Create a total green image
|
18 |
+
green = np.zeros((512,512,3), np.uint8)
|
19 |
+
green[:,:,:] = (0,255,0) # (B, G, R)
|
20 |
+
|
21 |
+
#Define the green color filter
|
22 |
+
f1 = np.asarray([0, 250, 0]) # green color filter
|
23 |
+
f2 = np.asarray([10, 255, 10])
|
24 |
+
|
25 |
+
#From mask, extrapolate only the green mask
|
26 |
+
green_mask = cv2.inRange(cv_mask, f1, f2) #green is 0
|
27 |
+
|
28 |
+
# (OPTIONAL) Apply dilate and open to mask
|
29 |
+
kernel = np.ones((5,5),np.uint8) #Try change it?
|
30 |
+
green_mask = cv2.dilate(green_mask, kernel, iterations = 1)
|
31 |
+
#green_mask = cv2.morphologyEx(green_mask, cv2.MORPH_OPEN, kernel)
|
32 |
+
|
33 |
+
# Create an inverted mask
|
34 |
+
green_mask_inv = cv2.bitwise_not(green_mask)
|
35 |
+
|
36 |
+
# Cut correct and green image, using the green_mask & green_mask_inv
|
37 |
+
res1 = cv2.bitwise_and(cv_correct, cv_correct, mask = green_mask_inv)
|
38 |
+
res2 = cv2.bitwise_and(green, green, mask = green_mask)
|
39 |
+
|
40 |
+
# Compone:
|
41 |
+
return cv2.add(res1, res2)
|
opencv_transform/maskdet_to_maskfin.py
ADDED
@@ -0,0 +1,519 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
import os
|
4 |
+
import random
|
5 |
+
|
6 |
+
#My library:
|
7 |
+
from opencv_transform.annotation import BodyPart
|
8 |
+
|
9 |
+
###
|
10 |
+
#
|
11 |
+
# maskdet_to_maskfin
|
12 |
+
#
|
13 |
+
# steps:
|
14 |
+
# 1. Extract annotation
|
15 |
+
# 1.a: Filter by color
|
16 |
+
# 1.b: Find ellipses
|
17 |
+
# 1.c: Filter out ellipses by max size, and max total numbers
|
18 |
+
# 1.d: Detect Problems
|
19 |
+
# 1.e: Resolve the problems, or discard the transformation
|
20 |
+
# 2. With the body list, draw maskfin, using maskref
|
21 |
+
#
|
22 |
+
###
|
23 |
+
|
24 |
+
# create_maskfin ==============================================================================
|
25 |
+
# return:
|
26 |
+
# (<Boolean> True/False), depending on the transformation process
|
27 |
+
def create_maskfin(maskref, maskdet):
|
28 |
+
|
29 |
+
#Create a total green image, in which draw details ellipses
|
30 |
+
details = np.zeros((512,512,3), np.uint8)
|
31 |
+
details[:,:,:] = (0,255,0) # (B, G, R)
|
32 |
+
|
33 |
+
#Extract body part features:
|
34 |
+
bodypart_list = extractAnnotations(maskdet);
|
35 |
+
|
36 |
+
#Check if the list is not empty:
|
37 |
+
if bodypart_list:
|
38 |
+
|
39 |
+
#Draw body part in details image:
|
40 |
+
for obj in bodypart_list:
|
41 |
+
|
42 |
+
if obj.w < obj.h:
|
43 |
+
aMax = int(obj.h/2) #asse maggiore
|
44 |
+
aMin = int(obj.w/2) #asse minore
|
45 |
+
angle = 0 #angle
|
46 |
+
else:
|
47 |
+
aMax = int(obj.w/2)
|
48 |
+
aMin = int(obj.h/2)
|
49 |
+
angle = 90
|
50 |
+
|
51 |
+
x = int(obj.x)
|
52 |
+
y = int(obj.y)
|
53 |
+
|
54 |
+
#Draw ellipse
|
55 |
+
if obj.name == "tit":
|
56 |
+
cv2.ellipse(details,(x,y),(aMax,aMin),angle,0,360,(0,205,0),-1) #(0,0,0,50)
|
57 |
+
elif obj.name == "aur":
|
58 |
+
cv2.ellipse(details,(x,y),(aMax,aMin),angle,0,360,(0,0,255),-1) #red
|
59 |
+
elif obj.name == "nip":
|
60 |
+
cv2.ellipse(details,(x,y),(aMax,aMin),angle,0,360,(255,255,255),-1) #white
|
61 |
+
elif obj.name == "belly":
|
62 |
+
cv2.ellipse(details,(x,y),(aMax,aMin),angle,0,360,(255,0,255),-1) #purple
|
63 |
+
elif obj.name == "vag":
|
64 |
+
cv2.ellipse(details,(x,y),(aMax,aMin),angle,0,360,(255,0,0),-1) #blue
|
65 |
+
elif obj.name == "hair":
|
66 |
+
xmin = x - int(obj.w/2)
|
67 |
+
ymin = y - int(obj.h/2)
|
68 |
+
xmax = x + int(obj.w/2)
|
69 |
+
ymax = y + int(obj.h/2)
|
70 |
+
cv2.rectangle(details,(xmin,ymin),(xmax,ymax),(100,100,100),-1)
|
71 |
+
|
72 |
+
#Define the green color filter
|
73 |
+
f1 = np.asarray([0, 250, 0]) # green color filter
|
74 |
+
f2 = np.asarray([10, 255, 10])
|
75 |
+
|
76 |
+
#From maskref, extrapolate only the green mask
|
77 |
+
green_mask = cv2.bitwise_not(cv2.inRange(maskref, f1, f2)) #green is 0
|
78 |
+
|
79 |
+
# Create an inverted mask
|
80 |
+
green_mask_inv = cv2.bitwise_not(green_mask)
|
81 |
+
|
82 |
+
# Cut maskref and detail image, using the green_mask & green_mask_inv
|
83 |
+
res1 = cv2.bitwise_and(maskref, maskref, mask = green_mask)
|
84 |
+
res2 = cv2.bitwise_and(details, details, mask = green_mask_inv)
|
85 |
+
|
86 |
+
# Compone:
|
87 |
+
maskfin = cv2.add(res1, res2)
|
88 |
+
return maskfin
|
89 |
+
|
90 |
+
# extractAnnotations ==============================================================================
|
91 |
+
# input parameter:
|
92 |
+
# (<string> maskdet_img): relative path of the single maskdet image (es: testimg1/maskdet/1.png)
|
93 |
+
# return:
|
94 |
+
# (<BodyPart []> bodypart_list) - for failure/error, return an empty list []
|
95 |
+
def extractAnnotations(maskdet):
|
96 |
+
|
97 |
+
#Load the image
|
98 |
+
#image = cv2.imread(maskdet_img)
|
99 |
+
|
100 |
+
#Find body part
|
101 |
+
tits_list = findBodyPart(maskdet, "tit")
|
102 |
+
aur_list = findBodyPart(maskdet, "aur")
|
103 |
+
vag_list = findBodyPart(maskdet, "vag")
|
104 |
+
belly_list = findBodyPart(maskdet, "belly")
|
105 |
+
|
106 |
+
#Filter out parts basing on dimension (area and aspect ratio):
|
107 |
+
aur_list = filterDimParts(aur_list, 100, 1000, 0.5, 3);
|
108 |
+
tits_list = filterDimParts(tits_list, 1000, 60000, 0.2, 3);
|
109 |
+
vag_list = filterDimParts(vag_list, 10, 1000, 0.2, 3);
|
110 |
+
belly_list = filterDimParts(belly_list, 10, 1000, 0.2, 3);
|
111 |
+
|
112 |
+
#Filter couple (if parts are > 2, choose only 2)
|
113 |
+
aur_list = filterCouple(aur_list);
|
114 |
+
tits_list = filterCouple(tits_list);
|
115 |
+
|
116 |
+
#Detect a missing problem:
|
117 |
+
missing_problem = detectTitAurMissingProblem(tits_list, aur_list) #return a Number (code of the problem)
|
118 |
+
|
119 |
+
#Check if problem is SOLVEABLE:
|
120 |
+
if (missing_problem in [3,6,7,8]):
|
121 |
+
resolveTitAurMissingProblems(tits_list, aur_list, missing_problem)
|
122 |
+
|
123 |
+
#Infer the nips:
|
124 |
+
nip_list = inferNip(aur_list)
|
125 |
+
|
126 |
+
#Infer the hair:
|
127 |
+
hair_list = inferHair(vag_list)
|
128 |
+
|
129 |
+
#Return a combined list:
|
130 |
+
return tits_list + aur_list + nip_list + vag_list + hair_list + belly_list
|
131 |
+
|
132 |
+
# findBodyPart ==============================================================================
|
133 |
+
# input parameters:
|
134 |
+
# (<RGB>image, <string>part_name)
|
135 |
+
# return
|
136 |
+
# (<BodyPart[]>list)
|
137 |
+
def findBodyPart(image, part_name):
|
138 |
+
|
139 |
+
bodypart_list = [] #empty BodyPart list
|
140 |
+
|
141 |
+
#Get the correct color filter:
|
142 |
+
if part_name == "tit":
|
143 |
+
#Use combined color filter
|
144 |
+
f1 = np.asarray([0, 0, 0]) # tit color filter
|
145 |
+
f2 = np.asarray([10, 10, 10])
|
146 |
+
f3 = np.asarray([0, 0, 250]) # aur color filter
|
147 |
+
f4 = np.asarray([0, 0, 255])
|
148 |
+
color_mask1 = cv2.inRange(image, f1, f2)
|
149 |
+
color_mask2 = cv2.inRange(image, f3, f4)
|
150 |
+
color_mask = cv2.bitwise_or(color_mask1, color_mask2) #combine
|
151 |
+
|
152 |
+
elif part_name == "aur":
|
153 |
+
f1 = np.asarray([0, 0, 250]) # aur color filter
|
154 |
+
f2 = np.asarray([0, 0, 255])
|
155 |
+
color_mask = cv2.inRange(image, f1, f2)
|
156 |
+
|
157 |
+
elif part_name == "vag":
|
158 |
+
f1 = np.asarray([250, 0, 0]) # vag filter
|
159 |
+
f2 = np.asarray([255, 0, 0])
|
160 |
+
color_mask = cv2.inRange(image, f1, f2)
|
161 |
+
|
162 |
+
elif part_name == "belly":
|
163 |
+
f1 = np.asarray([250, 0, 250]) # belly filter
|
164 |
+
f2 = np.asarray([255, 0, 255])
|
165 |
+
color_mask = cv2.inRange(image, f1, f2)
|
166 |
+
|
167 |
+
#find contours:
|
168 |
+
contours, hierarchy = cv2.findContours(color_mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
|
169 |
+
|
170 |
+
#for every contour:
|
171 |
+
for cnt in contours:
|
172 |
+
|
173 |
+
if len(cnt)>5: #at least 5 points to fit ellipse
|
174 |
+
|
175 |
+
#(x, y), (MA, ma), angle = cv2.fitEllipse(cnt)
|
176 |
+
ellipse = cv2.fitEllipse(cnt)
|
177 |
+
|
178 |
+
#Fit Result:
|
179 |
+
x = ellipse[0][0] #center x
|
180 |
+
y = ellipse[0][1] #center y
|
181 |
+
angle = ellipse[2] #angle
|
182 |
+
aMin = ellipse[1][0]; #asse minore
|
183 |
+
aMax = ellipse[1][1]; #asse maggiore
|
184 |
+
|
185 |
+
#Detect direction:
|
186 |
+
if angle == 0:
|
187 |
+
h = aMax
|
188 |
+
w = aMin
|
189 |
+
else:
|
190 |
+
h = aMin
|
191 |
+
w = aMax
|
192 |
+
|
193 |
+
#Normalize the belly size:
|
194 |
+
if part_name == "belly":
|
195 |
+
if w<15:
|
196 |
+
w *= 2
|
197 |
+
if h<15:
|
198 |
+
h *= 2
|
199 |
+
|
200 |
+
#Normalize the vag size:
|
201 |
+
if part_name == "vag":
|
202 |
+
if w<15:
|
203 |
+
w *= 2
|
204 |
+
if h<15:
|
205 |
+
h *= 2
|
206 |
+
|
207 |
+
#Calculate Bounding Box:
|
208 |
+
xmin = int(x - (w/2))
|
209 |
+
xmax = int(x + (w/2))
|
210 |
+
ymin = int(y - (h/2))
|
211 |
+
ymax = int(y + (h/2))
|
212 |
+
|
213 |
+
bodypart_list.append(BodyPart(part_name, xmin, ymin, xmax, ymax, x, y, w, h ))
|
214 |
+
|
215 |
+
return bodypart_list
|
216 |
+
|
217 |
+
# filterDimParts ==============================================================================
|
218 |
+
# input parameters:
|
219 |
+
# (<BodyPart[]>list, <num> minimum area of part, <num> max area, <num> min aspect ratio, <num> max aspect ratio)
|
220 |
+
def filterDimParts(bp_list, min_area, max_area, min_ar, max_ar):
|
221 |
+
|
222 |
+
b_filt = []
|
223 |
+
|
224 |
+
for obj in bp_list:
|
225 |
+
|
226 |
+
a = obj.w*obj.h #Object AREA
|
227 |
+
|
228 |
+
if ((a > min_area)and(a < max_area)):
|
229 |
+
|
230 |
+
ar = obj.w/obj.h #Object ASPECT RATIO
|
231 |
+
|
232 |
+
if ((ar>min_ar)and(ar<max_ar)):
|
233 |
+
|
234 |
+
b_filt.append(obj)
|
235 |
+
|
236 |
+
return b_filt
|
237 |
+
|
238 |
+
# filterCouple ==============================================================================
|
239 |
+
# input parameters:
|
240 |
+
# (<BodyPart[]>list)
|
241 |
+
def filterCouple(bp_list):
|
242 |
+
|
243 |
+
#Remove exceed parts
|
244 |
+
if (len(bp_list)>2):
|
245 |
+
|
246 |
+
#trovare coppia (a,b) che minimizza bp_list[a].y-bp_list[b].y
|
247 |
+
min_a = 0
|
248 |
+
min_b = 1
|
249 |
+
min_diff = abs(bp_list[min_a].y-bp_list[min_b].y)
|
250 |
+
|
251 |
+
for a in range(0,len(bp_list)):
|
252 |
+
for b in range(0,len(bp_list)):
|
253 |
+
#TODO: avoid repetition (1,0) (0,1)
|
254 |
+
if a != b:
|
255 |
+
diff = abs(bp_list[a].y-bp_list[b].y)
|
256 |
+
if diff<min_diff:
|
257 |
+
min_diff = diff
|
258 |
+
min_a = a
|
259 |
+
min_b = b
|
260 |
+
b_filt = []
|
261 |
+
|
262 |
+
b_filt.append(bp_list[min_a])
|
263 |
+
b_filt.append(bp_list[min_b])
|
264 |
+
|
265 |
+
return b_filt
|
266 |
+
else:
|
267 |
+
#No change
|
268 |
+
return bp_list
|
269 |
+
|
270 |
+
|
271 |
+
|
272 |
+
# detectTitAurMissingProblem ==============================================================================
|
273 |
+
# input parameters:
|
274 |
+
# (<BodyPart[]> tits list, <BodyPart[]> aur list)
|
275 |
+
# return
|
276 |
+
# (<num> problem code)
|
277 |
+
# TIT | AUR | code | SOLVE? |
|
278 |
+
# 0 | 0 | 1 | NO |
|
279 |
+
# 0 | 1 | 2 | NO |
|
280 |
+
# 0 | 2 | 3 | YES |
|
281 |
+
# 1 | 0 | 4 | NO |
|
282 |
+
# 1 | 1 | 5 | NO |
|
283 |
+
# 1 | 2 | 6 | YES |
|
284 |
+
# 2 | 0 | 7 | YES |
|
285 |
+
# 2 | 1 | 8 | YES |
|
286 |
+
def detectTitAurMissingProblem(tits_list, aur_list):
|
287 |
+
|
288 |
+
t_len = len(tits_list)
|
289 |
+
a_len = len(aur_list)
|
290 |
+
|
291 |
+
if (t_len == 0):
|
292 |
+
if (a_len == 0):
|
293 |
+
return 1
|
294 |
+
elif (a_len == 1):
|
295 |
+
return 2
|
296 |
+
elif (a_len == 2):
|
297 |
+
return 3
|
298 |
+
else:
|
299 |
+
return -1
|
300 |
+
elif (t_len == 1):
|
301 |
+
if (a_len == 0):
|
302 |
+
return 4
|
303 |
+
elif (a_len == 1):
|
304 |
+
return 5
|
305 |
+
elif (a_len == 2):
|
306 |
+
return 6
|
307 |
+
else:
|
308 |
+
return -1
|
309 |
+
elif (t_len == 2):
|
310 |
+
if (a_len == 0):
|
311 |
+
return 7
|
312 |
+
elif (a_len == 1):
|
313 |
+
return 8
|
314 |
+
else:
|
315 |
+
return -1
|
316 |
+
else:
|
317 |
+
return -1
|
318 |
+
|
319 |
+
# resolveTitAurMissingProblems ==============================================================================
|
320 |
+
# input parameters:
|
321 |
+
# (<BodyPart[]> tits list, <BodyPart[]> aur list, problem code)
|
322 |
+
# return
|
323 |
+
# none
|
324 |
+
def resolveTitAurMissingProblems(tits_list, aur_list, problem_code):
|
325 |
+
|
326 |
+
if problem_code == 3:
|
327 |
+
|
328 |
+
random_tit_factor = random.randint(2, 5) #TOTEST
|
329 |
+
|
330 |
+
#Add the first tit:
|
331 |
+
new_w = aur_list[0].w * random_tit_factor #TOTEST
|
332 |
+
new_x = aur_list[0].x
|
333 |
+
new_y = aur_list[0].y
|
334 |
+
|
335 |
+
xmin = int(new_x - (new_w/2))
|
336 |
+
xmax = int(new_x + (new_w/2))
|
337 |
+
ymin = int(new_y - (new_w/2))
|
338 |
+
ymax = int(new_y + (new_w/2))
|
339 |
+
|
340 |
+
tits_list.append(BodyPart("tit", xmin, ymin, xmax, ymax, new_x, new_y, new_w, new_w ))
|
341 |
+
|
342 |
+
#Add the second tit:
|
343 |
+
new_w = aur_list[1].w * random_tit_factor #TOTEST
|
344 |
+
new_x = aur_list[1].x
|
345 |
+
new_y = aur_list[1].y
|
346 |
+
|
347 |
+
xmin = int(new_x - (new_w/2))
|
348 |
+
xmax = int(new_x + (new_w/2))
|
349 |
+
ymin = int(new_y - (new_w/2))
|
350 |
+
ymax = int(new_y + (new_w/2))
|
351 |
+
|
352 |
+
tits_list.append(BodyPart("tit", xmin, ymin, xmax, ymax, new_x, new_y, new_w, new_w ))
|
353 |
+
|
354 |
+
elif problem_code == 6:
|
355 |
+
|
356 |
+
#Find wich aur is full:
|
357 |
+
d1 = abs(tits_list[0].x - aur_list[0].x)
|
358 |
+
d2 = abs(tits_list[0].x - aur_list[1].x)
|
359 |
+
|
360 |
+
if d1 > d2:
|
361 |
+
#aur[0] is empty
|
362 |
+
new_x = aur_list[0].x
|
363 |
+
new_y = aur_list[0].y
|
364 |
+
else:
|
365 |
+
#aur[1] is empty
|
366 |
+
new_x = aur_list[1].x
|
367 |
+
new_y = aur_list[1].y
|
368 |
+
|
369 |
+
#Calculate Bounding Box:
|
370 |
+
xmin = int(new_x - (tits_list[0].w/2))
|
371 |
+
xmax = int(new_x + (tits_list[0].w/2))
|
372 |
+
ymin = int(new_y - (tits_list[0].w/2))
|
373 |
+
ymax = int(new_y + (tits_list[0].w/2))
|
374 |
+
|
375 |
+
tits_list.append(BodyPart("tit", xmin, ymin, xmax, ymax, new_x, new_y, tits_list[0].w, tits_list[0].w ))
|
376 |
+
|
377 |
+
elif problem_code == 7:
|
378 |
+
|
379 |
+
#Add the first aur:
|
380 |
+
new_w = tits_list[0].w * random.uniform(0.03, 0.1) #TOTEST
|
381 |
+
new_x = tits_list[0].x
|
382 |
+
new_y = tits_list[0].y
|
383 |
+
|
384 |
+
xmin = int(new_x - (new_w/2))
|
385 |
+
xmax = int(new_x + (new_w/2))
|
386 |
+
ymin = int(new_y - (new_w/2))
|
387 |
+
ymax = int(new_y + (new_w/2))
|
388 |
+
|
389 |
+
aur_list.append(BodyPart("aur", xmin, ymin, xmax, ymax, new_x, new_y, new_w, new_w ))
|
390 |
+
|
391 |
+
#Add the second aur:
|
392 |
+
new_w = tits_list[1].w * random.uniform(0.03, 0.1) #TOTEST
|
393 |
+
new_x = tits_list[1].x
|
394 |
+
new_y = tits_list[1].y
|
395 |
+
|
396 |
+
xmin = int(new_x - (new_w/2))
|
397 |
+
xmax = int(new_x + (new_w/2))
|
398 |
+
ymin = int(new_y - (new_w/2))
|
399 |
+
ymax = int(new_y + (new_w/2))
|
400 |
+
|
401 |
+
aur_list.append(BodyPart("aur", xmin, ymin, xmax, ymax, new_x, new_y, new_w, new_w ))
|
402 |
+
|
403 |
+
elif problem_code == 8:
|
404 |
+
|
405 |
+
#Find wich tit is full:
|
406 |
+
d1 = abs(aur_list[0].x - tits_list[0].x)
|
407 |
+
d2 = abs(aur_list[0].x - tits_list[1].x)
|
408 |
+
|
409 |
+
if d1 > d2:
|
410 |
+
#tit[0] is empty
|
411 |
+
new_x = tits_list[0].x
|
412 |
+
new_y = tits_list[0].y
|
413 |
+
else:
|
414 |
+
#tit[1] is empty
|
415 |
+
new_x = tits_list[1].x
|
416 |
+
new_y = tits_list[1].y
|
417 |
+
|
418 |
+
#Calculate Bounding Box:
|
419 |
+
xmin = int(new_x - (aur_list[0].w/2))
|
420 |
+
xmax = int(new_x + (aur_list[0].w/2))
|
421 |
+
ymin = int(new_y - (aur_list[0].w/2))
|
422 |
+
ymax = int(new_y + (aur_list[0].w/2))
|
423 |
+
aur_list.append(BodyPart("aur", xmin, ymin, xmax, ymax, new_x, new_y, aur_list[0].w, aur_list[0].w ))
|
424 |
+
|
425 |
+
# detectTitAurPositionProblem ==============================================================================
|
426 |
+
# input parameters:
|
427 |
+
# (<BodyPart[]> tits list, <BodyPart[]> aur list)
|
428 |
+
# return
|
429 |
+
# (<Boolean> True/False)
|
430 |
+
def detectTitAurPositionProblem(tits_list, aur_list):
|
431 |
+
|
432 |
+
diffTitsX = abs(tits_list[0].x - tits_list[1].x)
|
433 |
+
if diffTitsX < 40:
|
434 |
+
print("diffTitsX")
|
435 |
+
#Tits too narrow (orizontally)
|
436 |
+
return True
|
437 |
+
|
438 |
+
diffTitsY = abs(tits_list[0].y - tits_list[1].y)
|
439 |
+
if diffTitsY > 120:
|
440 |
+
#Tits too distanced (vertically)
|
441 |
+
print("diffTitsY")
|
442 |
+
return True
|
443 |
+
|
444 |
+
diffTitsW = abs(tits_list[0].w - tits_list[1].w)
|
445 |
+
if ((diffTitsW < 0.1)or(diffTitsW>60)):
|
446 |
+
print("diffTitsW")
|
447 |
+
#Tits too equals, or too different (width)
|
448 |
+
return True
|
449 |
+
|
450 |
+
#Check if body position is too low (face not covered by watermark)
|
451 |
+
if aur_list[0].y > 350: #tits too low
|
452 |
+
#Calculate the ratio between y and aurs distance
|
453 |
+
rapp = aur_list[0].y/(abs(aur_list[0].x - aur_list[1].x))
|
454 |
+
if rapp > 2.8:
|
455 |
+
print("aurDown")
|
456 |
+
return True
|
457 |
+
|
458 |
+
return False
|
459 |
+
|
460 |
+
# inferNip ==============================================================================
|
461 |
+
# input parameters:
|
462 |
+
# (<BodyPart[]> aur list)
|
463 |
+
# return
|
464 |
+
# (<BodyPart[]> nip list)
|
465 |
+
def inferNip(aur_list):
|
466 |
+
nip_list = []
|
467 |
+
|
468 |
+
for aur in aur_list:
|
469 |
+
|
470 |
+
#Nip rules:
|
471 |
+
# - circle (w == h)
|
472 |
+
# - min dim: 5
|
473 |
+
# - bigger if aur is bigger
|
474 |
+
nip_dim = int(5 + aur.w*random.uniform(0.03, 0.09))
|
475 |
+
|
476 |
+
#center:
|
477 |
+
x = aur.x
|
478 |
+
y = aur.y
|
479 |
+
|
480 |
+
#Calculate Bounding Box:
|
481 |
+
xmin = int(x - (nip_dim/2))
|
482 |
+
xmax = int(x + (nip_dim/2))
|
483 |
+
ymin = int(y - (nip_dim/2))
|
484 |
+
ymax = int(y + (nip_dim/2))
|
485 |
+
|
486 |
+
nip_list.append(BodyPart("nip", xmin, ymin, xmax, ymax, x, y, nip_dim, nip_dim ))
|
487 |
+
|
488 |
+
return nip_list
|
489 |
+
|
490 |
+
# inferHair (TOTEST) ==============================================================================
|
491 |
+
# input parameters:
|
492 |
+
# (<BodyPart[]> vag list)
|
493 |
+
# return
|
494 |
+
# (<BodyPart[]> hair list)
|
495 |
+
def inferHair(vag_list):
|
496 |
+
hair_list = []
|
497 |
+
|
498 |
+
#70% of chanche to add hair
|
499 |
+
if random.uniform(0.0, 1.0) > 0.3:
|
500 |
+
|
501 |
+
for vag in vag_list:
|
502 |
+
|
503 |
+
#Hair rules:
|
504 |
+
hair_w = vag.w*random.uniform(0.4, 1.5)
|
505 |
+
hair_h = vag.h*random.uniform(0.4, 1.5)
|
506 |
+
|
507 |
+
#center:
|
508 |
+
x = vag.x
|
509 |
+
y = vag.y - (hair_h/2) - (vag.h/2)
|
510 |
+
|
511 |
+
#Calculate Bounding Box:
|
512 |
+
xmin = int(x - (hair_w/2))
|
513 |
+
xmax = int(x + (hair_w/2))
|
514 |
+
ymin = int(y - (hair_h/2))
|
515 |
+
ymax = int(y + (hair_h/2))
|
516 |
+
|
517 |
+
hair_list.append(BodyPart("hair", xmin, ymin, xmax, ymax, x, y, hair_w, hair_h ))
|
518 |
+
|
519 |
+
return hair_list
|
opencv_transform/nude_to_watermark.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import numpy as np
|
3 |
+
import os
|
4 |
+
|
5 |
+
# create_watermark ===============================================================
|
6 |
+
# return:
|
7 |
+
# (<Boolean> True/False), depending on the transformation process
|
8 |
+
def create_watermark(nude):
|
9 |
+
|
10 |
+
# Add alpha channel if missing
|
11 |
+
# if nude.shape[2] < 4:
|
12 |
+
# nude = np.dstack([nude, np.ones((512, 512), dtype="uint8") * 255])
|
13 |
+
|
14 |
+
# watermark = cv2.imread("fake.png", cv2.IMREAD_UNCHANGED)
|
15 |
+
|
16 |
+
# f1 = np.asarray([0, 0, 0, 250]) # red color filter
|
17 |
+
# f2 = np.asarray([255, 255, 255, 255])
|
18 |
+
# mask = cv2.bitwise_not(cv2.inRange(watermark, f1, f2))
|
19 |
+
# mask_inv = cv2.bitwise_not(mask)
|
20 |
+
|
21 |
+
# res1 = cv2.bitwise_and(nude, nude, mask = mask)
|
22 |
+
# # res2 = cv2.bitwise_and(nude, nude, mask = mask)
|
23 |
+
# # res2 = cv2.bitwise_and(watermark, watermark, mask = mask_inv)
|
24 |
+
# res = res1
|
25 |
+
|
26 |
+
# alpha = 0.6
|
27 |
+
# return cv2.addWeighted(res, alpha, nude, 1 - alpha, 0)
|
28 |
+
return nude
|