⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 marki.cpp

📁 这是个人脸识别程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// $util\marki.cpp 1.5 milbo$ manually landmark images////-----------------------------------------------------------------------------// Example:// The following command line////         marki -o new.shape -l 7 -p " m" -P 2 2 ../shape/68.shape//// will load all XM2VTS files with glasses in ../shape/68.shape into marki.// If you click on an image you will set the position of landmark 7 (which// is the tip of the chin). The results will be saved to new.shape, and also// file called "marked".//// You have to put the image files into the directories listed in the header// of marki.shape before using marki, and the images all have to be ".pgm"s.//// -l 7    specifies landmark 7 i.e. clicking on the image will update point 7//// -p " m" specifies files with tag strings matching the regular exprssion " m"//         i.e. all XM2VTS files (look at 68.shape and 84.shape to see the tag strings)//         -p " m[^r]" will show all except "reversed" i.e mirrored XM2VTS files//// -P 2 2  specifies tags with bit 0x2 set i.e. faces with glasses.//         "-P 2 0" will show all faces _without_ glasses//         (look at 84.shape and atface.hpp to learn about tags)//// You can "accept" or "reject" a file by clicking on the appropriate buttons.// This will create files "marki.sed" and "tagged" which you can use// for post processing.  This is useful for making corrections to the tags// e.g. an image is marked as glasses when it is in fact not wearing glasses.//// Be a bit careful because marki doesn't warn you before overwriting an// output file (i.e. any of NEW.shape, marked, marki.tag, tagged)//// Marki moves automatically to the next image unless you change that// behaviour by clicking on the AutoNext button.// Right clicking moves to the next image without changing the landmark position.// Have a look at the WmCommand function below to see what commands are available// using the mouse.//// See the WmKeydown function below to see what you can do from the keyboard.//// Note that marki writes to the registry (to store page layout etc. information).////-----------------------------------------------------------------------------// TODO! The last time I tried this, it seems to only work on for XM2VTS// files -- the program crashes when you try to save the results for files// that are not XM2VTS files (but "marked' and "tagged" will be saved ok// before the crash).////-----------------------------------------------------------------------------// My windows knowledges comes from Petzold's books, so that's where// you want to look to understand this program, if necessary.// This files uses a form of Hungariain notatin -- the prefix "g" on// and indentifier means "global" for example.//// TODO: Bug: when moving focus back to main window (from dialog window)// it sets the current image to MARKED//// Warning: this is raw research code -- expect it to be quite messy.// Tab size is 4// milbo nov 05 durban//-----------------------------------------------------------------------------// 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"#include <commctrl.h>#include "marki.hpp"#define USE_SHAPE_FILE 1	// 1:read shape file and get images from it							// 0: read images from directory "adj" (TODO still working?)static const char 	*sgVersion 			= "1.5";       const char 	*sgProgramName 		= "marki";static const char 	*sgMarkiLog	 		= "marki.log";static const char 	*sgClass       		= "marki";static const char	*sgRegistryKey		= "Software\\milbo\\marki";static const char	*sgRegistryName		= "Config";static const char	*sgTagged			= "tagged";static const char	*sgMarkedFile		= "marked";static const char	*sgUmSed			= "marki.sed";static const char	*sgDlg 				= "Dlg";static int			igLandmark = MLEyeInner;		// -l command line flagstatic char			sgNewShapeFile[SLEN];			// -o command line flagstatic char			sgTagRegExp[SLEN];				// -p command line flagstatic unsigned 	gAttrMask1, gAttrMask2;			// -P command line flagstatic unsigned		gRejectBit;						// -R command line flagstatic bool			fgOnlySelectedFiles;			// -O command line flagstatic int xgDlg;								// posn of dialog windowstatic int ygDlg;static HWND			hgMainWnd;					// main windowstatic HWND			hgToolbar;					// toolbarstatic HWND			hgDlgWnd;					// dialog windowstatic HBITMAP 		hgToolbarBmp;				// toolbar bitmapstatic HINSTANCE	hgAppInstance;				// application instancestatic HANDLE 		hgProgramMutex;				// this program's mutual exclusion handlestatic int			ngMaiwidth, ngMaiheight;	// main window dimensionsstatic clock_t		gStartTime;					// time program startedstatic RgbImage		gImg;						// current image#if USE_SHAPE_FILEstatic char			sgShapeFile[SLEN];static ShapeVec		gShapesOrg;			// array[nShapes] of SHAPE, each SHAPE is nPoints x 2, original training shapesstatic ShapeVec		gShapes;			// above, but modified by user mouse clicksstatic int 			ngPoints;			// number of landmark points in each training set shapestatic Mat	 	 	gLand;				// Lands structure#elsestatic const char	*sgDefaultImageDir = "adj";	// directory holding images#endifstatic StringVec	gTagStrings;		// array[nShapes] of string preceding each shape in ASM file, i.e. image filenamesstatic int 			ngImages;			// total number of imagesstatic int			igImage;			// index of current image in gTagStringsstatic char			sgImageDirs[SLEN];	// director(ies) holding imagesint igTopCrop, igBottomCrop;			// what we cropped off the image before displaying itint igLeftCrop, igRightCrop;static bool 		fgAutoNext;			// toolbar button: auto next after markstatic bool			fgEqualize;static bool			fgConnectDots;#define CONF_nMaxCrop	1				// allow only two crop statesstatic int			igCrop;				// toolbar button: crop 0..CONF_nMaxCropstatic bool 		fgMarkedFilesUpToDate = true;static bool			fgTaggedFilesUpToDate = true;typedef enum eImageStatus { ST_NONE=0, ST_REJECT, ST_ACCEPT } eImageStatus;static char *sgImageStatus[] = { "", "REJECT", "ACCEPT" };	// must match eImageStatusstatic eImageStatus	gImageStatus[CONF_nMaxFiles];	// array of accept/reject status, same index as gTagStrings// "chugging", which is a fast slide show, is useful if you are checking that// all images marked as say wearing glasses are indeed wearing glasses.static bool fgChug;						// chug mode: automatically cycle through imagesstatic const int IdTimer_Chug	= 1;static const int igChugDelay	= 250;	// ms delay between images in chug modestatic TBBUTTON gToolbarButtons[] =	{	6,	IDM_Save, 			BUTTON_Standard,	7,	IDM_Equalize,		BUTTON_Standard,	8,	IDM_ConnectDots,	BUTTON_Standard,	2,	IDM_AutoNext,		BUTTON_Standard,	5,	IDM_Crop,			BUTTON_Standard,	0,	IDM_Prev, 			BUTTON_Standard,	1,	IDM_Next,			BUTTON_Standard,	4,	IDM_Reject, 		BUTTON_Standard,	3,	IDM_Accept, 		BUTTON_Standard,	9,	IDM_EraseLandmark,	BUTTON_Standard,	-1,					// -1 terminates list	};static char *sgTooltips[] =	{	"Auto next on reject/accept",			// IDM_AutoNext	"Equalize images before displaying",	// IDM_Equalize	"Connect the dots",						// IDM_ConnectDots	"Crop display",							// IDM_Crop	"Display previous image",				// IDM_Prev	"Display next image",					// IDM_Next	"Reject image",							// IDM_Reject	"Accept image",							// IDM_Accept	"Erase landmark",						// IDM_EraseLandmark	};#if USE_SHAPE_FILEstatic char sgUsage[] ="Usage: marki  [-l LANDMARK] [-o OUTFILE] [-c CENTER_LANDMARK] [-p PATTERN] [-O] INFILE.shape\n""\n""-l LANDMARK\n""\t\tLandmark to be altered by left mouse click\n""\t\tDefault: 29 (inner left eye)\n""\n""-o OUTFILE.shape\n""\t\tOutput filename.\n""\t\tDefault: _INFILE.shape\n""\n""-p PATTERN\n""\t\tPATTERN is an egrep style pattern (not a file wildcard).\n""\t\tLoad only shapes in INFILE.shape with tags matching case-independent PATTERN.\n""\t\tExample: -p \"xyz\" loads filenames containing xyz\n""\t\tExample: -p \" m000| m001\" loads filenames beginning with m000 or m001.\n""\t\tDefault: all (except global detector shapes)\n""\n""-P Mask1 Mask2\n""\t\tLoad only shapes which satisfy (Attr & Mask1) == Mask2.\n""\t\tAttr is the hex number at start of the tag, Mask1 and Mask2 are hex.\n""\t\tThis filter is applied after -p PATTERN.\n""\t\tExample: -P 2 2 matches faces with glasses (FA_Glasses=2, see atface.hpp).\n""\t\tExample: -P 2 0 matches faces without glasses.\n""\t\tDefault: no filter (Mask1=Mask2=0).\n""\n""-O\n""\t\tWrite only the shapes selected by PATTERN when writing the new shape file OUTFILE.shape.\n""\t\tDefault: write all the shapes in INFILE.shape to OUTFILE.shape, updating those that have been marked.\n""\n""-R HexBit\n""\t\tSet the given bit in the tags in OUTFILE.shape for images marked \"REJECT\"\n""\t\tClear the given bit images marked \"ACCEPT\"\n""\t\tDefault: HexBit=0 i.e. don't change bits in OUTFILE.shape\n""\n""INFILE.shape\n""\t\tInput shape file.  Default: marki.shape\n";#endif//-----------------------------------------------------------------------------static void StripQuotesAndBackQuote (char *sStripped, const char *sQuoted){// remove quotes at each end of string, if anystrcpy(sStripped, &sQuoted[sQuoted[0] == '"'? 1:0]);				// discard initial "int iLen = strlen(sStripped)-1;if (iLen > 0 && sStripped[iLen] == '"')	sStripped[iLen] = 0;					// discard final "// replace backquote with spacefor (int i = 0; sStripped[i]; i++)	if (sStripped[i] == '`')		sStripped[i] = ' ';}//-----------------------------------------------------------------------------// See sgUsage#if USE_SHAPE_FILEstatic char *sParseCmdLine (LPSTR pCmdLine)	// return error msg if failure, NULL on success{char *sWhiteSpace = " \t";char sStripped[SLEN];// A hack to deal with strtok: convert spaces inside quotes to backquote// This allows us to place spaces inside strings in quotes (for regular expression and filenames)int Len = strlen(pCmdLine);for (int i = 0; i < Len; i++)	if (pCmdLine[i] == '"')		{		i++;		while (pCmdLine[i] && pCmdLine[i] != '"')			{			if (pCmdLine[i] == ' ')				pCmdLine[i] = '`';			i++;			}		}char *sToken = strtok(pCmdLine, sWhiteSpace);while (sToken != NULL)	{	if (sToken[0] == '-')		{		if (sToken[1] == 0)			return sgUsage;		switch (sToken[1])			{			case 'l':				sToken = strtok(NULL, sWhiteSpace);				if (sToken == NULL)					return sgUsage;				igLandmark = -1;				sscanf(sToken, "%d", &igLandmark);				if (igLandmark < 0 || igLandmark > 200)					return sgUsage;				break;			case 'o':				sToken = strtok(NULL, sWhiteSpace);				if (sToken == NULL)					return sgUsage;				StripQuotesAndBackQuote(sStripped, sToken);				if (!sStripped || sStripped[0] == 0 || sStripped[0] == '-')					return sgUsage;				strcpy(sgNewShapeFile, sStripped);				break;			case 'p':				sToken = strtok(NULL, sWhiteSpace);				if (sToken == NULL)					return sgUsage;				StripQuotesAndBackQuote(sStripped, sToken);				if (!sStripped || sStripped[0] == 0 || sStripped[0] == '-')					return sgUsage;				strcpy(sgTagRegExp, sStripped);				break;			case 'P':				sToken = strtok(NULL, sWhiteSpace);				if (sToken == NULL || 1 != sscanf(sToken, "%x", &gAttrMask1))					return "-P needs two hex number arguments.  Use -? for help.";				sToken = strtok(NULL, sWhiteSpace);				if (sToken == NULL || 1 != sscanf(sToken, "%x", &gAttrMask2))					return "-P needs two hex number arguments.  Use -? for help.";				break;			case 'R':				sToken = strtok(NULL, sWhiteSpace);				if (sToken == NULL || 1 != sscanf(sToken, "%x", &gRejectBit))					return "Expected a hex number after -R.  Use -? for help.";				break;			case 'O':				fgOnlySelectedFiles = true;				break;			default:	// bad flag				return sgUsage;			}		}	else	// assume a string without '-' is the INFILE		{		StripQuotesAndBackQuote(sgShapeFile, sToken);		strcpy(sgShapeFile, sToken);		}	sToken = strtok(NULL, sWhiteSpace);	if (sgShapeFile[0] && sToken)		return "Flags not allowed after shape file";	}if (!sgShapeFile[0])	// no shape file specified	return "\nYou must specify a shape file.  Use marki -? for help.\n";if (sgNewShapeFile[0] == 0)	{	char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT], sNewFname[_MAX_FNAME];	_splitpath(sgShapeFile, sDrive, sDir, sFname, sExt);	sprintf(sNewFname, "_%s", sFname);	_makepath(sgNewShapeFile, sDrive, sDir, sNewFname, ".shape");	}lprintf("ShapeFile %s ", sgShapeFile);lprintf("OutShapeFileFile %s\n", sgNewShapeFile);lprintf("Landmark %s\n", (igLandmark<sizeof(sgPointNames)/sizeof(sgPointNames[0])? sgPointNames[igLandmark]: "?"));lprintf("RegExp \"%s\"\n", sgTagRegExp);lprintf("Mask1 %x [%s] ", gAttrMask1, sGetAtFaceString(gAttrMask1));lprintf("Mask2 %x [%s]\n", gAttrMask2, sGetAtFaceString(gAttrMask2));lprintf("HexBit %x [%s]\n", gRejectBit, sGetAtFaceString(gRejectBit));return NULL;	// success}#endif//-----------------------------------------------------------------------------static void GetStateFromRegistry (int *pxPos, int *pyPos, int *pxSize, int *pySize,				int *piCrop, bool *pfAutoNext,				bool *pfEqualize, bool *pfConnectDots, int *pxDlg, int *pyDlg){HKEY  hKey;DWORD nBuf = SLEN;BYTE  Buf[SLEN];int xPos, yPos, xSize, ySize, iCrop=-1, fAutoNext=-1,	fEqualize=-1, fConnectDots=-1, xDlg=-1, yDlg=-1;// get values from registry and validate themif (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, sgRegistryKey, 0, KEY_READ, &hKey) ||	ERROR_SUCCESS != RegQueryValueEx(hKey, sgRegistryName, NULL, NULL, Buf, &nBuf))	{	// Can't get what we want from registry. Set big vals, and clip them below.	lprintf("Can't read registry HKEY_CURRENT_USER Key \"%s\" Name \"%s\", using defaults\n",		sgRegistryKey, sgRegistryName);	xPos = yPos = 0;	xSize = ySize = 100000;	}else if (10 != sscanf((char *)Buf, "%d %d %d %d %d %d %d %d %d %d",			&xPos, &yPos, &xSize, &ySize, &iCrop, &fAutoNext, &fEqualize, &fConnectDots, &xDlg, &yDlg) ||		xPos + xSize < 0 || 		yPos + ySize < 0 || 		xSize < 20 || 		ySize < 20 ||	// pos can be neg if window edges slightly off screen		(fAutoNext != 1 && fAutoNext != 0) || 		(fEqualize != 1 && fEqualize != 0) || (fConnectDots != 1 && fConnectDots != 0) ||		(igCrop < 0 || igCrop > 2) ||		(xDlg < 0 || yDlg < 0))	{	// Can't get what we want from registry. Set big vals, and clip them below.	lprintf("Can't get values from registry HKEY_CURRENT_USER Key \"%s\" Name \"%s\" "		"%dx%d %dx%d Crop %d Auto %d Eq %d Con %d, using defaults\n",		sgRegistryKey, sgRegistryName, xPos, yPos, xSize, ySize, iCrop, fAutoNext, fEqualize, fConnectDots);	xPos = yPos = 0;	xSize = ySize = 100000;	xDlg = yDlg = -1;	}else	{	*piCrop = iCrop;	*(int *)pfAutoNext = fAutoNext;	*(int *)pfEqualize = fEqualize;	*(int *)pfConnectDots = fConnectDots;	}RegCloseKey(hKey);if (igCrop > CONF_nMaxCrop)	igCrop = 0;// Validate registry entries against actual work area// If invalid, return biggest possible main window size.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -