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

📄 imutil.cpp

📁 这是个人脸识别程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
void ReduceImageAssign (Image &OutImg, 														// out						const Image &InImg, double Scale, int ReduceMethod, bool fVerbose)	// in{if (fVerbose)	lprintf("Reduce %g ", Scale);if (fEqual(Scale, 1, 1e-3))	// an optimization for speed	OutImg = InImg;else	{	int iScale, ix, iy;	int nNewWidth = int(InImg.width / Scale), nNewHeight = int(InImg.height / Scale);	if (nNewWidth < 10 || nNewHeight < 10)	// 10 is rather arbitrary		SysErr("ReduceImageAssign: image too small, nNewWidth %d nNewHeight %d", nNewWidth, nNewHeight);	switch (ReduceMethod)		{		case IM_NEAREST_PIXEL:			OutImg.dim(nNewWidth, nNewHeight);			for (iy = 0; iy < nNewHeight; iy++)				{				int iy1 = (iy * InImg.height) / nNewHeight;				for (ix = 0; ix < nNewWidth; ix++)					OutImg(ix, iy) = InImg((ix * InImg.width) / nNewWidth, iy1);				}			break;		case IM_BILINEAR:			OutImg = InImg;				//TODO make this more efficient?			ScaleImage(OutImg, nNewWidth, nNewHeight, fVerbose, IM_BILINEAR);			break;		case IM_AVERAGE_ALL:			ASSERT(fEqual(floor(Scale), Scale, 1e-3));	// scale is an integer?			iScale = (int)Scale;		// for efficiency do calculations using ints not doubles			OutImg.dim(nNewWidth, nNewHeight);			for (iy = 0; iy < nNewHeight; iy++)				for (ix = 0; ix < nNewWidth; ix++)					{					int Pixel = 0;					for (int j = 0; j < iScale; j++)						for (int i = 0; i < iScale; i++)							Pixel += InImg((ix * iScale) + i, iy * iScale + j);					OutImg(ix, iy) = byte(Pixel / (iScale * iScale));					}			break;		default:			SysErr("CONF_ReduceMethod");			break;		}	}}//-----------------------------------------------------------------------------// Return pixel value at (possibly inter-pixel) coordinate ix,iy in buf//// Lifted and modified from img.cc:interpolateExtendstatic inline int BilinearInterpolate (const Image &Img, double x, double y, bool fExtend)	// in{if (x < 0.0)	{	if (fExtend)		x = 0.0;	else		return 0;	}else if (x > Img.width - 1.0)	{	if (fExtend || x <= Img.width)		x = Img.width - 1.0;	else		return 0;	}if (y < 0.0)	{	if (fExtend)		y = 0.0;	else		return 0;	}else if (y > Img.height - 1.0)	{	if (fExtend || y <= Img.height)		y = Img.height - 1.0;	else		return 0;	}int iLeft   = (int)floor(x);int iRight  = (int)ceil(x);int iTop    = (int)floor(y);int iBottom = (int)ceil(y);double BotLeft  = Img(iLeft  + iBottom * Img.width);double BotRight = Img(iRight + iBottom * Img.width);double UpLeft   = Img(iLeft  + iTop * Img.width);double UpRight  = Img(iRight + iTop * Img.width);double xFrac = x - iLeft;double yFrac = y - iTop;double Val = yFrac        * ((1.0 - xFrac) * BotLeft + xFrac * BotRight) + 			(1.0 - yFrac) * ((1.0 - xFrac) * UpLeft  + xFrac * UpRight);return (int)floor(Val + 0.5);}//-----------------------------------------------------------------------------// macro for speed#define NEAREST_PIXEL(iPixel, Img, x, y, fExtend)				\{																\bool fZero = false;												\if (x < 0.0)													\	{															\	if (fExtend)												\		x = 0.0;												\	else														\		fZero = true;											\	}															\else if (x > Img.width - 1.0)									\	{															\	if (fExtend || x <= Img.width)								\		x = Img.width - 1.0;									\	else														\		fZero = true;											\	}															\if (y < 0.0)													\	{															\	if (fExtend)												\		y = 0.0;												\	else														\		fZero = true;											\	}															\else if (y >= Img.height - 1.0)								\	{															\	if (fExtend || y <= Img.height)							\		y = Img.height - 1.0;									\	else														\		fZero = true;											\	}															\iPixel = fZero? 0: (byte)Img((int)(x + 0.5), ((int)(y + 0.5))); \}																		//-----------------------------------------------------------------------------// xMid,yMid are the center of the new image but specified w.r.t. the old image pIn// Scale is how how we want to rescale the image.// Angle is the angle we want to rotate the image by anticlockwise (in radians)// nNewWidth nNewHeight are width and height of the new image//// I tested this by checking the images it produces against images transformed// by Photoshop. Everything seems to line up except that there may be a quarter pixel// difference (a shift between our image and Photoshop's) for certain transformation// involving a scale down, shift, and offset.  Possibly subjective. It's hard to// tell because their scale-down bilinear transform seems smoother than ours (looks// more like a bicubic).//// If Angle is 0, image quality is slightly better when xMid and yMid are// integral - but they don't have to be.//// If fBilinear is false we use the nearest pixel (usually a sharper image)//// When getting a pixel from the old image and that pixel is off the image:// 	fExtend=false: use black (this is the default)// 	fExtend=truee: use the closest edge pixel, thus effectively extending //				   the edge of of the input image//// TODO known bug: sometimes miscalculates the edge pixels.  To see(?): rotate image by PI, look at edges.//// Lifted and modified from a Rowley routinevoid ExtractImage (Image &Img, 												// io					int nNewWidth, int nNewHeight,   						// in				  	double nxMid, double nyMid, double Scale, double Angle, // in				  	bool fVerbose, bool fBilinear, bool fExtend)				// in{// The 0.5s compensate for BilinearInterpolate taking floor and ceilingdouble Width2  = (double)nNewWidth  / 2.0 - 0.5;double height2 = (double)nNewHeight / 2.0 - 0.5;double cosA = cos(Angle);double sinA = sin(Angle);Image OutImg(nNewWidth, nNewHeight);if (fVerbose)	lprintf("extract %dx%d at %.3g,%.3g scale %.3g rotate %.3g ", 		nNewWidth, nNewHeight, nxMid, nyMid, Scale, Angle * 180.0/PI);for (int j = 0; j < nNewHeight; j++)	{	double dj = (double)j;	int jWidth = j * nNewWidth;	for (int i = 0; i < nNewWidth; i++) 		{		double di = (double)i;		double xr = nxMid + ((di - Width2) * cosA - (dj - height2) * sinA - 0.5) / Scale;		double yr = nyMid + ((di - Width2) * sinA + (dj - height2) * cosA - 0.5) / Scale;		if (fBilinear)			OutImg(i + jWidth) = (byte)BilinearInterpolate(Img, xr, yr, fExtend);		else			NEAREST_PIXEL(OutImg(i + jWidth), Img, xr, yr, fExtend);		}	}Img = OutImg;}//-----------------------------------------------------------------------------void DrawVerticalLine (Image &Img, 					// io					  int ix, bool fVerbose)		// in{if (fVerbose)	lprintf("drawVert %d ", ix);for (int iy = 0; iy < Img.height; iy++)	Img(ix, iy) = 255;}//-----------------------------------------------------------------------------void DrawHorizontalLine (Image &Img, 				// io						int iy, bool fVerbose)		// in{if (fVerbose)	lprintf("drawHoriz %d ", iy);for (int ix = 0; ix < Img.width; ix++)	Img(ix, iy) = 255;}//-----------------------------------------------------------------------------// TODO not yet in test.cppvoid FillImage (Image &Img, byte Color){for (int i = 0; i < Img.width * Img.height; i++)			Img.buf[i] = Color;}//-----------------------------------------------------------------------------// TODO not yet in test.cppvoid FillRectangle (Image &Img, int ix1, int iy1, int ix2, int iy2, int Color){for (int iy = iy1; iy < iy2; iy++)	if (iy >= 0 && iy < Img.height)		for (int ix = ix1; ix < ix2; ix++)			if (ix >= 0 && ix < Img.width)				Img(ix, iy) = (byte)Color;}//-----------------------------------------------------------------------------// Scale the given byte pImg down by a factor of 1.2, putting the result// in the given destination (which can be the same as the source).  The// scaling uses bilinear interpolation, implemented by two steps of linear// interpolation: first scaling in the X direction, then in the Y direction.//// TODO not yet in test.cppvoid ReduceSizeBy1_2 (Image &Dest, Image &Src){#if 1// This version is based on HAR's original code. // I've kept it for backwards compatibility in regression tests. int width = Src.width;int height = Src.height;int nNewWidth = (int)floor(width / 1.2);int nNewHeight = (int)floor(height / 1.2);double scaleX = 1.2, scaleY = 1.2;// first scale in XImage Tmp(nNewWidth, height);int x, y;byte *pIn = Src.buf;for (y = 0; y < height; y++) 	{	for (x = 0; x < nNewWidth; x++) 		{		int pos = (int)(x * scaleX);		double frac = (x * scaleX) - pos;		double val = (1.0 - frac) * pIn[pos] + frac * pIn[pos + 1];		if (val < 0) val = 0; 		if (val > 255) val = 255;		Tmp(y + x * height) = byte(val + 0.5);		}	pIn += width;	}// scale in YImage Tmp2(nNewWidth, height);pIn = Tmp.buf;for (y = 0; y < nNewWidth; y++) 	{	for (x = 0; x < nNewHeight; x++) 		{		int pos = (int)(x * scaleY);		double frac = (x * scaleY) - pos;		double val = (1.0 - frac) * pIn[pos] + frac * pIn[pos + 1];		if (val < 0) val = 0; 		if (val > 255) val = 255;		Tmp2(y + x * nNewWidth) = byte(val + 0.5);		}	pIn += height;	}Dest = Tmp2;#else// This is a new version.  It gives slightly different results from the above version// because of small differences in pixel conversionDest = Src;	// TODO this could be made more efficient since we are overwriting Dest?ScaleImage(Dest, (int)floor(Src.width / 1.2), (int)floor(Src.height / 1.2), false, IM_BILINEAR);#endif}//-----------------------------------------------------------------------------// get size of an image stored on diskvoid GetImageSize (int &width, int &height, char sPath[]){Image Img;sLoadImage(Img, sPath);width = Img.width;height = Img.height;}//-----------------------------------------------------------------------------// A function for swapping images efficientlyinline void SwapImages (Image &Img0, Image &Img1){Image Temp;// Copy the image structures but not the pixel buffers.// The memcpy is dangerous because we are copying the address of Temp.buf.// A subsequent ~Temp will also free Img0's buffer (since we don't keep reference counts).  memcpy(&Temp, &Img0, sizeof(Image));memcpy(&Img0, &Img1, sizeof(Image));memcpy(&Img1, &Temp, sizeof(Image));Temp.buf = NULL;	// nasty trick to prevent ~Temp from affecting Img1}

⌨️ 快捷键说明

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