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