在传统的计算机视觉图像处理中,一般都有比较固定的处理步骤。当然这些步骤根据不同的图像处理要求,会有一定的变化。比如,对图像进行滤波、增强、分割、提取特征、统计等。其中的每一个步骤又涉及到很多不同的处理算法,每种算法的效果是不一样的。所以,我们要了解各种算法的原理以及针对每一种图像采用哪种算法的效果更好。这些需要长期的知识以及经验的积累。图像增强算法是图像处理的基础算法,刚开始接触图像处理的时候,一般都离不了对图像进行增强处理。
图像增强的目的是让图像变得更加清晰,让想要提取的特征更加突出的显示出来。在很多时候,由于现场光照的原因,往往某些想要提取的特征的灰度范围比较小,或者说与背景之间的差别比较小,这时候,就可以采用图像增强的方法,让特征所在的灰度区间更加突出的显示出来。
图像增强的方法有很多,最简单的当是灰度线性拉伸。灰度图像的灰度值区间是0到255.但是,有时候我们采集的图像的灰度区间往往只集中在某一个小范围的区间内,这时候,我们就可以采用线性拉伸的方法将灰度区间变换到0到255这个范围内。线性拉伸的算法比较简单。比如,假设原图的灰度在0到100这个范围内,同时假设特征的灰度空间在30到60这个范围。这时候,特征区间容易受到背景灰度的影响,如果我们想要提取该特征,得到的结果往往不能满足实际需求。因为在实际采集的图像中,光照可能随时会发生变化,采用预先设置的特征提取参数往往不能达到既定的需求,因为预先设置的参数的适用范围比较小。这时候,我们就可以采用图像增强的方法,让特征突出显示出来。对于这种图像,线性拉伸是一种比较简单且效率很高的算法。线性拉伸其实就是对原图的灰度值进行线性变换,假设原来的灰度值是x,变换函数就是一个线性方程,假设变换后的值为y,即y=ax+b.经过这样的变换之后,原来的灰度空间变大,特征区间与背景之间的区别被增大,这时候,我们再利用设定的阈值来提取特征,则阈值的变化区间变大,适用的范围也增大了,从而适用于更大的光照变化区间。让特征提取的算法适应性更强。下面是线性拉伸的具体代码。
void lienTranf(Mat src, Mat &dst, double k, double b){for (int i = 0; i < src.rows; i++){uchar* srcData = src.ptr(i);for (int j = 0; j < src.cols; j++){//线性变换dst.at(i, j) = srcData[j] * k + b;}}}int main(int argc, char** argv){Mat src = imread("E:1.bmp", 0);namedWindow("src", 1);imshow("src", src);int height = src.rows;int width = src.cols;Mat dst = Mat(src.size(), CV_32F);lienTranf(src, dst, 2, 5);//线性变换函数cv::convertScaleAbs(dst, dst);//将图像矩阵变为可以显示的图像normalize(dst, dst, 0, 255, NORM_MINMAX);//将图像变换后的值固定在0到255之间namedWindow("dst", 1);imshow("dst", dst);waitKey(0);return 0;}
图1 原图
图2 线性变换后的图像
从上面两张图像可以看出,经过线性拉伸之后,图像的背景与特征之间的区别变得更加明显了。这就是线性变换的效果。
dst.at(i, j) = srcData[j] * k + b;这一行代码就是线性变换的核心,其实就是一个直线方程。通过这个方程将原图的灰度值进行了变换,随着k值和b值的取值不同,原图的灰度值可能增大,也可能变小,这就需要根据具体的图像进行设置了。也就是说,线性拉伸并不是只是将原图的灰度值拉伸变大,根据具体的需求,也可以将原图的灰度值进行压缩。
同时,灰度线性拉伸也可以根据具体的需求,只对一部分灰度区间进行变换,这就是分段线性变换。下面这段代码说明了怎么进行分段线性变换,其中具体的线性变换的参数根据不同的图像有不同的设置,这里只是随便设置了一个,作为一个简单的实例程序。下面这段代码对0到50的灰度区间设置了一个变换,对50到200的灰度区间设置了另一个变换,对大于200的灰度区间又设置了不同的变换,这里只是展示了如何对不同的灰度区间进行不同的线性变换。对于不同的图像我们都可以很方便的设置不同的变换韩式,从而实现不同的增强效果。
//分段线性变换
if(src.at(i,j) <50)
{
dst.at(i,j) = src.at(i,j)*2 + 10;
}
if(src.at(i,j) > 50 && src.at(i,j) <200)
{
dst.at(i,j) = src.at(i,j);
}
if(src.at(i,j) > 200)
{
dst.at(i,j) = src.at(i,j)*0.8 + 10;
}
线性变换增强只是图像增强当中最基本的一种方法,后面我们将说明另外几种不同的图像增强方法,将更加适用于不同的图像。