图像模糊不清或曝光过度的情况下,可以通过线性灰度增强来对图像内的像素进行线性扩展,改变图片的显示效果。
转换公式: g(x,y)=((d-c)/(b-a))(f(x,y)-a)+c
其中,f(x,y)为转换前图像,其灰度范围为[a,b];g(x,y)为转换后图像,其灰度范围为[c,d]。
//线性灰度增强 g(x,y)=[(d-c)/(b-a)]*(f(x,y)-a)+c bool GrayLinearTransform(IplImage* src, IplImage* dst, uchar dstStart, uchar dstEnd) { uchar* srcData = (uchar*)src->imageData; //获取图像最大最小灰度(分情况可简化为255-0) int imageMax,imageMin; imageMax = imageMin = srcData[0]; for( int x = 0; x < src->height; x++) for(int y = 0; y < src->width; y++) { int value = srcData[x*src->widthStep+y]; if( imageMax < value) imageMax = value; else if(imageMin>value) imageMin = value; } float linearRatio = float(dstEnd-dstStart)/(imageMax-imageMin); for( int x = 0; x < src->height; x++) for(int y = 0; y < src->width; y++) { int step = src->widthStep; int a = srcData[x*step+y]; int bb = linearRatio*(a-imageMin)+ dstStart; dst->imageData[x*step+y] = bb; } return true; }
在OpenCV中,函数
cvNormalize( const CvArr* src, CvArr* dst, double a CV_DEFAULT(1.), double b CV_DEFAULT(0.), int norm_type CV_DEFAULT(CV_L2), const CvArr* mask CV_DEFAULT(NULL) );
也可实现相同功能:
// HelloOpenCV.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <cv.h> #include <cxcore.h> #include <highgui.h> // 隐藏 console 窗口 #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) //线性灰度增强 g(x,y)=[(d-c)/(b-a)]*(f(x,y)-a)+c bool GrayLinearTransform(IplImage* src, IplImage* dst, uchar dstStart, uchar dstEnd) { uchar* srcData = (uchar*)src->imageData; //获取图像最大最小灰度(分情况可简化为255-0) int imageMax,imageMin; imageMax = imageMin = srcData[0]; for( int x = 0; x < src->height; x++) for(int y = 0; y < src->width; y++) { int value = srcData[x*src->widthStep+y]; if( imageMax < value) imageMax = value; else if(imageMin>value) imageMin = value; } float linearRatio = float(dstEnd-dstStart)/(imageMax-imageMin); for( int x = 0; x < src->height; x++) for(int y = 0; y < src->width; y++) { int step = src->widthStep; int a = srcData[x*step+y]; int bb = linearRatio*(a-imageMin)+ dstStart; dst->imageData[x*step+y] = bb; } return true; } int main( int argc, char** argv ) { cvNamedWindow( "win",1); ::cvMoveWindow("win",300,100); IplImage* src = cvLoadImage( "C:\\Users\\Administrator\\Pictures\\lena.jpg", 1 ); //cvShowImage("win", src); //cvWaitKey(0); IplImage * dst_gray = cvCreateImage( cvGetSize(src), src->depth, 1); cvSetZero(dst_gray); cvCvtColor(src,dst_gray,CV_BGR2GRAY);//得到灰度图 cvShowImage("win", dst_gray); cvWaitKey(0); IplImage* transform = ::cvCreateImage(cvGetSize(dst_gray),dst_gray->depth,1); cvSetZero(transform); if(GrayLinearTransform(dst_gray,transform,100,200)) { cvShowImage("win", transform); cvWaitKey(0); } IplImage* transform2=::cvCreateImage(cvGetSize(dst_gray),dst_gray->depth,1); cvSetZero(transform2); cvNormalize(dst_gray,transform2,255,0,CV_MINMAX,NULL); cvShowImage("win", transform2); cvWaitKey(0); ::cvReleaseImage(&src); ::cvReleaseImage(&dst_gray); ::cvReleaseImage(&transform); ::cvReleaseImage(&transform2); ::cvDestroyWindow("win"); return 0; }
转换前,灰度图像:
将灰度区间缩小为[100,200]得到图片:
再将灰度图片由[100,200]放大至[0,255]:
经过缩放后的图片有一定的“锐化”效果