📄 convertm2.cpp
字号:
// $util\convertM2.cpp 1.5 milbo$ convertM2: convert XM2VTS coords to m2 coords// This reads a shape file and produces another shape file, with coords converted to our internal format.// You typically manually cut and paste parts of the output file into your shape file.// Warning: this is raw research code -- expect it to be quite messy.//-----------------------------------------------------------------------------// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// A copy of the GNU General Public License is available at// http://www.r-project.org/Licenses///-----------------------------------------------------------------------------#include "all.hpp"#define INFILE "/a/m/shape/m4.shape"#define OUTFILE "x.shape"//-----------------------------------------------------------------------------int main (void){ShapeVec Shapes; // array[nShapes] of SHAPEStringVec TagStrings; // array[nShapes] of string: string tag preceding each shape in shape filechar *sTagRegExp = " m[^r]"; // everything except mirrored files, neural net shapes will be discarded by DiscardGlobalFaceDetectorShapes()char sImageDirs[SLEN]; // image directories at head of shape file, separated by semicolonsconst unsigned Mask1 = 0; // FA_NnFailed;const unsigned Mask2 = 0; // FA_NnFailed;ReadShapeFile(&Shapes, TagStrings, sImageDirs, sTagRegExp, Mask1, Mask2, INFILE, QUIET);DiscardGlobalFaceDetectorShapes(&Shapes, TagStrings, AT_DISCARD_UNDERSCORES);int iShape;int nWantedPoints = Shapes[0].nrows();int nShapes = Shapes.size();int nChanged = 0;#if 0// Convert all shapes to have the same number of landmarks as the first shape// Unspecified landmarks are set to 0,0for (iShape = 0; iShape < nShapes && !fgErr; iShape++) if (fConvertShapeToInternalFormat(Shapes[iShape], nWantedPoints)) nChanged++;lprintf("got %d shape%s, first shape has %d landmarks\n", nShapes, ((nShapes==1)? "":"s"), nWantedPoints);if (nChanged) lprintf("Converted %d shape%s to %d points per shape, %d shape%s unchanged\n", nChanged, ((nChanged!=1)? "s":""), nWantedPoints, nShapes-nChanged, ((nShapes-nChanged!=1)? "s":""));#endifif (nWantedPoints != CONF_nPointsXm2vts) Warn("nWantedPoints %d != CONF_nPointsXm2vts %d", nWantedPoints, CONF_nPointsXm2vts);nChanged = 0;for (iShape = 0; iShape < nShapes; iShape++) { const char *sTag = TagStrings[iShape].c_str(); unsigned Attr; if (1 != sscanf(sTag, "%x", &Attr)) SysErr("Can't convert first part of tag %s to a hex number", sTag); int width, height; int iOffset = FNAME_OFFSET; if (sTag[FNAME_OFFSET] == '_') iOffset++; if (sTag[iOffset] == 'm') // XM2VTS file? { width = 720; height = 576; int height2 = 560;#if 0 // move synthesized landmarks if (sTag[iOffset+1] != 'r') // not reversed ie not mirrored file? { for (int iRow = 68; iRow < 76; iRow++) { Shapes[iShape].row(iRow+8) = Shapes[iShape].row(iRow); // move 68 to 76 Shapes[iShape].row(iRow).fill(0); // clear 68 } }#endif if (Attr & FA_Remarked) {#if 0 // move upper neck points in line with chin Shapes[iShape](MLNeckTop, VY) = Shapes[iShape](MTipOfChin, VY); Shapes[iShape](MRNeckTop, VY) = Shapes[iShape](MTipOfChin, VY); nChanged++;#endif#if 0 // add approximate upper neck points Shapes[iShape](MLNeckTop, VX) = Shapes[iShape](4, VX)-10; Shapes[iShape](MLNeckTop, VY) = Shapes[iShape](4, VY); Shapes[iShape](MRNeckTop, VX) = Shapes[iShape](10, VX)+10; Shapes[iShape](MRNeckTop, VY) = Shapes[iShape](10, VY); nChanged++;#endif#if 0 // add approximate lower neck points Shapes[iShape](MLNeckBottom, VX) = Shapes[iShape](4, VX)-10; Shapes[iShape](MLNeckBottom, VY) = __min(height2, Shapes[iShape](4, VY) - 60); Shapes[iShape](MRNeckBottom, VX) = Shapes[iShape](10, VX)+10; Shapes[iShape](MRNeckBottom, VY) = __min(height2, Shapes[iShape](10, VY) - 60);#endif } } else if (sTag[iOffset] == 'B') // BioId file? { width = 384; height = 286; } else if (sTag[iOffset] == 'a') // AR file? { width = 768; height = 576;#if 0 // add FA_Expression bit based on session number int iSessionOffset = iOffset + 5; if (sTag[iOffset+1] == 'r') iSessionOffset++; if (sTag[iSessionOffset-1] != '_') SysErr("sTag[%d-1] == '%c' Tag %s", iSessionOffset, sTag[iSessionOffset-1], sTag); char cSession = sTag[iSessionOffset]; if (cSession == '2' || cSession == '3' || cSession == '4') { unsigned Tag; if (1 != sscanf(sTag, "%x", &Tag)) SysErr("Can't scan tag %s", sTag); char s[SLEN]; sprintf(s, "%4.4x %s", (Tag | FA_Expression), &sTag[FNAME_OFFSET]); TagStrings[iShape] = s; lprintf("Assigning %s\n", TagStrings[iShape].c_str()); } else if (cSession != '1' && cSession != '5') SysErr("Bad tag %s", sTag); nChanged++;#endif } else { lprintf("\nUnrecognized tag %s, treating shape as an XM2VTS shape", TagStrings[iShape].c_str()); width = 720; height = 576; }#if 0 // translate tags from an older format to current format unsigned Tag; if (1 != sscanf(sTag, "%x", &Tag)) SysErr("Can't read tag"); unsigned NewTag = Tag & 0xfebf; // remove FA_Remarked bit and FA_Rowley bad bit if (Tag & 0x40) // remarked { NewTag |= 0x800; } if (Tag & 0x100) // nnbad { lprintf("NnFailed %s %4.4x ", sTag, NewTag); NewTag |= 0x80; lprintf("->%4.4x\n", NewTag); } char s[SLEN]; sprintf(s, "%4.4x %s", NewTag, sTag + FNAME_OFFSET); TagStrings[iShape] = s; nChanged++;#endif#if 0 // translate landmarks for (int iRow = 0; iRow < Shapes[iShape].nrows(); iRow++) { Shapes[iShape](iRow, VX) -= width / 2; Shapes[iShape](iRow, VY) = height / 2 - Shapes[iShape](iRow, VY); // make sure coords aren't 0,0 because that means "unused landmark" if (Shapes[iShape](iRow, VX) == 0 && Shapes[iShape](iRow, VY) == 0) Shapes[iShape](iRow, VX) = 0.1; } nChanged++;#endif#if 0 // reverse neural net landmarks if (sTag[0] == '2') { SHAPE Temp(Shapes[iShape]); Shapes[iShape](0, VX) = -Temp(1, VX); Shapes[iShape](1, VX) = -Temp(0, VX); Shapes[iShape](2, VX) = -Temp(3, VX); Shapes[iShape](3, VX) = -Temp(2, VX); } nChanged++;#endif#if 1 // reverse non-neural net landmarks if (sTag[0] != '2') { SHAPE Temp(Shapes[iShape]); int nrows = Temp.nrows(); for (int iRow = 0; iRow < nrows; iRow++) { int iPartner = gLandTabAll[iRow].iPartner; if (iPartner < 0) { if (fPointUsed(Temp, iRow)) { Shapes[iShape](iRow, VX) = -Temp(iRow, VX) - 1; Shapes[iShape](iRow, VY) = Temp(iRow, VY); } } else if (fPointUsed(Temp, iPartner)) { Shapes[iShape](iRow, VX) = -Temp(iPartner, VX) - 1; Shapes[iShape](iRow, VY) = Temp(iPartner, VY); } else { Shapes[iShape](iRow, VX) = 0; Shapes[iShape](iRow, VY) = 0; } } nChanged++; }#if 0 // show reversed image and shape const char *sBasename = TagStrings[iShape].c_str()+FNAME_OFFSET; char sFile[SLEN]; sprintf(sFile, sBasename, ".pgm"); Image Img; sLoadImageGivenDirs(Img, sImageDirs, sFile, QUIET, TRUE); FlipImage(Img); RgbImage RgbImg(Img); // convert to color DrawShape(RgbImg, Shapes[iShape], C_DRED, 1.0, IM_NO_CONNECT_DOTS, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_TRANSPARENT); char sPath[SLEN]; sprintf(sPath, "_%s", sBasename); WriteBmp(RgbImg, sPath, VERBOSE);#endif#endif }lprintf("%d shapes changed\n", nChanged);#if 1lprintf("\nCreating \"%s\" ", OUTFILE);WriteMatVec(Shapes, OUTFILE, NULL, NULL, NULL, &TagStrings, QUIET, "%.2f");#elselprintf("\nCreating \"%s\" ", OUTFILE);WriteShapeFile(OUTFILE, Shapes, TagStrings, nShapes, nWantedPoints, "Created by convertM2", sImageDirs);#endifreturn 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -