Files
xsl 443cfa298f 初始化:换发型/换发色/训练发型服务
包含:
- hair_service_sd: 主服务(换发型/换发色/生发,端口8801)
- photo_service: LoRA调度+训练(端口32678)
- hair_grow_service: 调试测试页(端口8888,含4个测试页)
- 批量训练脚本(batch_train_hairstyles.py)
- 发际线mask自动识别(hairline_mask.py,4种方案)
- 手绘mask换发型(hair_swap_manual.py)
- 文档:README.md + LARGE_FILES.md + docs/

大文件(模型权重200G、训练数据123G)已排除,见 LARGE_FILES.md
OSS/COS密钥已脱敏为环境变量,原文件备份在本地
2026-07-07 13:53:52 +08:00

1664 lines
88 KiB
Python
Executable File

import colorsys
import cv2
import numpy as np
import random
import math
import time
mean_face_x = np.array([
0.000213256, 0.0752622, 0.18113, 0.29077, 0.393397, 0.586856, 0.689483, 0.799124,
0.904991, 0.98004, 0.490127, 0.490127, 0.490127, 0.490127, 0.36688, 0.426036,
0.490127, 0.554217, 0.613373, 0.121737, 0.187122, 0.265825, 0.334606, 0.260918,
0.182743, 0.645647, 0.714428, 0.793132, 0.858516, 0.79751, 0.719335, 0.254149,
0.340985, 0.428858, 0.490127, 0.551395, 0.639268, 0.726104, 0.642159, 0.556721,
0.490127, 0.423532, 0.338094, 0.290379, 0.428096, 0.490127, 0.552157, 0.689874,
0.553364, 0.490127, 0.42689])
mean_face_y = np.array([
0.106454, 0.038915, 0.0187482, 0.0344891, 0.0773906, 0.0773906, 0.0344891,
0.0187482, 0.038915, 0.106454, 0.203352, 0.307009, 0.409805, 0.515625, 0.587326,
0.609345, 0.628106, 0.609345, 0.587326, 0.216423, 0.178758, 0.179852, 0.231733,
0.245099, 0.244077, 0.231733, 0.179852, 0.178758, 0.216423, 0.244077, 0.245099,
0.780233, 0.745405, 0.727388, 0.742578, 0.727388, 0.745405, 0.780233, 0.864805,
0.902192, 0.909281, 0.902192, 0.864805, 0.784792, 0.778746, 0.785343, 0.778746,
0.784792, 0.824182, 0.831803, 0.824182])
landmarks_2D = np.stack([mean_face_x, mean_face_y], axis=1)
mean_face_x_1k = np.array([0.498047, 0.504671, 0.511286, 0.517984, 0.524451, 0.531086, 0.537574, 0.543902, 0.550305, 0.556545, 0.562891, 0.568903, 0.574994, 0.581092, 0.587026, 0.592814, 0.598603, 0.604259, 0.609802, 0.615311, 0.620821, 0.626135, 0.631542, 0.636597, 0.641621, 0.646680, 0.651656, 0.656505, 0.661374, 0.666025, 0.670571, 0.675225, 0.679616, 0.683987, 0.688181, 0.692460, 0.696634, 0.700552, 0.704500, 0.708402, 0.712261, 0.715842, 0.719373, 0.722930, 0.726486, 0.729785, 0.732875, 0.736135, 0.739115, 0.742179, 0.744925, 0.747688, 0.750314, 0.752887, 0.755412, 0.757737, 0.760038, 0.762291, 0.764312, 0.766333, 0.768259, 0.770363, 0.771888, 0.773763, 0.775485, 0.777069, 0.778656, 0.780126, 0.781483, 0.782879, 0.784085, 0.785261, 0.786402, 0.787338, 0.788398, 0.789310, 0.790038, 0.790796, 0.791281, 0.792001, 0.792397, 0.792903, 0.793221, 0.793554, 0.793613, 0.793848, 0.793856, 0.793925, 0.793911, 0.793825, 0.793601, 0.793426, 0.793199, 0.792833, 0.792528, 0.791962, 0.791501, 0.790897, 0.790382, 0.789660, 0.788884, 0.787702, 0.786300, 0.784951, 0.783363, 0.781861, 0.780103, 0.778348, 0.776405, 0.774489, 0.772390, 0.770098, 0.767540, 0.765030, 0.762359, 0.759349, 0.756513, 0.753197, 0.749784, 0.746353, 0.742572, 0.738633, 0.734433, 0.730200, 0.725658, 0.720657, 0.715711, 0.710406, 0.705108, 0.699482, 0.693569, 0.687476, 0.681209, 0.674681, 0.668094, 0.661239, 0.654234, 0.647131, 0.639989, 0.632582, 0.625134, 0.617439, 0.610009, 0.602125, 0.594318, 0.586546, 0.578466, 0.570582, 0.562638, 0.554622, 0.546602, 0.538546, 0.530536, 0.522423, 0.514258, 0.506205, 0.498047, 0.489889, 0.481836, 0.473671, 0.465558, 0.457548, 0.449491, 0.441472, 0.433455, 0.425511, 0.417628, 0.409547, 0.401776, 0.393969, 0.386085, 0.378655, 0.370960, 0.363512, 0.356105, 0.348963, 0.341860, 0.334855, 0.328000, 0.321412, 0.314885, 0.308618, 0.302525, 0.296612, 0.290986, 0.285687, 0.280382, 0.275437, 0.270436, 0.265894, 0.261660, 0.257461, 0.253522, 0.249740, 0.246310, 0.242897, 0.239580, 0.236744, 0.233735, 0.231064, 0.228553, 0.225996, 0.223704, 0.221605, 0.219689, 0.217746, 0.215990, 0.214232, 0.212730, 0.211143, 0.209794, 0.208392, 0.207210, 0.206433, 0.205712, 0.205197, 0.204593, 0.204132, 0.203565, 0.203261, 0.202895, 0.202667, 0.202492, 0.202268, 0.202183, 0.202169, 0.202238, 0.202246, 0.202480, 0.202540, 0.202873, 0.203191, 0.203696, 0.204093, 0.204813, 0.205297, 0.206055, 0.206783, 0.207696, 0.208755, 0.209692, 0.210833, 0.212009, 0.213215, 0.214611, 0.215967, 0.217438, 0.219024, 0.220609, 0.222330, 0.224206, 0.225731, 0.227835, 0.229761, 0.231781, 0.233803, 0.236055, 0.238356, 0.240681, 0.243207, 0.245780, 0.248405, 0.251168, 0.253915, 0.256979, 0.259958, 0.263219, 0.266309, 0.269608, 0.273163, 0.276721, 0.280252, 0.283833, 0.287692, 0.291593, 0.295541, 0.299459, 0.303633, 0.307913, 0.312107, 0.316478, 0.320869, 0.325523, 0.330069, 0.334719, 0.339589, 0.344438, 0.349414, 0.354473, 0.359497, 0.364552, 0.369959, 0.375273, 0.380783, 0.386292, 0.391835, 0.397491, 0.403280, 0.409068, 0.415002, 0.421100, 0.427190, 0.433203, 0.439548, 0.445789, 0.452191, 0.458520, 0.465008, 0.471643, 0.478110, 0.484807, 0.491422, 0.396255, 0.397888, 0.399588, 0.401344, 0.403150, 0.405001, 0.406895, 0.408831, 0.410807, 0.412822, 0.414875, 0.416966, 0.419095, 0.421262, 0.423465, 0.425705, 0.427981, 0.430294, 0.432644, 0.435030, 0.437451, 0.439908, 0.442400, 0.444928, 0.447489, 0.450084, 0.452712, 0.455372, 0.458062, 0.460782, 0.463531, 0.466307, 0.469108, 0.471933, 0.474781, 0.477648, 0.480532, 0.483432, 0.486345, 0.489267, 0.492194, 0.495123, 0.498047, 0.500971, 0.503899, 0.506827, 0.509749, 0.512662, 0.515562, 0.518446, 0.521313, 0.524160, 0.526986, 0.529787, 0.532563, 0.535312, 0.538032, 0.540722, 0.543382, 0.546009, 0.548605, 0.551166, 0.553693, 0.556186, 0.558642, 0.561064, 0.563450, 0.565799, 0.568113, 0.570389, 0.572629, 0.574832, 0.576998, 0.579127, 0.581219, 0.583272, 0.585287, 0.587263, 0.589198, 0.591093, 0.592944, 0.594749, 0.596506, 0.598206, 0.599839, 0.597799, 0.595660, 0.593444, 0.591167, 0.588838, 0.586464, 0.584049, 0.581599, 0.579114, 0.576598, 0.574052, 0.571476, 0.568873, 0.566242, 0.563585, 0.560901, 0.558193, 0.555461, 0.552704, 0.549922, 0.547116, 0.544286, 0.541432, 0.538555, 0.535655, 0.532732, 0.529786, 0.526819, 0.523832, 0.520830, 0.517033, 0.513236, 0.509439, 0.505641, 0.501844, 0.498047, 0.494250, 0.490452, 0.486655, 0.482858, 0.479061, 0.475264, 0.472262, 0.469275, 0.466308, 0.463362, 0.460439, 0.457538, 0.454662, 0.451808, 0.448978, 0.446172, 0.443390, 0.440633, 0.437900, 0.435192, 0.432509, 0.429852, 0.427221, 0.424617, 0.422042, 0.419496, 0.416979, 0.414495, 0.412044, 0.409630, 0.407256, 0.404927, 0.402650, 0.400434, 0.398294, 0.410228, 0.414399, 0.418630, 0.422899, 0.427196, 0.431515, 0.435855, 0.440212, 0.444587, 0.448978, 0.453385, 0.457806, 0.462242, 0.466691, 0.471152, 0.475622, 0.480101, 0.484586, 0.489074, 0.493564, 0.498047, 0.502530, 0.507020, 0.511508, 0.515993, 0.520472, 0.524942, 0.529403, 0.533852, 0.538288, 0.542709, 0.547116, 0.551507, 0.555882, 0.560238, 0.564578, 0.568898, 0.573194, 0.577464, 0.581695, 0.585866, 0.581642, 0.577369, 0.573066, 0.568743, 0.564401, 0.560044, 0.555673, 0.551287, 0.546890, 0.542478, 0.538055, 0.533622, 0.529181, 0.524733, 0.520280, 0.515825, 0.511370, 0.506919, 0.502475, 0.498047, 0.493618, 0.489175, 0.484723, 0.480269, 0.475814, 0.471361, 0.466913, 0.462472, 0.458039, 0.453616, 0.449204, 0.444806, 0.440421, 0.436050, 0.431693, 0.427351, 0.423027, 0.418725, 0.414452, 0.459656, 0.459227, 0.458691, 0.458058, 0.457338, 0.456539, 0.455664, 0.454719, 0.453708, 0.452633, 0.451497, 0.450302, 0.449049, 0.447741, 0.446378, 0.444962, 0.443494, 0.441973, 0.440402, 0.438780, 0.437107, 0.435384, 0.433612, 0.431790, 0.429919, 0.427998, 0.426028, 0.424009, 0.421938, 0.419814, 0.417632, 0.415384, 0.442766, 0.471804, 0.498047, 0.524290, 0.553327, 0.580709, 0.578462, 0.576279, 0.574156, 0.572085, 0.570065, 0.568095, 0.566175, 0.564304, 0.562481, 0.560709, 0.558987, 0.557314, 0.555692, 0.554120, 0.552600, 0.551131, 0.549715, 0.548353, 0.547044, 0.545792, 0.544597, 0.543461, 0.542386, 0.541375, 0.540430, 0.539555, 0.538755, 0.538036, 0.537403, 0.536867, 0.536438, 0.551823, 0.524746, 0.471347, 0.444271, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.498047, 0.370401, 0.394341, 0.393977, 0.392891, 0.391151, 0.388793, 0.385710, 0.382329, 0.378604, 0.374564, 0.370390, 0.366216, 0.362177, 0.358453, 0.355074, 0.351995, 0.349640, 0.347903, 0.346822, 0.346461, 0.346826, 0.347911, 0.349651, 0.352010, 0.355092, 0.358473, 0.362199, 0.366239, 0.370413, 0.374587, 0.378626, 0.382350, 0.385728, 0.388808, 0.391163, 0.392899, 0.393981, 0.423391, 0.421623, 0.419536, 0.417200, 0.414654, 0.411925, 0.409036, 0.406003, 0.402844, 0.399571, 0.396199, 0.392740, 0.389206, 0.385609, 0.381960, 0.378271, 0.374552, 0.370812, 0.367063, 0.363314, 0.359575, 0.355859, 0.352173, 0.348530, 0.344945, 0.341429, 0.337998, 0.334669, 0.331464, 0.328407, 0.325532, 0.322889, 0.320595, 0.322717, 0.325103, 0.327689, 0.330440, 0.333327, 0.336328, 0.339426, 0.342603, 0.345848, 0.349146, 0.352488, 0.355863, 0.359264, 0.362683, 0.366116, 0.369556, 0.372999, 0.376442, 0.379882, 0.383316, 0.386742, 0.390158, 0.393563, 0.396955, 0.400332, 0.403694, 0.407038, 0.410363, 0.413666, 0.416943, 0.420190, 0.625692, 0.649633, 0.649272, 0.648190, 0.646454, 0.644099, 0.641019, 0.637641, 0.633917, 0.629878, 0.625704, 0.621530, 0.617490, 0.613764, 0.610383, 0.607301, 0.604942, 0.603202, 0.602117, 0.601752, 0.602113, 0.603194, 0.604931, 0.607286, 0.610365, 0.613744, 0.617468, 0.621507, 0.625681, 0.629855, 0.633895, 0.637621, 0.641001, 0.644084, 0.646442, 0.648182, 0.649268, 0.572703, 0.574471, 0.576557, 0.578893, 0.581440, 0.584168, 0.587058, 0.590090, 0.593250, 0.596523, 0.599895, 0.603354, 0.606888, 0.610485, 0.614134, 0.617823, 0.621542, 0.625282, 0.629031, 0.632780, 0.636518, 0.640235, 0.643921, 0.647563, 0.651149, 0.654665, 0.658096, 0.661425, 0.664630, 0.667686, 0.670562, 0.673205, 0.675499, 0.673377, 0.670991, 0.668404, 0.665654, 0.662767, 0.659765, 0.656668, 0.653491, 0.650246, 0.646948, 0.643606, 0.640231, 0.636830, 0.633411, 0.629978, 0.626538, 0.623095, 0.619652, 0.616212, 0.612778, 0.609352, 0.605936, 0.602531, 0.599139, 0.595762, 0.592400, 0.589056, 0.585731, 0.582428, 0.579150, 0.575904, 0.552267, 0.555073, 0.558014, 0.561313, 0.565180, 0.569636, 0.574564, 0.579836, 0.585356, 0.591050, 0.596857, 0.602735, 0.608652, 0.614591, 0.620542, 0.626500, 0.632462, 0.638425, 0.644390, 0.649985, 0.655581, 0.661175, 0.666765, 0.672343, 0.677894, 0.683391, 0.688788, 0.694021, 0.699020, 0.703737, 0.708170, 0.712362, 0.716374, 0.720268, 0.724091, 0.727877, 0.731647, 0.726965, 0.722281, 0.717595, 0.712902, 0.708202, 0.703489, 0.698762, 0.694017, 0.689253, 0.684472, 0.679678, 0.674876, 0.670068, 0.665257, 0.660446, 0.655633, 0.650821, 0.646008, 0.640808, 0.635608, 0.630406, 0.625203, 0.619997, 0.614788, 0.609577, 0.604360, 0.599139, 0.593915, 0.588693, 0.583472, 0.578256, 0.573043, 0.567837, 0.562637, 0.557446, 0.264446, 0.268217, 0.272003, 0.275826, 0.279720, 0.283732, 0.287924, 0.292357, 0.297074, 0.302073, 0.307305, 0.312703, 0.318199, 0.323751, 0.329329, 0.334919, 0.340513, 0.346109, 0.351704, 0.357669, 0.363632, 0.369594, 0.375552, 0.381503, 0.387442, 0.393359, 0.399237, 0.405044, 0.410737, 0.416258, 0.421530, 0.426457, 0.430914, 0.434781, 0.438079, 0.441020, 0.443827, 0.438648, 0.433457, 0.428257, 0.423050, 0.417838, 0.412621, 0.407401, 0.402179, 0.396955, 0.391734, 0.386517, 0.381305, 0.376096, 0.370891, 0.365688, 0.360486, 0.355285, 0.350085, 0.345273, 0.340460, 0.335648, 0.330836, 0.326026, 0.321218, 0.316416, 0.311622, 0.306841, 0.302077, 0.297332, 0.292605, 0.287892, 0.283191, 0.278499, 0.273812, 0.269128
])
mean_face_y_1k = np.array([0.851392, 0.851204, 0.850802, 0.849951, 0.849050, 0.847896, 0.846372, 0.844708, 0.842887, 0.840805, 0.838470, 0.836093, 0.833361, 0.830589, 0.827781, 0.824650, 0.821361, 0.817917, 0.814463, 0.810803, 0.807127, 0.803118, 0.799272, 0.795088, 0.790897, 0.786585, 0.782195, 0.777726, 0.773128, 0.768407, 0.763595, 0.758801, 0.753939, 0.748915, 0.743745, 0.738664, 0.733510, 0.728055, 0.722725, 0.717442, 0.711952, 0.706343, 0.700725, 0.695036, 0.689315, 0.683557, 0.677857, 0.671952, 0.666097, 0.659596, 0.652993, 0.646386, 0.639687, 0.632843, 0.626218, 0.619403, 0.612554, 0.605551, 0.598705, 0.591735, 0.584939, 0.577854, 0.571094, 0.564026, 0.557009, 0.549978, 0.542887, 0.535838, 0.528892, 0.521764, 0.514596, 0.507444, 0.500318, 0.493164, 0.486134, 0.478851, 0.471725, 0.464586, 0.457279, 0.450071, 0.443049, 0.435691, 0.428445, 0.421397, 0.414262, 0.406894, 0.399680, 0.392547, 0.385399, 0.378182, 0.370759, 0.363690, 0.356390, 0.349346, 0.341952, 0.335000, 0.327902, 0.320707, 0.313459, 0.306325, 0.299213, 0.291181, 0.283309, 0.275338, 0.267185, 0.259441, 0.251545, 0.243652, 0.235765, 0.228054, 0.220194, 0.212369, 0.204820, 0.197130, 0.189558, 0.182061, 0.174602, 0.167242, 0.159851, 0.152736, 0.145606, 0.138595, 0.131706, 0.125067, 0.118485, 0.112101, 0.105897, 0.099812, 0.094088, 0.088477, 0.082962, 0.077854, 0.072924, 0.068273, 0.063748, 0.059715, 0.055721, 0.052042, 0.048762, 0.045388, 0.042616, 0.039888, 0.037449, 0.035191, 0.033201, 0.031339, 0.029751, 0.028369, 0.027112, 0.025987, 0.025155, 0.024428, 0.023762, 0.023446, 0.023057, 0.022894, 0.022946, 0.022894, 0.023057, 0.023446, 0.023762, 0.024428, 0.025155, 0.025987, 0.027112, 0.028369, 0.029751, 0.031339, 0.033201, 0.035191, 0.037449, 0.039888, 0.042616, 0.045388, 0.048762, 0.052042, 0.055721, 0.059715, 0.063748, 0.068273, 0.072924, 0.077854, 0.082962, 0.088477, 0.094088, 0.099812, 0.105897, 0.112101, 0.118485, 0.125067, 0.131706, 0.138595, 0.145606, 0.152736, 0.159851, 0.167242, 0.174602, 0.182061, 0.189558, 0.197130, 0.204820, 0.212369, 0.220194, 0.228054, 0.235765, 0.243652, 0.251545, 0.259441, 0.267185, 0.275338, 0.283309, 0.291181, 0.299213, 0.306325, 0.313459, 0.320707, 0.327902, 0.335000, 0.341952, 0.349346, 0.356390, 0.363690, 0.370759, 0.378182, 0.385399, 0.392547, 0.399680, 0.406894, 0.414262, 0.421397, 0.428445, 0.435691, 0.443049, 0.450071, 0.457279, 0.464586, 0.471725, 0.478851, 0.486134, 0.493164, 0.500318, 0.507444, 0.514596, 0.521764, 0.528892, 0.535838, 0.542887, 0.549978, 0.557009, 0.564026, 0.571094, 0.577854, 0.584939, 0.591735, 0.598705, 0.605551, 0.612554, 0.619403, 0.626218, 0.632843, 0.639687, 0.646386, 0.652993, 0.659596, 0.666097, 0.671952, 0.677857, 0.683557, 0.689315, 0.695036, 0.700725, 0.706343, 0.711952, 0.717442, 0.722725, 0.728055, 0.733510, 0.738664, 0.743745, 0.748915, 0.753939, 0.758801, 0.763595, 0.768407, 0.773128, 0.777726, 0.782195, 0.786585, 0.790897, 0.795088, 0.799272, 0.803118, 0.807127, 0.810803, 0.814463, 0.817917, 0.821361, 0.824650, 0.827781, 0.830589, 0.833361, 0.836093, 0.838470, 0.840805, 0.842887, 0.844708, 0.846372, 0.847896, 0.849050, 0.849951, 0.850802, 0.851204, 0.664237, 0.666525, 0.668791, 0.671031, 0.673242, 0.675423, 0.677571, 0.679687, 0.681769, 0.683818, 0.685829, 0.687805, 0.689742, 0.691641, 0.693499, 0.695315, 0.697088, 0.698816, 0.700499, 0.702133, 0.703718, 0.705251, 0.706730, 0.708155, 0.709522, 0.710829, 0.712076, 0.713258, 0.714375, 0.715424, 0.716404, 0.717311, 0.718144, 0.718900, 0.719577, 0.720171, 0.720681, 0.721102, 0.721432, 0.721666, 0.721798, 0.721824, 0.721732, 0.721824, 0.721798, 0.721666, 0.721432, 0.721102, 0.720681, 0.720171, 0.719577, 0.718900, 0.718144, 0.717311, 0.716404, 0.715424, 0.714375, 0.713258, 0.712076, 0.710829, 0.709522, 0.708155, 0.706730, 0.705251, 0.703718, 0.702133, 0.700499, 0.698816, 0.697088, 0.695315, 0.693499, 0.691641, 0.689742, 0.687805, 0.685829, 0.683818, 0.681769, 0.679687, 0.677571, 0.675423, 0.673242, 0.671031, 0.668791, 0.666525, 0.664237, 0.662342, 0.660514, 0.658743, 0.657022, 0.655347, 0.653715, 0.652122, 0.650567, 0.649048, 0.647565, 0.646117, 0.644703, 0.643326, 0.641984, 0.640678, 0.639409, 0.638178, 0.636987, 0.635837, 0.634730, 0.633668, 0.632655, 0.631695, 0.630791, 0.629948, 0.629175, 0.628479, 0.627873, 0.627375, 0.627012, 0.628162, 0.629312, 0.630462, 0.631611, 0.632761, 0.633911, 0.632761, 0.631611, 0.630462, 0.629312, 0.628162, 0.627012, 0.627375, 0.627873, 0.628479, 0.629175, 0.629948, 0.630791, 0.631695, 0.632655, 0.633668, 0.634730, 0.635837, 0.636987, 0.638178, 0.639409, 0.640678, 0.641984, 0.643326, 0.644703, 0.646117, 0.647565, 0.649048, 0.650567, 0.652122, 0.653715, 0.655347, 0.657022, 0.658743, 0.660514, 0.662342, 0.665075, 0.665788, 0.666477, 0.667149, 0.667807, 0.668452, 0.669084, 0.669701, 0.670303, 0.670890, 0.671461, 0.672014, 0.672548, 0.673062, 0.673552, 0.674017, 0.674454, 0.674860, 0.675234, 0.675572, 0.675871, 0.675572, 0.675234, 0.674860, 0.674454, 0.674017, 0.673552, 0.673062, 0.672548, 0.672014, 0.671461, 0.670890, 0.670303, 0.669701, 0.669084, 0.668452, 0.667807, 0.667149, 0.666477, 0.665788, 0.665075, 0.664381, 0.663748, 0.663164, 0.662625, 0.662130, 0.661679, 0.661275, 0.660920, 0.660618, 0.660372, 0.660186, 0.660063, 0.660004, 0.660012, 0.660086, 0.660229, 0.660443, 0.660728, 0.661089, 0.661532, 0.661089, 0.660728, 0.660443, 0.660229, 0.660086, 0.660012, 0.660004, 0.660063, 0.660186, 0.660372, 0.660618, 0.660920, 0.661275, 0.661679, 0.662130, 0.662625, 0.663164, 0.663748, 0.664381, 0.375535, 0.380755, 0.385970, 0.391178, 0.396378, 0.401568, 0.406749, 0.411919, 0.417077, 0.422223, 0.427357, 0.432478, 0.437586, 0.442679, 0.447758, 0.452822, 0.457871, 0.462903, 0.467918, 0.472916, 0.477896, 0.482858, 0.487799, 0.492722, 0.497623, 0.502504, 0.507362, 0.512198, 0.517010, 0.521792, 0.526540, 0.531243, 0.559981, 0.564298, 0.572818, 0.564298, 0.559981, 0.531243, 0.526540, 0.521792, 0.517010, 0.512198, 0.507362, 0.502504, 0.497623, 0.492722, 0.487799, 0.482858, 0.477896, 0.472916, 0.467918, 0.462903, 0.457871, 0.452822, 0.447758, 0.442679, 0.437586, 0.432478, 0.427357, 0.422223, 0.417077, 0.411919, 0.406749, 0.401568, 0.396378, 0.391178, 0.385970, 0.380755, 0.375535, 0.543598, 0.549005, 0.549005, 0.543598, 0.521853, 0.516702, 0.511551, 0.506400, 0.501249, 0.496098, 0.490947, 0.485796, 0.480645, 0.475494, 0.470343, 0.465192, 0.460041, 0.454890, 0.449739, 0.444588, 0.439437, 0.434286, 0.429135, 0.423984, 0.418833, 0.413682, 0.408531, 0.403380, 0.398229, 0.393078, 0.387927, 0.382776, 0.377625, 0.372474, 0.367323, 0.362172, 0.357021, 0.362533, 0.362584, 0.366719, 0.370758, 0.374482, 0.377860, 0.380939, 0.383295, 0.385031, 0.386113, 0.386473, 0.386109, 0.385023, 0.383283, 0.380925, 0.377842, 0.374461, 0.370736, 0.366696, 0.362560, 0.358348, 0.354309, 0.350585, 0.347206, 0.344127, 0.341772, 0.340035, 0.338954, 0.338593, 0.338958, 0.340043, 0.341783, 0.344142, 0.347224, 0.350605, 0.354331, 0.358371, 0.375192, 0.372191, 0.369350, 0.366674, 0.364163, 0.361818, 0.359640, 0.357632, 0.355795, 0.354130, 0.352640, 0.351325, 0.350186, 0.349223, 0.348437, 0.347827, 0.347393, 0.347135, 0.347052, 0.347144, 0.347412, 0.347854, 0.348473, 0.349267, 0.350238, 0.351387, 0.352715, 0.354223, 0.355912, 0.357785, 0.359846, 0.362104, 0.364585, 0.367095, 0.369405, 0.371520, 0.373447, 0.375190, 0.376755, 0.378148, 0.379374, 0.380440, 0.381352, 0.382117, 0.382743, 0.383236, 0.383605, 0.383856, 0.383996, 0.384031, 0.383968, 0.383811, 0.383568, 0.383241, 0.382836, 0.382357, 0.381806, 0.381188, 0.380505, 0.379760, 0.378955, 0.378093, 0.377176, 0.376206, 0.362533, 0.362560, 0.366696, 0.370736, 0.374461, 0.377842, 0.380925, 0.383283, 0.385023, 0.386109, 0.386473, 0.386113, 0.385031, 0.383295, 0.380939, 0.377860, 0.374482, 0.370758, 0.366719, 0.362584, 0.358371, 0.354331, 0.350605, 0.347224, 0.344142, 0.341783, 0.340043, 0.338958, 0.338593, 0.338954, 0.340035, 0.341772, 0.344127, 0.347206, 0.350585, 0.354309, 0.358348, 0.375192, 0.372191, 0.369350, 0.366674, 0.364163, 0.361818, 0.359640, 0.357632, 0.355795, 0.354130, 0.352640, 0.351325, 0.350186, 0.349223, 0.348437, 0.347827, 0.347393, 0.347135, 0.347052, 0.347144, 0.347412, 0.347854, 0.348473, 0.349267, 0.350238, 0.351387, 0.352715, 0.354223, 0.355912, 0.357785, 0.359846, 0.362104, 0.364585, 0.367095, 0.369405, 0.371520, 0.373447, 0.375190, 0.376755, 0.378148, 0.379374, 0.380440, 0.381352, 0.382117, 0.382743, 0.383236, 0.383605, 0.383856, 0.383996, 0.384031, 0.383968, 0.383811, 0.383568, 0.383241, 0.382836, 0.382357, 0.381806, 0.381188, 0.380505, 0.379760, 0.378955, 0.378093, 0.377176, 0.376206, 0.298620, 0.293794, 0.288991, 0.284301, 0.279916, 0.276030, 0.272714, 0.269943, 0.267662, 0.265804, 0.264290, 0.263036, 0.261967, 0.261022, 0.260156, 0.259339, 0.258551, 0.257778, 0.257011, 0.257406, 0.257815, 0.258259, 0.258769, 0.259392, 0.260193, 0.261257, 0.262688, 0.264582, 0.266996, 0.269911, 0.273238, 0.276859, 0.280671, 0.284596, 0.288585, 0.292606, 0.296640, 0.296323, 0.296006, 0.295688, 0.295372, 0.295058, 0.294752, 0.294461, 0.294192, 0.293955, 0.293756, 0.293596, 0.293472, 0.293376, 0.293299, 0.293234, 0.293177, 0.293123, 0.293071, 0.293667, 0.294260, 0.294850, 0.295430, 0.295996, 0.296538, 0.297043, 0.297496, 0.297883, 0.298195, 0.298431, 0.298597, 0.298704, 0.298760, 0.298773, 0.298749, 0.298694, 0.296640, 0.292606, 0.288585, 0.284596, 0.280671, 0.276859, 0.273238, 0.269911, 0.266996, 0.264582, 0.262688, 0.261257, 0.260193, 0.259392, 0.258769, 0.258259, 0.257815, 0.257406, 0.257011, 0.257778, 0.258551, 0.259339, 0.260156, 0.261022, 0.261967, 0.263036, 0.264290, 0.265804, 0.267662, 0.269943, 0.272714, 0.276030, 0.279916, 0.284301, 0.288991, 0.293794, 0.298620, 0.298694, 0.298749, 0.298773, 0.298760, 0.298704, 0.298597, 0.298431, 0.298195, 0.297883, 0.297496, 0.297043, 0.296538, 0.295996, 0.295430, 0.294850, 0.294260, 0.293667, 0.293071, 0.293123, 0.293177, 0.293234, 0.293299, 0.293376, 0.293472, 0.293596, 0.293756, 0.293955, 0.294192, 0.294461, 0.294752, 0.295058, 0.295372, 0.295688, 0.296006, 0.296323
])
landmarks_2D_1k = np.stack([mean_face_x_1k, mean_face_y_1k], axis=1)
mean_face_x_137_22_client = np.array([0.4988282, 0.5449964, 0.5849726, 0.6179804, 0.643469, 0.6622178, 0.6730388, 0.676355, 0.6733304,
0.6478118,
0.5882786,
0.4988282,
0.4093778,
0.349844,
0.324326,
0.32130139999999996,
0.3246176,
0.33543860000000003,
0.35418740000000004,
0.3796754,
0.4126838,
0.45266])
mean_face_y_137_22_client = np.array([0.7108352, 0.7000166, 0.6745382, 0.640106, 0.5996582, 0.5467124, 0.4916804, 0.4355282, 0.3795278, 0.2916416,
0.23122520000000002,
0.2137676,
0.23122520000000002,
0.2916416,
0.3795278,
0.4355282,
0.4916804,
0.5467124,
0.5996582,
0.640106,
0.6745382,
0.7000166])
landmarks_2D_137_22_clinet = np.stack([mean_face_x_137_22_client, mean_face_y_137_22_client], axis=1)
mat_face1024_256_full_face_client = np.array([[4.1666666e-01, 1.5257437e-17, -8.5333336e+01],
[-1.5257449e-17, 4.1666666e-01, -8.5333336e+01]])
mat_face1024_256_full_face_server = np.array([[4.1666666e-01, -1.5237085e-17, -8.5333336e+01],
[1.5237085e-17, 4.1666666e-01, -8.5333336e+01]])
# 68 point landmark definitions
landmarks_68_pt = {"mouth": (48, 68),
"right_eyebrow": (17, 22),
"left_eyebrow": (22, 27),
"right_eye": (36, 42),
"left_eye": (42, 48),
"nose": (27, 36), # missed one point
"jaw": (0, 17)}
def get_max_rect(bounding_boxes):
max_area = 0
index = 0
for i, box in enumerate(bounding_boxes):
width = box[2] - box[0]
height = box[3] - box[1]
if width * height > max_area:
index = i
max_area = width * height
return index
def get_transform_mat_mmcv(landmark, output_size):
dst_size = output_size
if len(landmark) == 68:
eye_dis = 0.34
mouth_dis = 0.34
g_Average_5point_180 = np.array([
eye_dis, 0.3,
1 - eye_dis, 0.3,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
# print(g_Average_5point_180)
left_eye = (landmark[36] + landmark[39]) / 2
right_eye = (landmark[42] + landmark[45]) / 2
nose = (landmark[31] + landmark[35]) / 2
left_mouth = (landmark[48] + landmark[60]) / 2
right_mouth = (landmark[64] + landmark[54]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
elif len(landmark) == 87:
eye_dis = 0.34
mouth_dis = 0.34
g_Average_5point_180 = np.array([
eye_dis, 0.3,
1 - eye_dis, 0.3,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
# print(g_Average_5point_180)
left_eye = (landmark[31] + landmark[35]) / 2
right_eye = (landmark[39] + landmark[43]) / 2
nose = landmark[62]
left_mouth = (landmark[66] + landmark[79]) / 2
right_mouth = (landmark[72] + landmark[83]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
elif len(landmark) == 1000:
pt137 = pts_1k_to_137(landmark)
eye_dis = 0.34
mouth_dis = 0.34
g_Average_5point_180 = np.array([
eye_dis, 0.3,
1 - eye_dis, 0.3,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
# print(g_Average_5point_180)
left_eye = (pt137[88] + pt137[96]) / 2
right_eye = (pt137[105] + pt137[113]) / 2
nose = pt137[83]
left_mouth = (pt137[22] + pt137[48]) / 2
right_mouth = (pt137[56] + pt137[36]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
def umeyama(src, dst, estimate_scale):
"""Estimate N-D similarity transformation with or without scaling.
Parameters
----------
src : (M, N) array
Source coordinates.
dst : (M, N) array
Destination coordinates.
estimate_scale : bool
Whether to estimate scaling factor.
Returns
-------
T : (N + 1, N + 1)
The homogeneous similarity transformation matrix. The matrix contains
NaN values only if the problem is not well-conditioned.
References
----------
.. [1] "Least-squares estimation of transformation parameters between two
point patterns", Shinji Umeyama, PAMI 1991, DOI: 10.1109/34.88573
"""
num = src.shape[0]
dim = src.shape[1]
# Compute mean of src and dst.
src_mean = src.mean(axis=0)
dst_mean = dst.mean(axis=0)
# Subtract mean from src and dst.
src_demean = src - src_mean
dst_demean = dst - dst_mean
# Eq. (38).
A = np.dot(dst_demean.T, src_demean) / num
# Eq. (39).
d = np.ones((dim,), dtype=np.double)
if np.linalg.det(A) < 0:
d[dim - 1] = -1
T = np.eye(dim + 1, dtype=np.double)
U, S, V = np.linalg.svd(A)
# Eq. (40) and (43).
rank = np.linalg.matrix_rank(A)
if rank == 0:
return np.nan * T
elif rank == dim - 1:
if np.linalg.det(U) * np.linalg.det(V) > 0:
T[:dim, :dim] = np.dot(U, V)
else:
s = d[dim - 1]
d[dim - 1] = -1
T[:dim, :dim] = np.dot(U, np.dot(np.diag(d), V))
d[dim - 1] = s
else:
T[:dim, :dim] = np.dot(U, np.dot(np.diag(d), V.T))
if estimate_scale:
# Eq. (41) and (42).
scale = 1.0 / src_demean.var(axis=0).sum() * np.dot(S, d)
else:
scale = 1.0
T[:dim, dim] = dst_mean - scale * np.dot(T[:dim, :dim], src_mean.T)
T[:dim, :dim] *= scale
return T
def get_transform_mat_mmcv_bigger(landmark, output_size, forlabel=False):
dst_size = output_size
if len(landmark) == 87:
eye_dis = 0.34
mouth_dis = 0.34
g_Average_5point_180 = np.array([
eye_dis, 0.3,
1 - eye_dis, 0.3,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
# print(g_Average_5point_180)
left_eye = (landmark[31] + landmark[35]) / 2
right_eye = (landmark[39] + landmark[43]) / 2
nose = landmark[62]
left_mouth = (landmark[66] + landmark[79]) / 2
right_mouth = (landmark[72] + landmark[83]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
elif len(landmark) == 137:
if forlabel:
eye_dis = 0.4
mouth_dis = 0.4
g_Average_5point_180 = np.array([
eye_dis, 0.4,
1 - eye_dis, 0.4,
0.5, 0.5,
mouth_dis, 0.6,
1 - mouth_dis, 0.6
])
else:
eye_dis = 0.34
mouth_dis = 0.34
g_Average_5point_180 = np.array([
eye_dis, 0.3,
1 - eye_dis, 0.3,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
# print(g_Average_5point_180)
left_eye = (landmark[96] + landmark[88]) / 2
right_eye = (landmark[105] + landmark[113]) / 2
nose = landmark[83]
left_mouth = (landmark[22] + landmark[48]) / 2
right_mouth = (landmark[56] + landmark[36]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
elif len(landmark) == 1000:
# left_eye = (landmarks_2D_1k[691] + landmarks_2D_1k[723]) / 2
# right_eye = (landmarks_2D_1k[792] + landmarks_2D_1k[824]) / 2
# nose = landmarks_2D_1k[621]
# left_mouth = (landmarks_2D_1k[467] + landmarks_2D_1k[468]) / 2
# right_mouth = (landmarks_2D_1k[396] + landmarks_2D_1k[508]) / 2
# pts5_dst = np.vstack((left_eye, right_eye,
# nose,
# left_mouth, right_mouth)) * dst_size
eye_dis = 0.34
mouth_dis = 0.34
g_Average_5point_180 = np.array([
eye_dis, 0.3,
1 - eye_dis, 0.3,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
# print(g_Average_5point_180)
left_eye = (landmark[691] + landmark[723]) / 2
right_eye = (landmark[792] + landmark[824]) / 2
nose = landmark[621]
left_mouth = (landmark[467] + landmark[468]) / 2
right_mouth = (landmark[396] + landmark[508]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
image_to_face_mat = umeyama(pts5_src, pts5_dst, True)[:2]
return image_to_face_mat
def get_transform_mat_full_face(landmark, output_size):
dst_size = output_size
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_137 = pts_1k_to_137(landmarks_2D_1k)
# print("landmarks_2D_137 x: ", landmarks_2D_137[:22, 0])
# print("landmarks_2D_137 y: ", landmarks_2D_137[:22, 1])
# exit()
mat = umeyama(landmark[:22], landmarks_2D_137[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k[:312] * dst_size, True)[0:2]
return mat
elif len(landmark) == 22:
landmarks_2D_137 = pts_1k_to_137(landmarks_2D_1k)
mat = umeyama(landmark, landmarks_2D_137[:22] * dst_size, True)[0:2]
return mat
def get_transform_mat_full_face_592(landmark, output_size, ratio):
dst_size = output_size
landmarks_2D_1k_tmp = landmarks_2D_1k.copy()
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + 0.5
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.5) * ratio + 0.5
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_137 = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark[:22], landmarks_2D_137[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k_tmp[:312] * dst_size, True)[0:2]
return mat
elif len(landmark) == 22:
landmarks_2D_137 = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark, landmarks_2D_137[:22] * dst_size, True)[0:2]
return mat
def get_transform_mat_full_face_592_v1(landmark, output_size, ratio=1.0, h_ratio=0.57):
dst_size = output_size
landmarks_2D_1k_tmp = landmarks_2D_1k.copy()
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + 0.5
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.5) * ratio + h_ratio
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_137 = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark[:22], landmarks_2D_137[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k_tmp[:312] * dst_size, True)[0:2]
return mat
def get_transform_mat_full_face_592_client(landmark, output_size, ratio):
dst_size = output_size
landmarks_2D_137_22_clinet_tmp = landmarks_2D_137_22_clinet.copy()
landmarks_2D_137_22_clinet_tmp[:, 0] = (landmarks_2D_137_22_clinet_tmp[:, 0] - 0.5) * ratio + 0.5
landmarks_2D_137_22_clinet_tmp[:, 1] = (landmarks_2D_137_22_clinet_tmp[:, 1] - 0.5) * ratio + 0.5
if len(landmark) == 22:
# landmarks_2D_137 = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark, landmarks_2D_137_22_clinet_tmp * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
landmark_137 = pts_1k_to_137(landmark)
mat = umeyama(landmark_137[:22], landmarks_2D_137_22_clinet_tmp * dst_size, True)[0:2]
return mat
def get_transform_mat_face592_full_face(img_size, detect_single_face_size, ratio):
# face_landmark_client = landmarks_2D_137_22_clinet * img_size
#
# #TODO:客户端如何得到face 0.6
# face_size2face_M_ratio = get_transform_mat_full_face_592_client(face_landmark_client, img_size, ratio)
#服务端得到face 1
face_landmark_server = landmarks_2D_1k * img_size
face_size2face_M_ratio = get_transform_mat_full_face_592(face_landmark_server, img_size, ratio)
face_size2face_M_full = get_transform_mat_full_face(face_landmark_server, detect_single_face_size)
M_ori = np.zeros((3, 3), dtype=np.float32)
M_ori[:2, :] = cv2.invertAffineTransform(face_size2face_M_ratio)
M_ori[2:, :] = [0, 0, 1]
matAffine_ori = np.zeros((3, 3), dtype=np.float32)
matAffine_ori[:2, :] = face_size2face_M_full
matAffine_ori[2:, :] = [0, 0, 1]
new_mat = matAffine_ori.dot(M_ori)
if False:
img = np.zeros((img_size, img_size, 3), dtype=np.uint8)
pred_label_int = face_landmark_server.copy().astype(np.int32)
img_client = img.copy()
for pt in pred_label_int:
cv2.circle(img_client, (pt[0], pt[1]), 1, (0, 0, 255), 1)
cv2.imshow("img_client: ", img_client)
#
# img_server = np.zeros((img_size, img_size, 3), dtype=np.uint8)
# face_sever_22 = pts_1k_to_137(face_landmark_server)[:22].astype(np.int32)
# for pt in face_sever_22:
# cv2.circle(img_server, (pt[0], pt[1]), 1, (0, 255, 0), 1)
# cv2.imshow("img_server: ", img_server)
# cv2.waitKey()
#
# img_server_new = np.zeros((img_size, img_size, 3), dtype=np.uint8)
# face_sever_new = transform_points(face_landmark_server, face_size2face_M_full)
# face_sever_new_22 = pts_1k_to_137(face_sever_new)[:22].astype(np.int32)
#
# for pt in face_sever_new_22:
# cv2.circle(img_server_new, (pt[0], pt[1]), 1, (0, 255, 0), 1)
# cv2.imshow("img_server_new: ", img_server_new)
# cv2.waitKey()
face_landmark_server_new = transform_points(face_landmark_server, face_size2face_M_ratio)
img_server = np.zeros((img_size, img_size, 3), dtype=np.uint8)
pred_label_server_int = face_landmark_server_new.copy().astype(np.int32)
# img_client = img.copy()
for pt in pred_label_server_int:
cv2.circle(img_server, (pt[0], pt[1]), 1, (0, 0, 255), 1)
cv2.imshow("img_server: ", img_server)
img_new = np.zeros((detect_single_face_size, detect_single_face_size, 3), dtype=np.uint8)
pred_new_label_int = transform_points(face_landmark_server_new, new_mat[:2, :]).astype(np.int32)
for pt in pred_new_label_int:
cv2.circle(img_new, (pt[0], pt[1]), 1, (0, 255, 0), 1)
cv2.imshow("img_show new: ", img_new)
cv2.waitKey()
return new_mat[:2, :]
def get_transform_mat_for_eye(landmark, output_size):
dst_size = output_size
if len(landmark) == 137:
eye_dis = 0.34
mouth_dis = 0.34
g_Average_5point_180 = np.array([
eye_dis, 0.3,
1 - eye_dis, 0.3,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
# print(g_Average_5point_180)
left_eye = (landmark[96] + landmark[88]) / 2
right_eye = (landmark[105] + landmark[113]) / 2
nose = landmark[83]
left_mouth = (landmark[22] + landmark[48]) / 2
right_mouth = (landmark[56] + landmark[36]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
def get_transform_mat_for_face_recognition(landmark, output_size):
g_Average_5point_180 = np.array([
57, 73,
123, 73,
90, 107,
62, 134,
118, 134
])
dst_size = output_size
if len(landmark) == 87:
left_eye = (landmark[17 + 19] + landmark[17 + 22]) / 2
right_eye = (landmark[17 + 25] + landmark[17 + 28]) / 2
nose = (landmark[17 + 14] + landmark[17 + 18]) / 2
left_mouth = (landmark[17 + 31] + landmark[17 + 43]) / 2
right_mouth = (landmark[17 + 47] + landmark[17 + 37]) / 2
elif len(landmark) == 137:
left_eye = (landmark[88] + landmark[96]) / 2
right_eye = (landmark[105] + landmark[113]) / 2
nose = landmark[83]
left_mouth = (landmark[22] + landmark[48]) / 2
right_mouth = (landmark[56] + landmark[36]) / 2
elif len(landmark) == 1000:
left_eye = (landmark[691] + landmark[723]) / 2
right_eye = (landmark[792] + landmark[824]) / 2
nose = landmark[621]
left_mouth = (landmark[467] + landmark[468]) / 2
right_mouth = (landmark[396] + landmark[508]) / 2
else:
assert False
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) / 180 * dst_size
mat = umeyama(pts5_src, pts5_dst, True)
return mat
def get_transform_mat_mmcv_hair(landmark, output_size, forlabel=False):
dst_size = output_size
if len(landmark) == 1000:
eye_dis = 0.42
mouth_dis = 0.42
g_Average_5point_180 = np.array([
eye_dis, 0.48,
1 - eye_dis, 0.48,
0.5, 0.53,
mouth_dis, 0.58,
1 - mouth_dis, 0.58
])
# print(g_Average_5point_180)
left_eye = (landmark[691] + landmark[723]) / 2
right_eye = (landmark[792] + landmark[824]) / 2
nose = landmark[621]
left_mouth = (landmark[467] + landmark[468]) / 2
right_mouth = (landmark[396] + landmark[508]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
else:
print("landmark < 1000 !!!")
assert False
return mat
def get_transform_mat_mmcv_seg(landmark, output_size, forlabel=False):
dst_size = output_size
eye_dis = 0.40
mouth_dis = 0.40
g_Average_5point_180 = np.array([
eye_dis, 0.46,
1 - eye_dis, 0.46,
0.5, 0.55,
mouth_dis, 0.64,
1 - mouth_dis, 0.64
])
if len(landmark) == 1000:
# print(g_Average_5point_180)
left_eye = (landmark[691] + landmark[723]) / 2
right_eye = (landmark[792] + landmark[824]) / 2
nose = landmark[621]
left_mouth = (landmark[467] + landmark[468]) / 2
right_mouth = (landmark[396] + landmark[508]) / 2
elif len(landmark) == 137:
left_eye = (landmark[88] + landmark[96]) / 2
right_eye = (landmark[105] + landmark[113]) / 2
nose = landmark[83]
left_mouth = (landmark[22] + landmark[48]) / 2
right_mouth = (landmark[56] + landmark[36]) / 2
else:
print("landmark < 1000 !!!")
assert False
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
def get_transform_mat_two_sets(landmarks_src, landmarks_dst):
assert len(landmarks_src) == len(landmarks_dst)
assert len(landmarks_src) == 137
mat = umeyama(landmarks_src[:22], landmarks_dst[:22], True)[0:2]
return mat
def flip_points(landmark, width):
if len(landmark) == 137:
landmarks_order = np.array([1, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, # counter
37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 48, 47, 46, 45, 44, 43, 42, 41,
40, 39, 38,
57, 56, 55, 54, 53, 52, 51, 50, 49, 64, 63, 62, 61, 60, 59, 58, # mouth
79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 83, 82, 81, 80, 84, 85, 86, 87,
# nose
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, # eye
88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
134, 133, 132, 131, 130, 137, 136, 135, # eyebrow
126, 125, 124, 123, 122, 129, 128, 127], dtype=np.int32) - 1
landmark_flip = landmark.copy()
landmark_flip[:, 0] = width - 1 - landmark_flip[:, 0]
landmark_flip = landmark_flip[landmarks_order, :]
return landmark_flip
elif len(landmark) == 1000:
dst = [0] + list(range(311, 156, -1)) + list(range(156, 0, -1)) + \
list(range(396, 354, -1)) + list(range(354, 311, -1)) + list(range(467, 432, -1)) + list(range(432, 396, -1)) + \
list(range(508, 488, -1)) + list(range(488, 467, -1)) + list(range(547, 528, -1)) + list(range(528, 508, -1)) + \
list(range(616, 584, -1)) + [584, 583, 582, 581, 580] + list(range(579, 547, -1)) + [620, 619, 618, 617] + list(range(621, 654, 1)) + \
[755] + list(range(774, 755, -1)) + list(range(791, 774, -1)) + list(range(792, 856, 1)) + \
[654] + list(range(673, 654, -1)) + list(range(690, 673, -1)) + list(range(691, 755, 1)) + \
list(range(964, 927, -1)) + list(range(999, 964, -1)) + \
list(range(892, 855, -1)) + list(range(927, 892, -1))
landmarks_order = np.array(dst, dtype=np.int32)
landmark_flip = landmark.copy()
landmark_flip[:, 0] = width - 1 - landmark_flip[:, 0]
landmark_flip = landmark_flip[landmarks_order, :]
return landmark_flip
else:
assert False
def pts_1k_to_137(landmarks):
index_1k_to_137 = [0, 12, 24, 36, 48, 61, 74, 87, 100, 119, 137, 156, 175, 193, 212, 225, 238, 251, 264, 276, 288,
300, 312, 318, 324, 330, 336, 342, 348, 354, 360, 366, 372, 378, 384, 390, 396, 402, 408, 414,
420, 426, 432, 438, 444, 450, 456, 462, 468, 473, 478, 483, 488, 493, 498, 503, 508, 513, 518,
523, 528, 533, 538, 543, 548, 556, 564, 571, 579, 580, 581, 582, 583, 584, 585, 593, 600, 608,
616, 617, 618, 619, 620, 621, 632, 642, 653, 654, 691, 695, 699, 703, 707, 711, 715, 719, 723,
727, 731, 735, 739, 743, 747, 751, 755, 792, 796, 800, 804, 808, 812, 816, 820, 824, 828, 832,
836, 840, 844, 848, 852, 856, 865, 874, 883, 892, 901, 910, 919, 928, 937, 946, 955, 964, 973,
982, 991]
landmarks_137 = landmarks[index_1k_to_137, :]
return landmarks_137
def get_transform_mat_full_face_to_target(landmark, dst_pt):
mat = umeyama(landmark[:312], dst_pt[:312], True)[0:2]
return mat
def decompose_affine_matrix(matrix):
# 确保输入矩阵是 2x3 的
assert matrix.shape == (2, 3), "输入矩阵必须是 2x3 的仿射变换矩阵"
# 提取平移分量
tx = matrix[0, 2]
ty = matrix[1, 2]
# 提取旋转、缩放分量
a = matrix[0, 0]
b = matrix[0, 1]
c = matrix[1, 0]
d = matrix[1, 1]
# 计算缩放因子
scale_x = np.sqrt(a ** 2 + c ** 2)
scale_y = np.sqrt(b ** 2 + d ** 2)
# 计算旋转角度
theta = np.arctan2(c, a)
return {
"translation": (tx, ty),
"scale": (scale_x, scale_y),
"rotation": np.degrees(theta) # 以度数表示
}
# 定义一个高质量缩放图像的函数,主要是用于处理比如头发这种非常细微的图片
def high_quality_warpAffine(origin_img, M, dst_size, const_value=(255, 255, 255)):
M_params = decompose_affine_matrix(M)
scale_ratio = M_params['scale'][0]
M_big = M / scale_ratio
crop_face_big = cv2.warpAffine(origin_img, M_big, (int(dst_size[0] / scale_ratio), int(dst_size[1] / scale_ratio)),
cv2.BORDER_CONSTANT, borderValue=const_value)
if scale_ratio < 1:
crop_face = cv2.resize(crop_face_big, (dst_size[0], dst_size[1]), interpolation=cv2.INTER_AREA)
else:
crop_face = cv2.resize(crop_face_big, (dst_size[0], dst_size[1]), interpolation=cv2.INTER_LANCZOS4)
return crop_face
def transform_points(points, mat, invert=False):
if invert:
mat = cv2.invertAffineTransform(mat)
points = np.expand_dims(points, axis=1)
points = cv2.transform(points, mat, points.shape)
points = np.squeeze(points)
return points
def get_transform_mat_bodyseg(landmark, output_size, ratio=1.0, offset = (0, 0)):
dst_size = output_size
assert len(landmark) == 1000
mat = umeyama(landmark[:312], landmarks_2D_1k[:312] * dst_size * ratio + dst_size * (1 - ratio) / 2 + offset, True)[0:2]
return mat
def align2stylegan(face_landmarks_1k, output_size=256):
face_landmarks_1k = np.float32(face_landmarks_1k)
x_scale = 1.0
y_scale = 1.0
em_scale = 0.1
eye_left = (face_landmarks_1k[691] + face_landmarks_1k[723]) / 2
eye_right = (face_landmarks_1k[792] + face_landmarks_1k[824]) / 2
mouth_left = (face_landmarks_1k[467] + face_landmarks_1k[468]) / 2
mouth_right = (face_landmarks_1k[396] + face_landmarks_1k[508]) / 2
eye_avg = (eye_left + eye_right) * 0.5
eye_to_eye = eye_right - eye_left
mouth_avg = (mouth_left + mouth_right) * 0.5
eye_to_mouth = mouth_avg - eye_avg
x = eye_to_eye - np.flipud(eye_to_mouth) * [-1, 1]
x /= np.hypot(*x)
x *= max(np.hypot(*eye_to_eye) * 2.0, np.hypot(*eye_to_mouth) * 1.8)
x *= x_scale
y = np.flipud(x) * [-y_scale, y_scale]
c = eye_avg + eye_to_mouth * em_scale
quad = np.stack([c - x - y, c - x + y, c + x + y, c + x - y])
quad_ori = np.array(quad)
rotate_radian = math.atan2((quad_ori[3][1] - quad_ori[0][1]), (quad_ori[3][0] - quad_ori[0][0]))
rotate_degree = rotate_radian / np.pi * 180
scale = output_size / cv2.norm(quad_ori[3] - quad_ori[0])
src_center = (quad_ori[0] + quad_ori[2]) * 0.5
dst_center = np.float32([output_size / 2, output_size / 2])
M = cv2.getRotationMatrix2D((src_center[0], src_center[1]), rotate_degree, scale)
M[:, 2] += dst_center - src_center
return M
def align2stylegan_ratio(face_landmarks_1k, ratio=1.0, output_size=256):
face_landmarks_1k = np.float32(face_landmarks_1k)
x_scale = 1.0 / ratio
y_scale = 1.0 / ratio
em_scale = 0.1
eye_left = (face_landmarks_1k[691] + face_landmarks_1k[723]) / 2
eye_right = (face_landmarks_1k[792] + face_landmarks_1k[824]) / 2
mouth_left = (face_landmarks_1k[467] + face_landmarks_1k[468]) / 2
mouth_right = (face_landmarks_1k[396] + face_landmarks_1k[508]) / 2
eye_avg = (eye_left + eye_right) * 0.5
eye_to_eye = eye_right - eye_left
mouth_avg = (mouth_left + mouth_right) * 0.5
eye_to_mouth = mouth_avg - eye_avg
x = eye_to_eye - np.flipud(eye_to_mouth) * [-1, 1]
x /= np.hypot(*x)
x *= max(np.hypot(*eye_to_eye) * 2.0, np.hypot(*eye_to_mouth) * 1.8)
x *= x_scale
y = np.flipud(x) * [-y_scale, y_scale]
c = eye_avg + eye_to_mouth * em_scale
quad = np.stack([c - x - y, c - x + y, c + x + y, c + x - y])
quad_ori = np.array(quad)
rotate_radian = math.atan2((quad_ori[3][1] - quad_ori[0][1]), (quad_ori[3][0] - quad_ori[0][0]))
rotate_degree = rotate_radian / np.pi * 180
scale = output_size / cv2.norm(quad_ori[3] - quad_ori[0])
src_center = (quad_ori[0] + quad_ori[2]) * 0.5
dst_center = np.float32([output_size / 2, output_size / 2])
M = cv2.getRotationMatrix2D((src_center[0], src_center[1]), rotate_degree, scale)
M[:, 2] += dst_center - src_center
return M
def calc_face_pitch(landmarks):
if not isinstance(landmarks, np.ndarray):
landmarks = np.array(landmarks)
t = ((landmarks[6][1] - landmarks[8][1]) + (landmarks[10][1] - landmarks[8][1])) / 2.0
b = landmarks[8][1]
return float(b - t)
def calc_face_yaw(landmarks):
if not isinstance(landmarks, np.ndarray):
landmarks = np.array(landmarks)
l = ((landmarks[27][0] - landmarks[0][0]) + (landmarks[28][0] - landmarks[1][0]) + (
landmarks[29][0] - landmarks[2][0])) / 3.0
r = ((landmarks[16][0] - landmarks[27][0]) + (landmarks[15][0] - landmarks[28][0]) + (
landmarks[14][0] - landmarks[29][0])) / 3.0
return float(r - l)
# deprecated
def draw_pncc_features(fc_landmark, img_target, w=256, h=256, is_train=True):
assert False
return img_target
def draw_blur_no_mouth_img(img_target, fc_landmark, is_train=False):
h, w, c = img_target.shape
assert h == w
if len(fc_landmark) == 1000:
fc_landmark = pts_1k_to_137(fc_landmark)
k_mid_size = int(w / 6.)
thresh = int(w / 15.)
if is_train:
k_size = random.choice(range(k_mid_size - thresh, k_mid_size + thresh, 2))
else:
k_size = k_mid_size
if k_size % 2 == 0:
k_size += 1
img_target_blur = cv2.blur(img_target, (k_size, k_size))
hull_mask = np.zeros(img_target.shape, dtype=np.uint8)
if len(fc_landmark) == 1000:
fc_landmark = pts_1k_to_137(fc_landmark)
cv2.fillPoly(hull_mask, fc_landmark[22:48][np.newaxis, :, :], (255, 255, 255))
# cv2.imshow('hull_mask1', hull_mask)
# cv2.imshow('img_target_blur', img_target_blur)
# cv2.imshow('img_target1', img_target)
kernel_size = int(w / 35.)
if kernel_size % 2 == 0:
kernel_size += 1
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size, kernel_size))
hull_mask = cv2.dilate(hull_mask, kernel, iterations=1) .astype(np.uint8)
# cv2.imshow('hull_mask2', hull_mask)
img_target = img_target_blur * (hull_mask<125) + img_target * (hull_mask>125)
# cv2.imshow('img_target2', img_target)
# cv2.waitKey()
return img_target
def draw_blur_img(img_target, fc_landmark, is_train=False):
h, w, c = img_target.shape
assert h == w
inpaint_mask = np.zeros((h, w), dtype=np.uint8)
if len(fc_landmark) == 1000:
fc_landmark = pts_1k_to_137(fc_landmark)
# cv2.imshow('img_target1', img_target)
k_mid_size = int(w / 6.)
thresh = int(w / 15.)
if is_train:
k_size = random.choice(range(k_mid_size - thresh, k_mid_size + thresh, 2))
else:
k_size = k_mid_size
if k_size % 2 == 0:
k_size += 1
img_target = cv2.blur(img_target, (k_size, k_size))
# cv2.imshow('img_target2', img_target)
# cv2.waitKey()
return img_target
def draw_blurmore_img(img_target, fc_landmark, is_train=False):
h, w, c = img_target.shape
assert h == w
inpaint_mask = np.zeros((h, w), dtype=np.uint8)
if len(fc_landmark) == 1000:
fc_landmark = pts_1k_to_137(fc_landmark)
# cv2.imshow('img_target1', img_target)
k_mid_size = int(w / 3.)
thresh = int(w / 15.)
if is_train:
k_size = random.choice(range(k_mid_size - thresh, k_mid_size + thresh, 2))
else:
k_size = k_mid_size
if k_size % 2 == 0:
k_size += 1
img_target = cv2.blur(img_target, (k_size, k_size))
# cv2.imshow('img_target2', img_target)
# cv2.waitKey()
return img_target
def draw_comapre_mask(fc_landmark, w=256, h=256):
inpaint_mask = np.zeros((h, w), dtype=np.uint8)
cv2.fillConvexPoly(inpaint_mask, cv2.convexHull(fc_landmark[129:137]), (255,))
cv2.fillConvexPoly(inpaint_mask, cv2.convexHull(fc_landmark[121:129]), (255,))
left_eye = np.around((fc_landmark[96] + fc_landmark[88]) / 2).astype(np.int32)
right_eye = np.around((fc_landmark[105] + fc_landmark[113]) / 2).astype(np.int32)
len = cv2.norm(fc_landmark[96].astype(np.int32) - fc_landmark[88].astype(np.int32))
cv2.circle(inpaint_mask, (left_eye[0], left_eye[1]), 1, (255), int(len * 1.1))
len = cv2.norm(fc_landmark[105].astype(np.int32) - fc_landmark[113].astype(np.int32))
cv2.circle(inpaint_mask, (right_eye[0], right_eye[1]), 1, (255), int(len * 1.1))
cv2.fillConvexPoly(inpaint_mask, cv2.convexHull(fc_landmark[64:87]), (255,))
cv2.fillConvexPoly(inpaint_mask, cv2.convexHull(fc_landmark[22:64]), (255,))
dilate_kernel_size = int(w / 23.)
if dilate_kernel_size % 2 == 0:
dilate_kernel_size += 1
kernel = np.ones((dilate_kernel_size, dilate_kernel_size), np.uint8)
inpaint_mask = cv2.dilate(inpaint_mask, kernel)
inpaint_mask = 1 - inpaint_mask.astype(np.float32) / 255
return inpaint_mask
def draw_hull_mask(fc_landmark, w=256, h=256, is_gray=False):
if not is_gray:
hull_mask = np.zeros((h, w, 3), dtype=np.uint8)
line_size1 = int(w / 85.)
line_size2 = int(w / 51.)
if len(fc_landmark) == 137:
# cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark[0:22]), (64, 16, 32))
# left_brown = ((fc_landmark[129] + fc_landmark[133]) / 2).astype(np.int32)
# cv2.circle(hull_mask, (left_brown[0], left_brown[1]), 1, (0, 255, 0), line_size1)
# right_brwon = ((fc_landmark[121] + fc_landmark[125]) / 2).astype(np.int32)
# cv2.circle(hull_mask, (right_brwon[0], right_brwon[1]), 1, (0, 0, 255), line_size1)
cv2.line(hull_mask, (int(fc_landmark[129, 0]), int(fc_landmark[129, 1])),
(int(fc_landmark[133, 0]), int(fc_landmark[133, 1])), (0, 255, 0), line_size1)
cv2.line(hull_mask, (int(fc_landmark[121, 0]), int(fc_landmark[121, 1])),
(int(fc_landmark[125, 0]), int(fc_landmark[125, 1])), (0, 0, 255), line_size1)
cv2.fillPoly(hull_mask, fc_landmark[88:104][np.newaxis, :, :], (128, 128, 0))
cv2.fillPoly(hull_mask, fc_landmark[105:121][np.newaxis, :, :], (128, 0, 128))
# cv2.line(hull_mask, (int(fc_landmark[86, 0]), int(fc_landmark[86, 1])),
# (int(fc_landmark[83, 0]), int(fc_landmark[83, 1])), (255, 0, 0), line_size2)
cv2.fillPoly(hull_mask, fc_landmark[48:64][np.newaxis, :, :], (0, 128, 128))
# cv2.fillPoly(hull_mask, np.concatenate((fc_landmark[22:37], fc_landmark[56:47:-1]))[np.newaxis, :, :],
# (0, 128, 0))
#
# cv2.fillPoly(hull_mask,
# np.concatenate((fc_landmark[47:35:-1], fc_landmark[56:64], [fc_landmark[48], fc_landmark[22]]))[
# np.newaxis, :, :], (0, 0, 128))
eye = np.zeros((h, w, 3), dtype=np.uint8)
eye_mask1 = np.zeros((h, w, 1), dtype=np.uint8)
eye_mask2 = np.zeros((h, w, 1), dtype=np.uint8)
cv2.fillPoly(eye_mask1, fc_landmark[88:104][np.newaxis, :, :], (1,))
cv2.fillPoly(eye_mask1, fc_landmark[105:121][np.newaxis, :, :], (1,))
left_eye = fc_landmark[87]
right_eye = fc_landmark[104]
# left_eye = np.around((fc_landmark[96] + fc_landmark[88]) / 2).astype(np.int32)
# right_eye = np.around((fc_landmark[105] + fc_landmark[113]) / 2).astype(np.int32)
cv2.circle(eye_mask2, (left_eye[0], left_eye[1]), 1, (1,), line_size2)
cv2.circle(eye_mask2, (right_eye[0], right_eye[1]), 1, (1,), line_size2)
eye_mask = eye_mask1 & eye_mask2
cv2.circle(eye, (left_eye[0], left_eye[1]), 1, (255, 255, 255), line_size2)
cv2.circle(eye, (right_eye[0], right_eye[1]), 1, (255, 255, 255), line_size2)
hull_mask = hull_mask * (1 - eye_mask[:, :, 0:1]) + eye * eye_mask[:, :, 0:1]
elif len(fc_landmark) == 1000:
# cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark[0:312]), (64, 16, 32))
# left_brown = ((fc_landmark[928] + fc_landmark[964]) / 2).astype(np.int32)
# cv2.circle(hull_mask, (left_brown[0], left_brown[1]), 1, (0, 255, 0), line_size1)
# right_brwon = ((fc_landmark[856] + fc_landmark[892]) / 2).astype(np.int32)
# cv2.circle(hull_mask, (right_brwon[0], right_brwon[1]), 1, (0, 0, 255), line_size1)
cv2.line(hull_mask, (int(fc_landmark[928, 0]), int(fc_landmark[928, 1])),
(int(fc_landmark[964, 0]), int(fc_landmark[964, 1])), (0, 255, 0), line_size1)
cv2.line(hull_mask, (int(fc_landmark[856, 0]), int(fc_landmark[856, 1])),
(int(fc_landmark[892, 0]), int(fc_landmark[892, 1])), (0, 0, 255), line_size1)
cv2.fillPoly(hull_mask, fc_landmark[691:755][np.newaxis, :, :], (128, 128, 0))
cv2.fillPoly(hull_mask, fc_landmark[792:856][np.newaxis, :, :], (128, 0, 128))
# cv2.line(hull_mask, (int(fc_landmark[653, 0]), int(fc_landmark[653, 1])),
# (int(fc_landmark[621, 0]), int(fc_landmark[621, 1])), (255, 0, 0), line_size2)
cv2.fillPoly(hull_mask, fc_landmark[468:548][np.newaxis, :, :], (0, 128, 128))
# cv2.fillPoly(hull_mask, np.concatenate((fc_landmark[312:397], fc_landmark[508:467:-1]))[np.newaxis, :, :],
# (0, 128, 0))
#
# cv2.fillPoly(hull_mask,
# np.concatenate((fc_landmark[467:395:-1], fc_landmark[508:548], [fc_landmark[468], fc_landmark[312]]))[
# np.newaxis, :, :], (0, 0, 128))
eye = np.zeros((h, w, 3), dtype=np.uint8)
eye_mask1 = np.zeros((h, w, 1), dtype=np.uint8)
eye_mask2 = np.zeros((h, w, 1), dtype=np.uint8)
cv2.fillPoly(eye_mask1, fc_landmark[691:755][np.newaxis, :, :], (1,))
cv2.fillPoly(eye_mask1, fc_landmark[792:856][np.newaxis, :, :], (1,))
left_eye = fc_landmark[654]
right_eye = fc_landmark[755]
# cv2.fillPoly(eye_mask2, fc_landmark[655:691][np.newaxis, :, :], (1,))
cv2.circle(eye_mask2, (left_eye[0], left_eye[1]), 1, (1,), line_size2)
# cv2.fillPoly(eye_mask2, fc_landmark[756:792][np.newaxis, :, :], (1,))
cv2.circle(eye_mask2, (right_eye[0], right_eye[1]), 1, (1,), line_size2)
eye_mask = eye_mask1 & eye_mask2
# cv2.fillPoly(eye, fc_landmark[655:691][np.newaxis, :, :], (255, 255, 255))
cv2.circle(eye, (left_eye[0], left_eye[1]), 1, (255, 255, 255), line_size2)
# cv2.fillPoly(eye, fc_landmark[756:792][np.newaxis, :, :], (255, 255, 255))
cv2.circle(eye, (right_eye[0], right_eye[1]), 1, (255, 255, 255), line_size2)
hull_mask = hull_mask * (1 - eye_mask[:, :, 0:1]) + eye * eye_mask[:, :, 0:1]
else:
assert False
else:
hull_mask = np.zeros((h, w), dtype=np.uint8)
if len(fc_landmark) == 137:
cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark), (1))
elif len(fc_landmark) == 1000:
cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark), (1))
else:
assert False
return hull_mask
def draw_makeup_mask(another_pts1k, another_mask, pts1k, hull_mask):
pts1kint = pts1k.astype(np.int32)
assert len(another_pts1k) == 1000 and len(pts1kint) == 1000
cv2.fillPoly(another_mask, another_pts1k[691:755][np.newaxis, :, :], (4)) # eye
cv2.fillPoly(another_mask, another_pts1k[792:856][np.newaxis, :, :], (5)) # eye
cv2.fillPoly(another_mask, np.concatenate((another_pts1k[312:397], another_pts1k[508:467:-1]))[np.newaxis, :, :], (7)) # mouth
cv2.fillPoly(another_mask, np.concatenate((another_pts1k[467:395:-1], another_pts1k[508:548], [another_pts1k[468], another_pts1k[312]]))[np.newaxis, :, :], (9)) # mouth
cv2.fillPoly(another_mask, another_pts1k[928:1000][np.newaxis, :, :], (0)) # eyebrow
cv2.fillPoly(another_mask, another_pts1k[856:928][np.newaxis, :, :], (0)) # eyebrow
cv2.fillPoly(hull_mask, pts1kint[691:755][np.newaxis, :, :], (4)) # eye
cv2.fillPoly(hull_mask, pts1kint[792:856][np.newaxis, :, :], (5)) # eye
cv2.fillPoly(hull_mask, np.concatenate((pts1kint[312:397], pts1kint[508:467:-1]))[np.newaxis, :, :], (7)) # mouth
cv2.fillPoly(hull_mask, np.concatenate((pts1kint[467:395:-1], pts1kint[508:548], [pts1kint[468], pts1kint[312]]))[np.newaxis, :, :], (9)) # mouth
cv2.fillPoly(hull_mask, pts1kint[928:1000][np.newaxis, :, :], (0)) # eyebrow
cv2.fillPoly(hull_mask, pts1kint[856:928][np.newaxis, :, :], (0)) # eyebrow
return another_mask, hull_mask
def draw_users_hull_mask(fc_landmark, w=256, h=256):
hull_mask = np.zeros((h, w), dtype=np.uint8)
if len(fc_landmark) == 87:
cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark), (1))
elif len(fc_landmark) == 137:
cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark), (1))
elif len(fc_landmark) == 1000:
cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark), (1))
else:
assert False
return hull_mask
def draw_bigger_hull_mask(fc_landmark, w=256, h=256):
if len(fc_landmark) == 1000:
fc_landmark = pts_1k_to_137(fc_landmark)
hull_mask = np.zeros((h, w), dtype=np.uint8)
if len(fc_landmark) == 137:
cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark), (255))
elif len(fc_landmark) == 1000:
cv2.fillConvexPoly(hull_mask, cv2.convexHull(fc_landmark), (255))
else:
assert False
kernel_size = int(w / 11.)
if kernel_size % 2 == 0:
kernel_size += 1
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size, kernel_size))
hull_mask = (cv2.dilate(hull_mask, kernel, iterations=1) / 255.).astype(np.uint8)
cv2.fillPoly(hull_mask, fc_landmark[22:48][np.newaxis, :, :], (10,))
leye_mask = np.zeros((h, w), dtype=np.uint8)
cv2.fillPoly(leye_mask, fc_landmark[88:104][np.newaxis, :, :], (1,))
cv2.fillPoly(leye_mask, fc_landmark[105:121][np.newaxis, :, :], (1,))
kernel_size = int(w / 5.)
if kernel_size % 2 == 0:
kernel_size += 1
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size, kernel_size))
leye_mask = (cv2.dilate(leye_mask, kernel, iterations=1)).astype(np.uint8)
hull_mask[leye_mask > 0] = 10
# cv2.imshow('hull_mask', hull_mask * 25 )
# cv2.waitKey()
return hull_mask
def get_kernel_size(div_num, output_img_size=256):
kernel_size = int(float(output_img_size) / div_num)
if kernel_size % 2 == 0:
kernel_size += 1
return kernel_size
class LKTracking(object):
def __init__(self, termcrit=cv2.TERM_CRITERIA_COUNT | cv2.TERM_CRITERIA_EPS, winSize=31, extSize=41, threshold=5):
self.termcrit = termcrit
self.winSize = winSize
self.extSize = extSize
self.threshold = threshold
self.prepoints = []
self.preimg_small_ = None
self.preimg_rect_ = np.array([0, 0, 0, 0])
def UpdatePoints(self, new_pts):
if len(new_pts) != len(self.prepoints):
self.prepoints = []
return False
self.prepoints = new_pts
return True
def TrackingPoints(self, curimg, curpoints):
need_init = False
def Prepare(self, curimg, curpoints):
prepoints_int = curpoints.astype(np.int32)
pass
def get_transform_mat_mouth(landmark, output_size):
# mean_mouth_x_4pts = np.array([0.15, 0.5, 0.75, 0.5])
# mean_mouth_y_4pts = np.array([0.5, 0.15, 0.5, 0.75])
mean_mouth_x_4pts = np.array([0.2, 0.5, 0.8, 0.5])
mean_mouth_y_4pts = np.array([0.5, 0.2, 0.5, 0.8])
landmarks_2D_mouth_4pts = np.stack([mean_mouth_x_4pts, mean_mouth_y_4pts], axis=1)
dst_size = output_size
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_137 = pts_1k_to_137(landmarks_2D_1k)
mat = umeyama(landmark[:22], landmarks_2D_137[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 236:
#mouth crop
landmark_mouth = []
landmark_mouth.append(landmark[467-312])
landmark_mouth.append(landmark[432-312])
landmark_mouth.append(landmark[397-312])
landmark_mouth.append(landmark[354-312])
landmark_mouth = np.array(landmark_mouth)
mat = umeyama(landmark_mouth, landmarks_2D_mouth_4pts * dst_size, True)[0:2]
return mat
mean_mouth_x_4pts = np.array([0.2, 0.5, 0.8, 0.5])
mean_mouth_y_4pts = np.array([0.5, 0.2, 0.5, 0.8])
landmarks_2D_mouth_4pts = np.stack([mean_mouth_x_4pts, mean_mouth_y_4pts], axis=1)
def get_transform_mat_for_mouth(landmark, output_size):
dst_size = output_size
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
# landmarks_2D_137 = pts_1k_to_137(landmarks_2D_1k)
# mat = umeyama(landmark[:22], landmarks_2D_137[:22] * dst_size, True)[0:2]
landmark_mouth = []
landmark_mouth.append(landmark[22])
landmark_mouth.append(landmark[42])
landmark_mouth.append(landmark[36])
landmark_mouth.append(landmark[29])
landmark_mouth = np.array(landmark_mouth)
mat = umeyama(landmark_mouth, landmarks_2D_mouth_4pts * dst_size, True)[0:2]
return mat
elif len(landmark) == 236:
# mouth crop
landmark_mouth = []
landmark_mouth.append(landmark[467 - 312])
landmark_mouth.append(landmark[432 - 312])
landmark_mouth.append(landmark[397 - 312])
landmark_mouth.append(landmark[354 - 312])
landmark_mouth = np.array(landmark_mouth)
mat = umeyama(landmark_mouth, landmarks_2D_mouth_4pts * dst_size, True)[0:2]
# mat = umeyama(landmark[:312], landmarks_2D_1k[:312] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
# mouth crop
landmark_mouth = []
landmark_mouth.append(landmark[467])
landmark_mouth.append(landmark[432])
landmark_mouth.append(landmark[397])
landmark_mouth.append(landmark[354])
landmark_mouth = np.array(landmark_mouth)
mat = umeyama(landmark_mouth, landmarks_2D_mouth_4pts * dst_size, True)[0:2]
# mat = umeyama(landmark[:312], landmarks_2D_1k[:312] * dst_size, True)[0:2]
return mat
def get_transform_mat_full_face_ratio_skin(landmark, output_size, ratio=1.0, skin=0):
dst_size = output_size
landmarks_2D_1k_tmp = landmarks_2D_1k.copy()
# landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + 0.5
# landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.5) * ratio + 0.4
if skin == 1:
###################### 0.3 face rata 592
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + 0.5
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.6) * ratio + 0.3
###################### 0.3 face rata 592
else:
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.4) * ratio + 0.45
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.4) * ratio + 0.4
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_1k_tmp = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark[:22], landmarks_2D_1k_tmp[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k_tmp[:312] * dst_size, True)[0:2]
return mat
def get_transform_mat_for_uv(landmark, output_size):
dst_size = output_size
if len(landmark) == 1000:
landmark = pts_1k_to_137(landmark)
if len(landmark) == 137:
eye_dis = 0.35
mouth_dis = 0.42
g_Average_5point_180 = np.array([
eye_dis, 0.24,
1 - eye_dis, 0.24,
0.5, 0.42,
mouth_dis, 0.55,
1 - mouth_dis, 0.55
])
# print(g_Average_5point_180)
left_eye = (landmark[96] + landmark[88]) / 2
right_eye = (landmark[105] + landmark[113]) / 2
nose = landmark[83]
left_mouth = (landmark[22] + landmark[48]) / 2
right_mouth = (landmark[56] + landmark[36]) / 2
pts5_dst = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_src = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
else:
assert False
def draw_crop_eye_bysize(img, pts1k, img_size, change_eyebrow):
pts137tmp = pts_1k_to_137(pts1k).astype(np.int32)
eye_mask = np.zeros((img_size, img_size, 3), dtype=np.uint8)
cv2.fillPoly(eye_mask, pts137tmp[88:104][np.newaxis, :, :], (1, 1, 1))
cv2.fillPoly(eye_mask, pts137tmp[105:121][np.newaxis, :, :], (1, 1, 1))
kernel_size = int(img_size / 198.) # 31
if kernel_size % 2 == 0:
kernel_size += 1
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size, kernel_size))
eye_mask = (cv2.dilate(eye_mask, kernel, iterations=1)).astype(np.uint8)
kernel_size = int(img_size / 7) # 8.2
if kernel_size % 2 == 0:
kernel_size += 1
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size*2, kernel_size))
eye_mask2 = (cv2.dilate(eye_mask, kernel, iterations=1)).astype(np.uint8)
eye_mask2 = eye_mask2 - eye_mask
if change_eyebrow:
# eyebrow
eyebrow_mask = np.zeros((img_size, img_size, 3), dtype=np.uint8)
x, y, w, h = cv2.boundingRect(pts137tmp[129:137])
# cv2.rectangle(eyebrow_mask, (x, y), (x + w, y + h), (1, 1, 1), -1)
eyebrow_mask[y:y + h, x:x + w, :] = [1, 1, 1]
x, y, w, h = cv2.boundingRect(pts137tmp[121:129])
# cv2.rectangle(eyebrow_mask, (x, y), (x + w, y + h), (1, 1, 1), -1)
eyebrow_mask[y:y + h, x:x + w, :] = [1, 1, 1]
kernel_size = int(592 / 21.) # 21
if kernel_size % 2 == 0:
kernel_size += 1
kernel_eyebrow = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (int(kernel_size * 5), int(kernel_size)))
eyebrow_mask = (cv2.dilate(eyebrow_mask, kernel_eyebrow, iterations=1)).astype(np.uint8)
eye_mask2 = (eye_mask2.astype(bool) | eyebrow_mask.astype(bool)).astype(np.float32)
else:
eyebrow_mask = np.zeros((img_size, img_size, 3), dtype=np.uint8)
cv2.fillPoly(eyebrow_mask, pts137tmp[129:137][np.newaxis, :, :], (1, 1, 1))
cv2.fillPoly(eyebrow_mask, pts137tmp[121:129][np.newaxis, :, :], (1, 1, 1))
eyebrow_mask = 1 - eyebrow_mask
eye_mask2 = (eye_mask2.astype(bool) & eyebrow_mask.astype(bool)).astype(np.float32)
# nose
cv2.fillPoly(eye_mask2, pts137tmp[64:79][np.newaxis, :, :], (0, 0, 0))
eye_mask2[(pts137tmp[133, 1] - img_size // 10):pts137tmp[65, 1], pts137tmp[64, 0]:pts137tmp[78, 0]] = 0
img[eye_mask2 > 0] = 0
cv2.circle(img, (pts137tmp[133, 0], pts137tmp[133, 1]), img_size // 50, (255, 0, 0), -1)
cv2.circle(img, (pts137tmp[121, 0], pts137tmp[121, 1]), img_size // 50, (255, 0, 0), -1)
return img
# def draw_crop_eye_bysize_using_seg_mask(img, pts1k, mask, img_size, change_eyebrow):
#
# pts137tmp = pts_1k_to_137(pts1k).astype(np.int32)
# c0, c1, c2 = mask[:, :, 0], mask[:, :, 1], mask[:, :, 2]
# c0[c0 >= 100] = 255
# c0[c0 < 100] = 0
# c1[c1 >= 100] = 255
# c1[c1 < 100] = 0
# c2[c2 > 0] = 0
# mask[:, :, 0] = c0
# mask[:, :, 1] = c1
# mask[:, :, 2] = c2
# eye_index = (mask == [255, 0, 0]).all(axis=2)
# eyelids_index = (mask == [0, 255, 0]).all(axis=2)
# black_im = np.zeros((img_size, img_size, 3), dtype=np.uint8)
# black_im2 = np.zeros((img_size, img_size, 3), dtype=np.uint8)
#
# black_im[eye_index] = [255, 255, 255]
# black_im2[eye_index] = [255, 255, 255]
# kernel_size = int(img_size // 7) # 8.2
#
# if kernel_size % 2 == 0:
# kernel_size += 1
# kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size * 2, kernel_size))
# black_im2 = cv2.dilate(black_im2, kernel).astype(np.uint8)
#
# endless_belt_im = black_im2 - black_im
# endless_belt_im = np.ones_like(endless_belt_im) * 255 - endless_belt_im
#
# if change_eyebrow:
# # eyebrow
# eyebrow_mask = np.zeros((img_size, img_size, 3), dtype=np.uint8)
# x, y, w, h = cv2.boundingRect(pts137tmp[129:137])
# # cv2.rectangle(eyebrow_mask, (x, y), (x + w, y + h), (1, 1, 1), -1)
# eyebrow_mask[y:y + h, x:x + w, :] = [1, 1, 1]
#
# x, y, w, h = cv2.boundingRect(pts137tmp[121:129])
# # cv2.rectangle(eyebrow_mask, (x, y), (x + w, y + h), (1, 1, 1), -1)
# eyebrow_mask[y:y + h, x:x + w, :] = [1, 1, 1]
#
# kernel_size = int(592 / 21.) # 21
# if kernel_size % 2 == 0:
# kernel_size += 1
# kernel_eyebrow = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (int(kernel_size * 5), int(kernel_size)))
# eyebrow_mask = (cv2.dilate(eyebrow_mask, kernel_eyebrow, iterations=1)).astype(np.uint8)
# eyebrow_mask = 1 - eyebrow_mask
# endless_belt_im = (endless_belt_im.astype(bool) & eyebrow_mask.astype(bool)).astype(np.float32) * 255
# else:
# eyebrow_mask = np.zeros((img_size, img_size, 3), dtype=np.uint8)
# cv2.fillPoly(eyebrow_mask, pts137tmp[129:137][np.newaxis, :, :], (1, 1, 1))
# cv2.fillPoly(eyebrow_mask, pts137tmp[121:129][np.newaxis, :, :], (1, 1, 1))
# endless_belt_im = (endless_belt_im.astype(bool) | eyebrow_mask.astype(bool)).astype(np.float32) * 255
#
# cv2.fillPoly(endless_belt_im, pts137tmp[64:79][np.newaxis, :, :], (255, 255, 255))
# endless_belt_im[(pts137tmp[133, 1] - img_size // 10):pts137tmp[65, 1], pts137tmp[64, 0]:pts137tmp[78, 0], :] = 255
#
#
# res = np.uint8(endless_belt_im / 255)
# res = np.uint8(res * img)
#
# # add eyelids semantic map
# eyelids_mask = np.zeros((img_size, img_size, 3))
# eyelids_mask[eyelids_index] = [0, 255, 0]
# res = res + np.uint8(eyelids_mask)
#
# cv2.circle(res, (pts137tmp[133, 0], pts137tmp[133, 1]), img_size // 50, (255, 0, 0), -1)
# cv2.circle(res, (pts137tmp[121, 0], pts137tmp[121, 1]), img_size // 50, (255, 0, 0), -1)
#
# return res
def draw_crop_eye_bysize_using_seg_mask(img, pts1k, mask, img_size, change_eyebrow):
start = time.time()
mask = mask.copy()
pts137tmp = pts_1k_to_137(pts1k).astype(np.int32)
c0, c1, c2 = mask[:, :, 0], mask[:, :, 1], mask[:, :, 2]
c0[c0 >= 100] = 255
c0[c0 < 100] = 0
c1[c1 >= 100] = 255
c1[c1 < 100] = 0
# c2 也需要截断
c2[c2 >= 100] = 255
c2[c2 < 100] = 0
mask[:, :, 0] = c0
mask[:, :, 1] = c1
mask[:, :, 2] = c2
eye_index = (mask == [255, 0, 0]).all(axis=2) | (mask == [0, 0, 255]).all(axis=2)
eyelids_index = (mask == [0, 255, 0]).all(axis=2)
black_im = np.zeros((img_size, img_size, 3), dtype=np.uint8)
black_im2 = np.zeros((img_size, img_size, 3), dtype=np.uint8)
black_im[eye_index] = [255, 255, 255]
black_im2[eye_index] = [255, 255, 255]
# cv2.imshow("black_im: ", black_im)
# cv2.waitKey()
kernel_size = int(img_size // 7) # 8.2
if kernel_size % 2 == 0:
kernel_size += 1
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size * 2, kernel_size))
black_im2 = cv2.dilate(black_im2, kernel).astype(np.uint8)
endless_belt_im = black_im2 - black_im
endless_belt_im = np.ones_like(endless_belt_im) * 255 - endless_belt_im
if change_eyebrow:
# eyebrow
eyebrow_mask = np.zeros((img_size, img_size, 3), dtype=np.uint8)
x, y, w, h = cv2.boundingRect(pts137tmp[129:137])
cv2.rectangle(eyebrow_mask, (x, y), (x + w, y + h), (1, 1, 1), -1)
x, y, w, h = cv2.boundingRect(pts137tmp[121:129])
cv2.rectangle(eyebrow_mask, (x, y), (x + w, y + h), (1, 1, 1), -1)
kernel_size = int(img_size / 21.) # 21
if kernel_size % 2 == 0:
kernel_size += 1
kernel_eyebrow = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (int(kernel_size * 5), int(kernel_size)))
eyebrow_mask = (cv2.dilate(eyebrow_mask, kernel_eyebrow, iterations=1)).astype(np.uint8)
eyebrow_mask = 1 - eyebrow_mask
endless_belt_im = (endless_belt_im.astype(bool) & eyebrow_mask.astype(bool)).astype(np.float32) * 255
else:
eyebrow_mask = np.zeros((img_size, img_size, 3), dtype=np.uint8)
cv2.fillPoly(eyebrow_mask, pts137tmp[129:137][np.newaxis, :, :], (1, 1, 1))
cv2.fillPoly(eyebrow_mask, pts137tmp[121:129][np.newaxis, :, :], (1, 1, 1))
endless_belt_im = (endless_belt_im.astype(bool) | eyebrow_mask.astype(bool)).astype(np.float32) * 255
# nose
cv2.fillPoly(endless_belt_im, pts137tmp[64:79][np.newaxis, :, :], (255, 255, 255))
endless_belt_im[(pts137tmp[133, 1] - img_size // 10):pts137tmp[65, 1], pts137tmp[64, 0]:pts137tmp[78, 0], :] = 255
res = np.uint8(endless_belt_im / 255)
res = np.uint8(res * img)
# add eyelids semantic map
eyelids_mask = np.zeros((img_size, img_size, 3))
eyelids_mask[eyelids_index] = [0, 255, 0]
res = res + np.uint8(eyelids_mask)
cv2.circle(res, (pts137tmp[133, 0], pts137tmp[133, 1]), img_size // 50, (255, 0, 0), -1)
cv2.circle(res, (pts137tmp[121, 0], pts137tmp[121, 1]), img_size // 50, (255, 0, 0), -1)
return res
def get_transform_singleeye(landmark, output_size, forlabel=False):
dst_size = output_size
left_dis = 0.28
g_Average_5point_180 = np.array([
left_dis, 0.5,
0.5, 0.499,
1 - left_dis, 0.5,
])
pts3_dst = g_Average_5point_180.reshape((3, -1)) * dst_size
pts3_src = np.vstack((landmark[0], landmark[1], landmark[2]))
image_to_face_mat = umeyama(pts3_src, pts3_dst, True)[:2]
return image_to_face_mat
def get_transform_mat_full_face_ratio_stylegan(landmark, output_size, ratio=1.0):
dst_size = output_size
landmarks_2D_1k_tmp = landmarks_2D_1k.copy()
####################
# # ###################### train stylegan hair rate_0.4 size_512
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + 0.5
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.6) * ratio + 0.4
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_1k_tmp = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark[:22], landmarks_2D_1k_tmp[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k_tmp[:312] * dst_size, True)[0:2]
return mat
def get_transform_mat_hair(landmark, output_size, ratio=0.5, w_ratio=0.5, h_ratio=0.40):
dst_size = output_size
landmarks_2D_1k_tmp = landmarks_2D_1k.copy()
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + w_ratio
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.5) * ratio + h_ratio
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_1k_tmp = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark[:22], landmarks_2D_1k_tmp[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k_tmp[:312] * dst_size, True)[0:2]
return mat
def get_transform_mat_sex(landmark, output_size, forlabel=False):
dst_size = output_size
if len(landmark) == 87:
eye_dis = 0.34
mouth_dis = 0.34
g_Average_5point_180 = np.array([
eye_dis, 0.3,
1 - eye_dis, 0.3,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
# print(g_Average_5point_180)
left_eye = (landmark[31] + landmark[35]) / 2
right_eye = (landmark[39] + landmark[43]) / 2
nose = landmark[62]
left_mouth = (landmark[66] + landmark[79]) / 2
right_mouth = (landmark[72] + landmark[83]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
elif len(landmark) == 137:
eye_dis = 0.317
mouth_dis = 0.345
g_Average_5point_180 = np.array([
eye_dis, 0.4,
1 - eye_dis, 0.4,
0.5, 0.6,
mouth_dis, 0.63,
1 - mouth_dis, 0.63
])
# print(g_Average_5point_180)
left_eye = (landmark[96] + landmark[88]) / 2
right_eye = (landmark[105] + landmark[113]) / 2
nose = landmark[83]
left_mouth = (landmark[22] + landmark[48]) / 2
right_mouth = (landmark[56] + landmark[36]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
mat = umeyama(pts5_src, pts5_dst, True)[0:2]
return mat
def get_transform_mat_hair_ratio(landmark, output_size, ratio=1.0):
dst_size = output_size
landmarks_2D_1k_tmp = landmarks_2D_1k.copy()
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + 0.5
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.5) * ratio + 0.45
# landmarks1k_contours = landmarks_2D_1k_tmp[:312]
# x_l, y_l = np.min(landmarks1k_contours, axis=0)
# x_h, y_h = np.max(landmarks1k_contours, axis=0)
#
# print("x_l: ", x_l, "x_h: ", x_h)
# print("y_l: ", y_l, "y_h: ", y_h)
#
# def draw_landmark(landmark_ori, img):
# landmark_full_int = (landmark_ori.copy() * 512).astype(np.int32)
# img_show = img.copy()
# for pt in landmark_full_int:
# cv2.circle(img_show, (pt[0], pt[1]), 2, (0, 0, 255), 1)
#
# return img_show.astype(np.uint8)
#
# img_temp = np.zeros((512, 512, 3), dtype=np.uint8)
# img_show = draw_landmark(landmarks_2D_1k_tmp, img_temp)
# cv2.imshow("img_show", img_show)
# cv2.waitKey()
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_1k_tmp = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark[:22], landmarks_2D_1k_tmp[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k_tmp[:312] * dst_size, True)[0:2]
return mat
def get_transform_mat_hair_ratio_v1(landmark, output_size, ratio=1.0, h_offset=0.5):
dst_size = output_size
landmarks_2D_1k_tmp = landmarks_2D_1k.copy()
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + 0.5
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.5) * ratio + h_offset
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_1k_tmp = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark[:22], landmarks_2D_1k_tmp[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k_tmp[:312] * dst_size, True)[0:2]
return mat
def get_transform_mat_full_face_ratio_deeplab(landmark, output_size, ratio=0.3, w_ratio=0.5, h_ratio=0.45):
dst_size = output_size
landmarks_2D_1k_tmp = landmarks_2D_1k.copy()
landmarks_2D_1k_tmp[:, 0] = (landmarks_2D_1k_tmp[:, 0] - 0.5) * ratio + w_ratio
landmarks_2D_1k_tmp[:, 1] = (landmarks_2D_1k_tmp[:, 1] - 0.5) * ratio + h_ratio
if len(landmark) == 87:
assert False
elif len(landmark) == 137:
landmarks_2D_1k_tmp = pts_1k_to_137(landmarks_2D_1k_tmp)
mat = umeyama(landmark[:22], landmarks_2D_1k_tmp[:22] * dst_size, True)[0:2]
return mat
elif len(landmark) == 1000:
mat = umeyama(landmark[:312], landmarks_2D_1k_tmp[:312] * dst_size, True)[0:2]
return mat
def get_transform_mat_face_restore(landmark, output_size):
dst_size = output_size
if len(landmark) == 1000:
eye_dis = 0.4
mouth_dis = 0.42
g_Average_5point_180 = np.array([
eye_dis, 0.47,
1 - eye_dis, 0.47,
0.5, 0.6,
mouth_dis, 0.71,
1 - mouth_dis, 0.71
])
pts5_dst = g_Average_5point_180.reshape((5, -1)) * dst_size
left_eye = (landmark[691] + landmark[723]) / 2
right_eye = (landmark[792] + landmark[824]) / 2
nose = landmark[621]
left_mouth = (landmark[467] + landmark[468]) / 2
right_mouth = (landmark[396] + landmark[508]) / 2
pts5_src = np.vstack((left_eye, right_eye,
nose,
left_mouth, right_mouth))
image_to_face_mat = umeyama(pts5_src, pts5_dst, True)[:2]
return image_to_face_mat