现在的位置: 首页 > 综合 > 正文

图像锐化算法

2018年10月27日 ⁄ 综合 ⁄ 共 5232字 ⁄ 字号 评论关闭

对3通道8位图像锐化:

A.每个通道的9宫格内的像素值进行Laplacian锐化,代码如下:

void hello::LinearSharpen(unsigned char* lpImage, int nWidth, int nHeight, unsigned char* SharpenImage)
{
 // 遍历图象的纵坐标
	int y;

 // 遍历图象的横坐标
	int x;

	double * pdGrad ;
 
 // 设置模板系数,定义a方便参数改动
	double a;
	a=0.3;
	static double nWeight[3][3] = {{-a,-a,-a},{-a,8*a,-a},{-a,-a,-a}};

 
 //这些变量用来表示Laplacian算子象素值
	double rTmp[3][3];
	double gTmp[3][3];
	double bTmp[3][3];
 
 // 临时变量
	 double rGrad,gGrad,bGrad;
 
 // 模板循环控制变量
	int yy ;
	int xx ;
 
	pdGrad = (double *)malloc(3*nWidth*nHeight*sizeof(double));
 
 // 初始化为0
	memset(pdGrad, 0, 3*nWidth*nHeight*sizeof(double));
 
	for(y=1; y<nHeight-1 ; y++ )
		for(x=1 ; x<nWidth*3-1 ; x=x+3 ){
			rGrad = 0 ;
			gGrad = 0;
			bGrad = 0;
   // Laplacian算子需要的各点象素值
   
   // 模板第一行
			rTmp[0][0] = lpImage[(y-1)*nWidth*3 + x - 3 ] ; 
			rTmp[0][1] = lpImage[(y-1)*nWidth*3 + x     ] ; 
			rTmp[0][2] = lpImage[(y-1)*nWidth*3 + x + 3 ] ; 

			gTmp[0][0] = lpImage[(y-1)*nWidth*3 + x - 2 ] ; 
			gTmp[0][1] = lpImage[(y-1)*nWidth*3 + x + 1 ] ; 
			gTmp[0][2] = lpImage[(y-1)*nWidth*3 + x + 4 ] ;

			bTmp[0][0] = lpImage[(y-1)*nWidth*3 + x - 1 ] ; 
			bTmp[0][1] = lpImage[(y-1)*nWidth*3 + x + 2 ] ; 
			bTmp[0][2] = lpImage[(y-1)*nWidth*3 + x + 5 ] ;
   
   // 模板第二行
			rTmp[1][0] = lpImage[y*nWidth*3 + x - 3 ]; 
			rTmp[1][1] = lpImage[y*nWidth*3 + x     ] ; 
			rTmp[1][2] = lpImage[y*nWidth*3 + x + 3 ] ;

			gTmp[1][0] = lpImage[y*nWidth*3 + x - 2 ] ; 
			gTmp[1][1] = lpImage[y*nWidth*3 + x + 1 ] ; 
			gTmp[1][2] = lpImage[y*nWidth*3 + x + 4 ] ;

			bTmp[1][0] = lpImage[y*nWidth*3 + x - 1 ] ; 
			bTmp[1][1] = lpImage[y*nWidth*3 + x + 2 ] ; 
			bTmp[1][2] = lpImage[y*nWidth*3 + x + 5 ] ;
   
   // 模板第三行
			rTmp[2][0] = lpImage[(y+1)*nWidth*3 + x - 3 ] ; 
			rTmp[2][1] = lpImage[(y+1)*nWidth*3 + x     ] ; 
			rTmp[2][2] = lpImage[(y+1)*nWidth*3 + x + 3 ] ; 

			gTmp[2][0] = lpImage[(y+1)*nWidth*3 + x - 2 ] ; 
			gTmp[2][1] = lpImage[(y+1)*nWidth*3 + x + 1 ] ; 
			gTmp[2][2] = lpImage[(y+1)*nWidth*3 + x + 4 ] ;

			bTmp[2][0] = lpImage[(y+1)*nWidth*3 + x - 1 ] ; 
			bTmp[2][1] = lpImage[(y+1)*nWidth*3 + x + 2 ] ; 
			bTmp[2][2] = lpImage[(y+1)*nWidth*3 + x + 5 ] ;
   
   // 计算梯度
			for(yy=0; yy<3; yy++)
				for(xx=0; xx<3; xx++){
					rGrad += rTmp[yy][xx] * nWeight[yy][xx] ;
					gGrad += gTmp[yy][xx] * nWeight[yy][xx] ;
					bGrad += bTmp[yy][xx] * nWeight[yy][xx] ;
				}
    
    // 梯度值写入内存
			*(pdGrad+y*nWidth*3+x  ) = rGrad;
			*(pdGrad+y*nWidth*3+x+1) = gGrad;
			*(pdGrad+y*nWidth*3+x+2) = bGrad;
		}
	for(y=0; y<nHeight ; y++ ){
		for(x=0 ; x<nWidth*3 ; x=x+3 ){
			int temp1 = lpImage[y*nWidth*3+x]   + (int)pdGrad[y*nWidth*3+x];
			int temp2 = lpImage[y*nWidth*3+x+1] + (int)pdGrad[y*nWidth*3+x+1];
			int temp3 = lpImage[y*nWidth*3+x+2] + (int)pdGrad[y*nWidth*3+x+2];

			if(temp1 > 255)
				temp1 = 255;
			else if(temp1 < 0)
				temp1 = 0;
			if(temp2 > 255)
				temp2 = 255;
			else if(temp2 < 0)
				temp2 = 0;
			if(temp3 > 255)
				temp3 = 255;
			else if(temp3 < 0)
				temp3 = 0;

			SharpenImage[y*nWidth*3+x  ] = (unsigned char)temp1;
			SharpenImage[y*nWidth*3+x+1] = (unsigned char)temp2;
			SharpenImage[y*nWidth*3+x+2] = (unsigned char)temp3;
 
		}
	}
	free(pdGrad) ;
	pdGrad = NULL   ;
}

B.对每一点的3通道像素值进行平均,并对平均的值进行卷积,然后锐化:

void hello::LinearSharpen_Avg(unsigned char* lpImage, int nWidth, int nHeight, unsigned char* SharpenImage)
{
 // 遍历图象的纵坐标
	int y;
 
 // 遍历图象的横坐标
	int x;

	double * pdGrad ;
 
 // 设置模板系数
	double a;
	a=0.2;
	static double nWeight[3][3] = {{-a,-a,-a},{-a,8*a,-a},{-a,-a,-a}};
 
 //这个变量用来表示Laplacian算子象素值
	double rTmp[3][3];

 
 // 临时变量
	 double rGrad;//,gGrad,bGrad;
 
 // 模板循环控制变量
	int yy ;
	int xx ;
 
	pdGrad = (double *)malloc(3*nWidth*nHeight*sizeof(double));
 
 // 初始化为0
	memset(pdGrad, 0, 3*nWidth*nHeight*sizeof(double));
 
	for(y=1; y<nHeight-1 ; y++ )
		for(x=1 ; x<nWidth*3-1 ; x=x+3 ){
			rGrad = 0 ;
   // Laplacian算子需要的各点象素值
   
   // 模板第一行
			rTmp[0][0] = (lpImage[(y-1)*nWidth*3+x-3 ]+lpImage[(y-1)*nWidth*3+x-2]+lpImage[(y-1)*nWidth*3+x-1])/3 ; 
			rTmp[0][1] = (lpImage[(y-1)*nWidth*3+x   ]+lpImage[(y-1)*nWidth*3+x+1]+lpImage[(y-1)*nWidth*3+x+2])/3 ; 
			rTmp[0][2] = (lpImage[(y-1)*nWidth*3+x+3 ]+lpImage[(y-1)*nWidth*3+x+4]+lpImage[(y-1)*nWidth*3+x+5])/3 ; 
   
   // 模板第二行

			rTmp[1][0] = (lpImage[y*nWidth*3+x-3 ]+lpImage[y*nWidth*3+x-2 ]+lpImage[y*nWidth*3+x-1])/3 ; 
			rTmp[1][1] = (lpImage[y*nWidth*3+x   ]+lpImage[y*nWidth*3+x+1 ]+lpImage[y*nWidth*3+x+2])/3 ; 
			rTmp[1][2] = (lpImage[y*nWidth*3+x+3 ]+lpImage[y*nWidth*3+x+4 ]+lpImage[y*nWidth*3+x+5])/3 ; 
   
   // 模板第三行

			rTmp[2][0] = (lpImage[(y+1)*nWidth*3+x-3 ]+lpImage[(y+1)*nWidth*3+x-2 ]+lpImage[(y+1)*nWidth*3+x-1])/3 ; 
			rTmp[2][1] = (lpImage[(y+1)*nWidth*3+x   ]+lpImage[(y+1)*nWidth*3+x+1 ]+lpImage[(y+1)*nWidth*3+x+2])/3 ; 
			rTmp[2][2] = (lpImage[(y+1)*nWidth*3+x+3 ]+lpImage[(y+1)*nWidth*3+x+4 ]+lpImage[(y+1)*nWidth*3+x+5])/3 ; 
   
// 计算梯度
			for(yy=0; yy<3; yy++)
				for(xx=0; xx<3; xx++){
					rGrad += rTmp[yy][xx] * nWeight[yy][xx] ;
				}
    
    // 梯度值写入内存
			*(pdGrad+y*nWidth*3+x)=rGrad;
			*(pdGrad+y*nWidth*3+x+1)=rGrad;
			*(pdGrad+y*nWidth*3+x+2)=rGrad;
		}
	for(y=0; y<nHeight ; y++ ){
		for(x=0 ; x<nWidth*3 ; x=x+3 ){
			int temp1 = lpImage[y*nWidth*3+x] + (int)pdGrad[y*nWidth*3+x];
			int temp2 = lpImage[y*nWidth*3+x+1] + (int)pdGrad[y*nWidth*3+x+1];
			int temp3 = lpImage[y*nWidth*3+x+2] + (int)pdGrad[y*nWidth*3+x+2];

			if(temp1 > 255)
				temp1 = 255;
			else if(temp1 < 0)
				temp1 = 0;
			if(temp2 > 255)
				temp2 = 255;
			else if(temp2 < 0)
				temp2 = 0;
			if(temp3 > 255)
				temp3 = 255;
			else if(temp3 < 0)
				temp3 = 0;

			SharpenImage[y*nWidth*3+x] = (unsigned char)temp1;
			SharpenImage[y*nWidth*3+x+1] = (unsigned char)temp2;
			SharpenImage[y*nWidth*3+x+2] = (unsigned char)temp3;
 
		}
	}
	free(pdGrad) ;
	pdGrad = NULL   ;
}

Main函数如下:

void hello::LinearMain(){
	cout<<"please input the path of picture;"<<endl;
	IplImage* IpImage =cvLoadImage(hello::inimage().c_str());//inimage()为string类型的输入函数,输入图片的路径

	IplImage* out=cvCreateImage(cvGetSize(IpImage),IpImage->depth,3);
	unsigned char* temp_IpImage=&((unsigned char*)IpImage->imageData)[0];
	unsigned char* temp_out=&((unsigned char*)out->imageData)[0];
	hello::LinearSharpen(temp_IpImage,cvGetSize(IpImage).width,cvGetSize(IpImage).height,temp_out);

	cvShowImage("Linear-in",IpImage);
	cvShowImage("Linear-out",out);

	cvWaitKey(0);
	cvReleaseImage(&IpImage);
	cvReleaseImage(&out);
}

备注:这是把卷积算法简单实现了下,但没有考虑边缘像素点,opencv中cvFilter2D() 和 cvCopyMakeBorder() 两个函数可以实现卷积及扩大边界。

抱歉!评论已关闭.