master
wangerke 4 years ago
parent 7595a61360
commit acb3c2ee77

@ -1,21 +1,33 @@
MIT License
Copyright (c) 2022 MitoroMisaka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
GCC RUNTIME LIBRARY EXCEPTION
Version 3.1, 31 March 2009
General information: http://www.gnu.org/licenses/gcc-exception.html
Copyright (C) 2009 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
This GCC Runtime Library Exception ("Exception") is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file (the "Runtime Library") that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception.
When you use GCC to compile a program, GCC may combine portions of certain GCC header files and runtime libraries with the compiled program. The purpose of this Exception is to allow compilation of non-GPL (including proprietary) programs to use, in this way, the header files and runtime libraries covered by this Exception.
0. Definitions.
A file is an "Independent Module" if it either requires the Runtime Library for execution after a Compilation Process, or makes use of an interface provided by the Runtime Library, but is not otherwise based on the Runtime Library.
"GCC" means a version of the GNU Compiler Collection, with or without modifications, governed by version 3 (or a specified later version) of the GNU General Public License (GPL) with the option of using any subsequent versions published by the FSF.
"GPL-compatible Software" is software whose conditions of propagation, modification and use would permit combination with GCC in accord with the license of GCC.
"Target Code" refers to output from any compiler for a real or virtual target processor architecture, in executable form or suitable for input to an assembler, loader, linker and/or execution phase. Notwithstanding that, Target Code does not include data in any format that is used as a compiler intermediate representation, or used for producing a compiler intermediate representation.
The "Compilation Process" transforms code entirely represented in non-intermediate languages designed for human-written code, and/or in Java Virtual Machine byte code, into Target Code. Thus, for example, use of source code generators and preprocessors need not be considered part of the Compilation Process, since the Compilation Process can be understood as starting with the output of the generators or preprocessors.
A Compilation Process is "Eligible" if it is done using GCC, alone or with other GPL-compatible software, or if it is done without using any work based on GCC. For example, using non-GPL-compatible Software to optimize any GCC intermediate representations would not qualify as an Eligible Compilation Process.
1. Grant of Additional Permission.
You have permission to propagate a work of Target Code formed by combining the Runtime Library with Independent Modules, even if such propagation would otherwise violate the terms of GPLv3, provided that all Target Code was generated by Eligible Compilation Processes. You may then convey such a combination under terms of your choice, consistent with the licensing of the Independent Modules.
2. No Weakening of GCC Copyleft.
The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

110
app.py

@ -1,10 +1,11 @@
import os
import random
import cv2
from flask import Flask, request, send_from_directory
from flask_uploads import UploadSet, configure_uploads, IMAGES,\
patch_request_class
from output import out_path , web_path , file_name
from flask import Flask, request, send_from_directory, render_template, jsonify, make_response
from flask_uploads import UploadSet, configure_uploads, IMAGES, \
patch_request_class
from output import out_path, web_path, file_name, direct_path
from program import task
app = Flask(__name__)
@ -16,7 +17,7 @@ patch_request_class(app) # 文件大小限制默认为16MB
# 存储的最开始的图片的名字 后面上传就会改变
photo_name = 'Tsunami_by_hokusai_19th_century.jpg'
app.config['PHOTO_URL'] =os.getcwd() + '\\static\\uploads\\' + 'Tsunami_by_hokusai_19th_century.jpg'
app.config['PHOTO_URL'] = os.getcwd() + '\\static\\uploads\\' + 'Tsunami_by_hokusai_19th_century.jpg'
# 现在的图片的版本
app.config['cnt'] = 0
@ -35,8 +36,9 @@ pure_html = '''
<title>Processed Image</title>
'''
# 主页面
@app.route('/', methods=['GET', 'POST'])
@app.route('/upload_file', methods=['GET', 'POST'])
def upload_file():
cnt = 0
del_all()
@ -51,8 +53,48 @@ def upload_file():
img = cv2.imread(app.config['PHOTO_URL']) # 根据路径读取一张图片
cv2.imwrite(out_path(0), img)
print(file_url)
return html + '<br><img src=' + file_url + '>'
return html
res = {
'code': 0,
'url_before': direct_path(app.config['cnt']) + '?' + str(random.random()),
'url_after': ''
}
print(res)
return jsonify(res)
res = {
'code': -1,
'url_before': '',
'url_after': ''
}
print(res)
return jsonify(res)
@app.route('/upload_style', methods=['GET', 'POST'])
def upload_style():
cnt = 0
del_all()
if request.method == 'POST' and 'photo' in request.files:
filename = photos.save(request.files['photo'])
# app.name = filename
app.photo_name = filename
file_url = photos.url(filename)
print(file_url)
app.config['PHOTO_URL'] = os.getcwd() + '\\static\\uploads\\' + filename
print(app.config['PHOTO_URL'] + 'photourl')
img = cv2.imread(app.config['PHOTO_URL']) # 根据路径读取一张图片
cv2.imwrite(out_path(0), img)
print(file_url)
cv2.imwrite('./img_src/styles/style0.jpg', img)
res = {
'code': 0,
}
print(res)
return jsonify(res)
res = {
'code': -1,
}
print(res)
return jsonify(res)
# 删除uploads文件夹 (不用设置接口)
@ -65,6 +107,8 @@ def del_all():
del_file(c_path)
else:
os.remove(c_path)
app.config['cnt'] = 0
# 用在delete_all里面不用设置接口 (不用设置接口)
@app.route('/delete_file/<path>')
@ -74,19 +118,43 @@ def del_file(path):
# 通过commmand_id来选择处理的方式commmand_id具体内容再program.py里面找
@app.route('/deal/<command_id>')
@app.route('/deal/<command_id>', methods=['GET', 'POST'])
def deal(command_id):
img = cv2.imread(app.config['PHOTO_URL']) # 根据路径读取一张图片
cmd = command_id
res = {
'code': -1,
'url_before': '',
'url_after': ''
}
cmd = command_id
if (cmd == 'b' or cmd == 'back'):
# 撤销操作
if (app.config['cnt'] > 0):
if (app.config['cnt'] > 1):
if os.path.exists(out_path(app.config['cnt'])):
os.remove(out_path(app.config['cnt']))
app.config['cnt'] = app.config['cnt'] - 1
print('back success')
print(app.config['cnt'])
app.config['cnt'] = app.config['cnt'] - 1
res = {
'code': 0,
'url_before': direct_path(app.config['cnt'] - 1) + '?' + str(random.random()),
'url_after': direct_path(app.config['cnt']) + '?' + str(random.random())
}
elif (app.config['cnt'] == 1):
res = {
'code': 0,
'url_before': direct_path(app.config['cnt'] - 1) + '?' + str(random.random()),
'url_after': ''
}
app.config['cnt'] = app.config['cnt'] - 1
elif (app.config['cnt'] == 0):
res = {
'code': 1,
'url_before': direct_path(app.config['cnt'] - 1) + '?' + str(random.random()),
'url_after': ''
}
elif (cmd == 's' or cmd == 'save'):
# 保存操作
@ -105,16 +173,26 @@ def deal(command_id):
success = task(cmd, app.config['cnt'])
if (success == 0):
app.config['cnt'] = app.config['cnt'] + 1
res = {
'code': 0,
'url_before': direct_path(app.config['cnt'] - 1) + '?' + str(random.random()),
'url_after': direct_path(app.config['cnt']) + '?' + str(random.random()),
}
str_cnt = str(app.config['cnt'])
print(type(str_cnt))
print(app.config['cnt'])
return pure_html + web_path(app.config['cnt'])
return jsonify(res)
# 这个download会下载最新的照片
@app.route('/download', methods=['POST','GET'])
@app.route('/download', methods=['POST', 'GET'])
def download():
direct_path = os.getcwd() + '\\static\\uploads'
return send_from_directory(direct_path, file_name(app.config['cnt']), as_attachment=True)
# return send_from_directory(direct_path, file_name(app.config['cnt']), as_attachment=True)
response = send_from_directory(direct_path, file_name(app.config['cnt']), as_attachment=True)
response.headers["Access-Control-Expose-Headers"] = "Content-disposition"
return response
if __name__ == '__main__':
app.run()
app.run()

@ -0,0 +1,4 @@
import util.util as util
if __name__ == "__main__":
util.download_pretrained_models()

@ -1 +1 @@
static/uploads/0.jpg
static/uploads/0.jgg

@ -9,7 +9,7 @@ def operate(decide,cnt):
if(decide==0):#非
X = ~X
else:
Y = cv2.imread('../img_src/operate.jpg')
Y = cv2.imread('./img_src/operate.jpg')
Y = cv2.resize(Y, (width, height), interpolation=cv2.INTER_LINEAR)
if(decide==1):#或
X = X | Y

@ -30,7 +30,7 @@ def Aging(decide, cnt):
def Aging_core(cnt, opt):
with open('image_list.txt', 'w') as f: # 设置文件对象
f.write('static/uploads/' + str(cnt) + '.jpg') # 将字符串写入文件中
f.write('static/uploads/' + str(cnt) + '.jgg') # 将字符串写入文件中
opt.nThreads = 1 # test code only supports nThreads = 1
opt.batchSize = 1 # test code only supports batchSize = 1

@ -8,6 +8,7 @@ import matplotlib.pyplot as plt
import torchvision.transforms as transforms
import torchvision.models as models
from flask import app
from torchvision.utils import save_image
from utils import *
@ -25,7 +26,7 @@ def style_transfer(decide,cnt):
set_style(decide)
de_resize(cnt)
width = 512
style_img = read_image('../img_src/style.jpg', target_width=width).to(device)
style_img = read_image('./img_src/style.jpg', target_width=width).to(device)
content_img = read_image(out_path(cnt), target_width=width).to(device)
# plt.figure(figsize=(12, 6))
@ -91,7 +92,7 @@ def style_transfer(decide,cnt):
plt.subplot(1, 3, 3)
imshow(input_img, title='Output Image')
plt.savefig('../img_src/transfer.jpg')
plt.savefig('./img_src/transfer.jpg')
plt.figure(figsize=(8, 8))
plt.subplot(1, 1, 1)
@ -105,12 +106,12 @@ def de_resize(cnt):
img = cv2.imread(out_path(cnt))
img = cv2.resize(img, (612, 612), interpolation=cv2.INTER_LINEAR)
cv2.imwrite(out_path(cnt), img)
img = cv2.imread('../img_src/style.jpg')
img = cv2.imread('./img_src/style.jpg')
img = cv2.resize(img, (612, 612), interpolation=cv2.INTER_LINEAR)
cv2.imwrite('../img_src/style.jpg', img)
cv2.imwrite('./img_src/style.jpg', img)
def set_style(decide):
file_name = '../img_src/styles/style'+ str(int(decide)) +'.jpg'
file_name = './img_src/styles/style'+ str(int(decide)) +'.jpg'
if os.path.exists(file_name):
img = cv2.imread(file_name)
cv2.imwrite('../img_src/style.jpg', img)
cv2.imwrite('./img_src/style.jpg', img)

@ -9,7 +9,7 @@ if __name__ == '__main__':
if os.path.exists(out_path(id)):
os.remove(out_path(id))
cnt = 0;
img = cv2.imread('../img_src/origin.jpg') # 根据路径读取一张图片
img = cv2.imread('./img_src/origin.jpg') # 根据路径读取一张图片
cv2.imwrite(out_path(cnt),img)
while(1):
cmd = input("cmd: ")

@ -12,9 +12,9 @@ class BaseOptions():
def initialize(self):
# experiment specifics
self.parser.add_argument('--name', type=str, default='males_model', help='name of the experiment. It decides where to store samples and models')
self.parser.add_argument('--name', type=str, default='males_model', help='name of the experiment. It decides where to store samples and agingModels')
self.parser.add_argument('--gpu_ids', type=str, default='0', help='gpu ids: e.g. 0 0,1,2, 0,2. use -1 for CPU')
self.parser.add_argument('--checkpoints_dir', type=str, default='./checkpoints', help='models are saved here')
self.parser.add_argument('--checkpoints_dir', type=str, default='./checkpoints', help='agingModels are saved here')
# input/output sizes
self.parser.add_argument('--batchSize', type=int, default=1, help='input batch size')
@ -40,13 +40,13 @@ class BaseOptions():
self.parser.add_argument('--display_id', type=int, default=0, help='window id of the web display')
# for generator
self.parser.add_argument('--use_modulated_conv', type=bool, default=True, help='if specified, use modulated conv layers in the decoder like in StyleGAN2')
self.parser.add_argument('--conv_weight_norm', type=bool, default=True, help='if specified, use weight normalization in conv and linear layers like in progrssive growing of GANs')
self.parser.add_argument('--use_modulated_conv', type=bool, default = True, help='if specified, use modulated conv layers in the decoder like in StyleGAN2')
self.parser.add_argument('--conv_weight_norm', type=bool, default = True, help='if specified, use weight normalization in conv and linear layers like in progrssive growing of GANs')
self.parser.add_argument('--id_enc_norm', type=str, default='pixel', help='instance, pixel normalization')
self.parser.add_argument('--decoder_norm',type=str, default='pixel', choices=['pixel','none'], help='type of upsampling layers normalization')
self.parser.add_argument('--n_adaptive_blocks', type=int, default=4, help='# of adaptive normalization blocks')
self.parser.add_argument('--activation',type=str, default='lrelu', choices=['relu','lrelu'], help='type of generator activation layer')
self.parser.add_argument('--normalize_mlp', type=bool, default=True, help='if specified, normalize the generator MLP inputs and outputs')
self.parser.add_argument('--normalize_mlp', type=bool, default = True, help='if specified, normalize the generator MLP inputs and outputs')
self.parser.add_argument('--no_moving_avg', action='store_true', help='if specified, do not use moving average network')
self.parser.add_argument('--use_resblk_pixel_norm', action='store_true', help='if specified, apply pixel norm on the resnet block outputs')
self.parser.add_argument('--ngf', type=int, default=64, help='# of gen filters in first conv layer')

@ -8,6 +8,7 @@ from img_4_noise import *
from img_5_enhance import *
from img_6_morphology import *
from img_styleTransfer import *
from img_aging import *
def task(cmd, cnt):
@ -96,6 +97,12 @@ def task(cmd, cnt):
elif (cmd == '73'): # 预设风格3
style_transfer(3, cnt)
# 年龄转换
elif (cmd == '80'):
Aging(0, cnt) #此时启用男性年龄模型
elif (cmd == '81'):
Aging(1, cnt) #此时启用女性年龄模型
else:
print('Invalid command!')
return 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

@ -22,7 +22,7 @@ class preprocessInTheWildImage():
def __init__(self, out_size=256):
self.out_size = out_size
# load landmark detector agingModels
# load landmark detector models
self.detector = dlib.get_frontal_face_detector()
if not os.path.isfile(predictor_file_path):
print('Cannot find landmarks shape predictor model.\n'\

@ -11,7 +11,6 @@ import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
cnn_normalization_mean = [0.485, 0.456, 0.406]
cnn_normalization_std = [0.229, 0.224, 0.225]
tensor_normalizer = transforms.Normalize(mean=cnn_normalization_mean, std=cnn_normalization_std)
@ -22,15 +21,15 @@ def preprocess_image(image, target_width=None):
"""输入 PIL.Image 对象,输出标准化后的四维 tensor"""
if target_width:
t = transforms.Compose([
transforms.Resize(target_width),
transforms.CenterCrop(target_width),
transforms.ToTensor(),
tensor_normalizer,
transforms.Resize(target_width),
transforms.CenterCrop(target_width),
transforms.ToTensor(),
tensor_normalizer,
])
else:
t = transforms.Compose([
transforms.ToTensor(),
tensor_normalizer,
transforms.ToTensor(),
tensor_normalizer,
])
return t(image).unsqueeze(0)
@ -52,7 +51,7 @@ def recover_image(tensor):
"""输入 GPU 上的四维 tensor输出 0~255 范围的三维 numpy 矩阵RGB 顺序"""
image = tensor.detach().cpu().numpy()
image = image * np.array(cnn_normalization_std).reshape((1, 3, 1, 1)) + \
np.array(cnn_normalization_mean).reshape((1, 3, 1, 1))
np.array(cnn_normalization_mean).reshape((1, 3, 1, 1))
return (image.transpose(0, 2, 3, 1) * 255.).clip(0, 255).astype(np.uint8)[0]
@ -79,7 +78,7 @@ def mean_std(features):
x = x.view(*x.shape[:2], -1)
x = torch.cat([x.mean(-1), torch.sqrt(x.var(-1) + epsilon)], dim=-1)
n = x.shape[0]
x2 = x.view(n, 2, -1).transpose(2, 1).contiguous().view(n, -1) # 【mean, ..., std, ...] to [mean, std, ...]
x2 = x.view(n, 2, -1).transpose(2, 1).contiguous().view(n, -1) # 【mean, ..., std, ...] to [mean, std, ...]
mean_std_features.append(x2)
mean_std_features = torch.cat(mean_std_features, dim=-1)
return mean_std_features
@ -91,16 +90,16 @@ class Smooth:
self.window_size = windowsize
self.data = np.zeros((self.window_size, 1), dtype=np.float32)
self.index = 0
def __iadd__(self, x):
if self.index == 0:
self.data[:] = x
self.data[self.index % self.window_size] = x
self.index += 1
return self
def __float__(self):
return float(self.data.mean())
def __format__(self, f):
return self.__float__().__format__(f)
return self.__float__().__format__(f)
Loading…
Cancel
Save