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