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

📄 geometrytrans.cpp

📁 将数字图像处理的一般算法都集中在一个MFC的框架中
💻 CPP
📖 第 1 页 / 共 3 页
字号:
 *   interpolationDblLinear()
 *
 * 参数:
 *   array,2*2数组,存放图像待插值位置周围四个像素灰度值
 *   xpos,ypos为相对于数组四个像素的插值位置坐标,取小数
 *
 * 返回值:
 *   插值结果。
 *
 * 说明:
 *   该函数将原图像待插值位置的四个像素数据拷贝到数组array中,根据插值位置坐标对
 *   应到array的位置,对数组array的四个元素进行双线性插值,返回值为插值的结果。
 ************************************************************************/
unsigned char GeometryTrans::interpolationDblLinear(unsigned char array[2][2], 
													float xpos, float ypos)
{
	//两个中间变量
	int t1, t2;

	//先垂直方向线性插值
	t1 = (1-ypos)*array[0][0] + ypos*array[1][0];
	t2 = (1-ypos)*array[0][1] + ypos*array[1][1];

	//再水平方向线性插值
	float t=(int)((1-xpos)*t1 + xpos*t2);

	//若插值结果小于0,则输出0
	if(t<0)
		t=0;

	//若插值结果大于255,则输出255
	if(t>255) 
		t=255;

	//插值结果返回
	return (unsigned char)t;
}


/*************************************************************************
 *
 * 函数名称:
 *   interpolationCube()
 *
 * 参数:
 *   array,4x4数组,存放图像待插值位置周围16个像素灰度值
 *   xpos,ypos对应于4x4数组16个元素的插值坐标
 *
 * 返回值:
 *   插值结果。
 *
 * 说明:
 *   该函数将原图像待插值位置周围16个像素数据拷贝到数组array中,根据插值位置坐标对
 *   应到array的位置,对数组array的16个元素进行立方卷积插值,返回值为插值的结果。
 *
 ************************************************************************/
unsigned char GeometryTrans::interpolationCube(unsigned char array[4][4], float xpos, float ypos)
{

	//申请数组,计算插值所需要的系数
	float col[4], row[4];

	//准备插值的x方向数据源
	col[0]=xpos+1;
	col[1]=xpos;
	col[2]=1-xpos;
	col[3]=2-xpos;

	//准备插值的y方向数据源
	row[0]=ypos+1;
	row[1]=ypos;
	row[2]=1-ypos;
	row[3]=2-ypos;
	
	//循环变量
	int i;

	//临时变量
	float t;

	//对水平方向系数数组进行计算
	for(i=0;i<4;i++){
		t=fabs(col[i]);
		if (t>=0&&t<1)
			col[i]=pow(t,3)-2*pow(t,2)+1;
		else if (t>=1&&t<2)
			col[i]=-pow(t,3)+5*pow(t,2)-8*t+4;
		else
			col[i]=0;
	}

	//对垂直方向系数数组进行计算
	for(i=0;i<4;i++){
		t=fabs(row[i]);
		if (t>=0&&t<1)
			row[i]=pow(t,3)-2*pow(t,2)+1;
		else if (t>=1&&t<2)
			row[i]=-pow(t,3)+5*pow(t,2)-8*t+4;
		else
			row[i]=0;
	}
	
	//将计算好的系数与对应图像数据数组作卷积
	float tempArray[4], temp;
	//先x方向卷积
	for(i=0;i<4;i++)
		tempArray[i]=row[0]*array[0][i]+row[1]*array[1][i]+row[2]*array[2][i]+row[3]*array[3][i];
	
	//再y方向卷积
	temp=0;
	for (i=0;i<4;i++)
		temp+=tempArray[i]*col[i];
		
	//将插值结果在图像灰度级范围内输出
	if (temp>255)
		temp=255;
	if (temp<0)
		temp=0;

	//函数返回值,插值结果
	return (unsigned char)temp;

}


/*************************************************************************
 *
 * 函数名称:
 *   Zoom()
 *
 * 参数:
 *   int zoomWidthPixel  -输出图像的宽,像素为单位
 *   int zoomHeightPixel  -输出图像的高,像素为单位
 *   int interpolationflag  -插值方式,0为近邻插值,1为双线性插值,2为立方卷积插值
 *
 * 返回值:
 *   无
 *
 * 说明:
 *   根据指定的大小和指定的插值方式,对原图像进行缩放,缩放后的结果存放
 *   在m_pImgDataOut缓冲区中,该函数同时适合于彩色和灰度图像
 *
 ************************************************************************/
void GeometryTrans::Zoom(int zoomWidthPixel, int zoomHeightPixel, int interpolationflag)
{
	//释放旧的输出图像缓冲区
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}

	//输出图像的宽和高
	m_imgWidthOut=zoomWidthPixel;
	m_imgHeightOut=zoomHeightPixel;

	//输出图像每行像素字节数
	int lineByteOut=(m_imgWidthOut*m_nBitCountOut/8+3)/4*4;

	//申请缓冲区,存放输出结果
	m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeightOut];

	//近邻插值缩放
	if(interpolationflag==0)
		ZoomNeighbor(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount, 
		             m_pImgDataOut, m_imgWidthOut, m_imgHeightOut);

	//双线性插值缩放
	else if(interpolationflag==1)
		ZoomDblLinear(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
		              m_pImgDataOut, m_imgWidthOut, m_imgHeightOut);
	
	//立方卷积插值
	else
	    ZoomCube(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
		         m_pImgDataOut, m_imgWidthOut, m_imgHeightOut);
}


/*************************************************************************
 *
 * 函数名称:
 *   ZoomNeighbor()
 *
 * 参数:
 *   unsigned char *pImgIn  -输入图像缓冲区指针
 *   int widthIn  -输入图像的宽
 *   int heightIn  -输入图像的高
 *   int biBitCount -图像每像素位数,输入图像与输出图像相同
 * 	 unsigned char *pImgOut  -输出图像缓冲区指针,该存储区已经存在
 *   int widthOut  -输出图像的宽
 *   int heightOut -输出图像的高

 * 返回值:
 *   无
 *
 * 说明:
 *  将pImgIn所指向的数据由widthIn*heightIn最近邻缩放至widthOut*heightOut的大小,
 *  结果存放在pImgOut缓冲区中,该函数同时适合于彩色和灰度图像
 *
 ************************************************************************/
void GeometryTrans::ZoomNeighbor(unsigned char *pImgIn, int widthIn, int heightIn, 
				int biBitCount, unsigned char *pImgOut, int widthOut, int heightOut)
{
	//水平方向缩放比例
	float ratioX=(float)widthOut/widthIn;

	//垂直方向缩放比例
	float ratioY=(float)heightOut/heightIn;

	//每像素字节数,输入图像与输出图像相同
	int pixelByte=biBitCount/8;


	//输出图像在输入图像中待插值的位置坐标
    int coordinateX, coordinateY;

	//输入图像每行像素字节数
	int lineByteIn=(widthIn*pixelByte+3)/4*4;

	//输出图像每行像素字节数
	int lineByteOut=(widthOut*pixelByte+3)/4*4;

	//循环变量,输出图像的坐标
	int i, j;

	//循环变量,像素的每个通道
	int k;

    //近邻插值
	for(i=0; i< heightOut; i++){
		for(j=0; j< widthOut ; j++){  
			//输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置
			coordinateX=j/ratioX+0.5;
			coordinateY=i/ratioY+0.5;

			//若插值位置在输入图像范围内,则近邻插值
			if(0<=coordinateX&&coordinateX<widthIn
				&& coordinateY>=0&&coordinateY<heightIn){
				for(k=0;k<pixelByte;k++)
					*(pImgOut + i * lineByteOut + j*pixelByte + k) 
					=*(pImgIn+ coordinateY*lineByteIn+ coordinateX*pixelByte + k) ;
			}
			else //若不在输入图像范围内,则置255  
			{
				for(k=0;k<pixelByte;k++)
					*(pImgOut + i * lineByteOut + j*pixelByte+k) = 255;
			}
			
		}
	}
}

/*************************************************************************
 *
 * 函数名称:
 *   ZoomDblLinear()
 *
 * 参数:
 *   unsigned char *pImgIn  -输入图像缓冲区指针
 *   int widthIn  -输入图像的宽
 *   int heightIn  -输入图像的高
 *   int biBitCount -图像每像素位数,输入图像与输出图像相同
 * 	 unsigned char *pImgOut  -输出图像缓冲区指针,该存储区已经存在
 *   int widthOut  -输出图像的宽
 *   int heightOut -输出图像的高

 * 返回值:
 *   无
 *
 * 说明:
 *  将pImgIn所指向的数据由widthIn*heightIn双线性缩放至widthOut*heightOut的大小,
 *  结果存放在pImgOut缓冲区中,该函数同时适合于彩色和灰度图像
 *
 ************************************************************************/
void GeometryTrans::ZoomDblLinear(unsigned char *pImgIn, int widthIn, int heightIn, 
				int biBitCount,unsigned char *pImgOut, int widthOut, int heightOut)
										 
{
	//水平方向缩放比例
	float ratioX=(float)widthOut/widthIn;

	//垂直方向缩放比例
	float ratioY=(float)heightOut/heightIn;

	//每像素字节数,输入图像与输出图像相同
	int pixelByte=biBitCount/8;

	//输出图像在输入图像中待插值的位置坐标,必须浮点型
    float coordinateX, coordinateY;

	//输入图像每行像素字节数
	int lineByteIn=(widthIn*pixelByte+3)/4*4;

	//输出图像每行像素字节数
	int lineByteOut=(widthOut*pixelByte+3)/4*4;

	//循环变量,输出图像的坐标
	int i, j;

	//循环变量,像素的每个通道
	int k;

	//临时变量,待插值位置向下取整的坐标
	int Iu, Iv;

	//数组,存放插值位置周围的4个像素
	unsigned char array[2][2];

  //双线性插值
	for(i=0; i< heightOut; i++){
		for(j=0; j< widthOut ; j++){   

			//输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置
			coordinateX=j/ratioX;
			coordinateY=i/ratioY;

			//对插值位置坐标取整
			Iu=(int)coordinateX;
			Iv=(int)coordinateY;
			
			//若插值位置在输入图像范围内,则双线性插值
			if(0<=coordinateX&&coordinateX<widthIn
				&& coordinateY>=0&&coordinateY<heightIn){
				//将图像每个像素通道的数据进行分别插值,
				//彩图pixelByte为3,灰度图像pixelByte为1
				for(k=0;k<pixelByte;k++){
					//将第k个通道的四个像素数据拷贝至array数组中
					array[0][0]=*(pImgIn+ Iv*lineByteIn+ Iu*pixelByte+k);
					array[0][1]=*(pImgIn+ Iv*lineByteIn+ (Iu+1)*pixelByte+k);
					array[1][0]=*(pImgIn+ (Iv+1)*lineByteIn+ Iu*pixelByte+k);
					array[1][1]=*(pImgIn+ (Iv+1)*lineByteIn+ (Iu+1)*pixelByte+k);
					
					//调用双线性插值函数插值并输出到pImgOut中
					*(pImgOut + i * lineByteOut + j*pixelByte+k)
						=interpolationDblLinear(array, coordinateX-Iu, coordinateY-Iv);
				}
			}
			else{//边缘像素采用近邻插值
				for(k=0;k<pixelByte;k++)
					*(pImgOut + i * lineByteOut + j*pixelByte + k) =
					*(pImgIn+ Iv*lineByteIn+ Iu*pixelByte+k);
			}

		}
	}
	
}

/*************************************************************************
 *
 * 函数名称:
 *   ZoomCube()
 *
 * 参数:
 *   unsigned char *pImgIn  -输入图像缓冲区指针
 *   int widthIn  -输入图像的宽
 *   int heightIn  -输入图像的高
 *   int biBitCount -图像每像素位数,输入图像与输出图像相同
 * 	 unsigned char *pImgOut  -输出图像缓冲区指针,该存储区已经存在
 *   int widthOut  -输出图像的宽
 *   int heightOut -输出图像的高

 * 返回值:
 *   无
 *
 * 说明:
 *  将pImgIn所指向的数据由widthIn*heightIn立方卷积缩放至widthOut*heightOut的大小,
 *  结果存放在pImgOut缓冲区中,该函数同时适合于彩色和灰度图像
 *
 ************************************************************************/
void GeometryTrans::ZoomCube(unsigned char *pImgIn, int widthIn, int heightIn,
		int biBitCount, unsigned char *pImgOut, int widthOut, int heightOut)
{
	//水平方向缩放比例
	float ratioX=(float)widthOut/widthIn;

	//垂直方向缩放比例
	float ratioY=(float)heightOut/heightIn;

	//每像素字节数,输入图像与输出图像相同
	int pixelByte=biBitCount/8;

	//输出图像在输入图像中待插值的位置坐标,必须浮点型
    float coordinateX, coordinateY;

	//输入图像每行像素字节数
	int lineByteIn=(widthIn*pixelByte+3)/4*4;

	//输出图像每行像素字节数
	int lineByteOut=(widthOut*pixelByte+3)/4*4;

	//循环变量,输出图像的坐标
	int i, j;

	//循环变量,像素的每个通道
	int k;

	//临时变量,待插值位置向下取整的坐标
	int Iu, Iv;

	//数组,存放插值位置周围16个像素
	unsigned char array[4][4];
 
	//循环变量,遍历待插值位置4x4的图像数据
	int  x, y;


	//立方卷积插值
	for(i=0; i< heightOut; i++){
		for(j=0; j< widthOut ; j++){   
			//输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置
			coordinateX=j/ratioX;
			coordinateY=i/ratioY;

			//对插值位置坐标取整
			Iu=(int)coordinateX;
			Iv=(int)coordinateY;

			//若插值位置在输入图像范围内,则立方卷积插值
			if(1<=coordinateX&&coordinateX<widthIn-2
				&& coordinateY>=1&&coordinateY<heightIn-2){
				//将图像每个像素通道的数据进行分别插值,
				//彩图pixelByte为3,灰度图像pixelByte为1
				for(k=0;k<pixelByte;k++){
					//将第k个通道的4x4个像素数据拷贝至array数组中
					for(y=Iv-1;y<Iv+3;y++)
					{
						for (x=Iu-1;x<Iu+3;x++)
						{
							array[y-Iv+1][x-Iu+1]=
								*(pImgIn+y*lineByteIn+x*pixelByte+k);
						}
					}

					//调用立方卷积插值函数插值并输出到pImgOut中
					*(pImgOut + i * lineByteOut + j*pixelByte+k)
						=interpolationCube(array, coordinateX-Iu, coordinateY-Iv);
				}
			}
			else{//边缘像素采用近邻插值
				for(k=0;k<pixelByte;k++)
					*(pImgOut + i * lineByteOut + j*pixelByte + k) =
					*(pImgIn+ Iv*lineByteIn+ Iu*pixelByte+k);
			}

		}

⌨️ 快捷键说明

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