对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() 两个函数可以实现卷积及扩大边界。