FaceGen 3 SDKs Reference
Loading...
Searching...
No Matches
FgApply.cpp
1//
2// Copyright (c) Singular Inversions Inc. 2014
3//
4// Authors: Andrew Beatty
5// Created: Jan 2, 2014
6//
7
8#include "stdafx.h"
9
10#include "FgApply.hpp"
11
12using namespace std;
13
14namespace Fg {
15
16Arr<ScaleTrans3F,2> cEyesTransform(FaceLmPos3Fs const & lmBases,Vec3Fs const & allTargs)
17{
18 FGASSERT(lmBases.size() == allTargs.size()); // must be 1-1
19 auto cXf = [&](FaceLm upperCentre,FaceLm lowerCentre,FaceLm endocanthion,FaceLm exocanthion)
20 {
21 Arr<size_t,4> inds {
22 findFirstIdx(lmBases,upperCentre,true),
23 findFirstIdx(lmBases,lowerCentre,true),
24 findFirstIdx(lmBases,endocanthion,true),
25 findFirstIdx(lmBases,exocanthion,true),
26 };
27 Arr<Vec3F,4> bases = mapCall(inds,[&](size_t idx){return lmBases[idx].pos; });
28 Arr<Vec3F,4> targs = mapIndex(inds,allTargs);
29 // this algo differs from G8.1 and earlier algo (baked into EGM) since eyes are deeper in G9:
30 Vec3F centreB = cMean(bases),
31 centreT = cMean(targs),
32 delta = centreT - centreB,
33 canthCentreB = (bases[2] + bases[3]) * 0.5,
34 canthCentreT = (targs[2] + targs[3]) * 0.5,
35 canthDelta = canthCentreT - canthCentreB;
36 // X values of lids are not well defined so don't use:
37 delta[0] = canthDelta[0];
38 float sizeB = scast<float>(cLenD(bases[2]-bases[3])),
39 sizeT = scast<float>(cLenD(targs[2]-targs[3])),
40 scale = sizeT / sizeB;
41 return ScaleTrans3F{canthCentreB+delta} * ScaleTrans3F{scale} * ScaleTrans3F{-canthCentreB};
42 };
43 return {
44 cXf(FaceLm::lidUpperCentreL,FaceLm::lidLowerCentreL,FaceLm::endocanthionL,FaceLm::exocanthionL),
45 cXf(FaceLm::lidUpperCentreR,FaceLm::lidLowerCentreR,FaceLm::endocanthionR,FaceLm::exocanthionR),
46 };
47}
48
49Arr3D sampleColor(ImgRgba8 const & img,ImgUC const & region)
50{
51 FGASSERT(areColinear(img.dims(),region.dims()));
52 float scaleToColor = scast<float>(img.dims()[0]) / scast<float>(region.dims()[0]);
53 size_t taps {0};
54 Arr3UL acc {0};
55 for (Iter2UI it{region.dims()}; it.valid(); it.next()) {
56 if (region[it()] == 255) { // iris sample region
57 Vec2F pacs = (Vec2F{it()} + Vec2F{0.5,0.5}) * scaleToColor;
58 Rgba8 clr = img[Vec2UI{pacs}];
59 for (uint cc=0; cc<3; ++cc)
60 acc[cc] += clr[cc];
61 ++taps;
62 }
63 }
64 FGASSERT(taps > 0);
65 return mapCast<double>(acc) / scast<double>(taps); // still [0,255]
66};
67
68void shiftColor_(Arr3D delta,ImgUC const & region,ImgRgba8 & img)
69{
70 float scaleToRegion = scast<float>(region.width()) / scast<float>(img.width());
71 for (Iter2UI it{img.dims()}; it.valid(); it.next()) {
72 Vec2F pacs = (Vec2F{it()} + Vec2F{0.5}) * scaleToRegion;
73 double delFac = scast<double>(region[Vec2UI{pacs}]) / 255.0;
74 Rgba8 & pix = img[it()];
75 for (uint cc=0; cc<3; ++cc) {
76 double val = delta[cc] * delFac + pix[cc];
77 pix[cc] = scast<uchar>(clamp(val,0.0,255.0));
78 }
79 }
80}
81
82}