常见的图像增强算法有;直方图均衡,拉普拉斯算子,对数log变换,伽玛变换。
1.对数log变换:
void main()
{
Mat src = imread("C:/Users/Administrator/Desktop/add/1.jpg");
imshow("src",src);
Mat temp(src.size(),CV_32FC3);
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
temp.at<Vec3f>(i, j)[0] = log(1 + src.at<Vec3b>(i, j)[0]);
temp.at<Vec3f>(i, j)[1] = log(1 + src.at<Vec3b>(i, j)[1]);
temp.at<Vec3f>(i, j)[2] = log(1 + src.at<Vec3b>(i, j)[2]);
}
}
normalize(temp, temp, 0, 255, CV_MINMAX);
convertScaleAbs(temp,temp);
imshow("temp",temp);
waitKey(0);
}
如果temp直接定义为src.type()类型,最后的图感觉都点失真。converScaleAbs必不可少,否则最后的输出只有部分图像。这里的log是以e为底数。log还有其它几种形式,分别为:log10(即以10为底)、log2(即以2位底)、log1p(以e为底,指数加1)、logb(即指数,返回n)。其中normalize可以看这个。对数的底数越大,变换后图像的对比度越大。对数变换对图像对比度偏低的效果比较好。
2.伽玛变换:
void main()
{
Mat src = imread("C:/Users/Administrator/Desktop/add/1.jpg");
imshow("src",src);
Mat temp(src.size(),CV_32FC3);
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
temp.at<Vec3f>(i, j)[0] = pow(src.at<Vec3b>(i, j)[0],0.4);
temp.at<Vec3f>(i, j)[1] = pow(src.at<Vec3b>(i, j)[1], 0.4);
temp.at<Vec3f>(i, j)[2] = pow(src.at<Vec3b>(i, j)[2], 0.4);
}
}
normalize(temp, temp, 0, 255, CV_MINMAX);
convertScaleAbs(temp,temp);
imshow("temp",temp);
waitKey(0);
}
converScaleAbs必不可少,否则最后的输出只有部分图像。以1为分界点,pow中的幂指数越大,图像就会越暗;幂指数越小,图像就会越亮。
3.直方图均衡:
void main()
{
Mat src = imread("C:/Users/Administrator/Desktop/add/1.jpg");
imshow("src",src);
vector<Mat> lis;
split(src,lis);
for (int i = 0; i < 3; i++)
{
equalizeHist(lis[i],lis[i]);
}
Mat dst;
merge(lis,dst);
imshow("dst",dst);
waitKey(0);
}
其实还可以先将src转为hsv颜色空间,然后split,直方图均衡V分量,效果和均衡RGB一样。均衡RGB容易出现失真,直接均衡亮度V比较好。
void main()
{
Mat src = imread("C:/Users/Administrator/Desktop/add/1.jpg");
imshow("src", src);
cvtColor(src, src, CV_BGR2HSV);
vector<Mat> lis;
split(src, lis);
equalizeHist(lis[2], lis[2]);
Mat dst;
merge(lis, dst);
cvtColor(dst,dst,CV_HSV2BGR);
imshow("dst", dst);
waitKey(0);
}
4.拉普拉斯算子:
算子:
,用它作为卷积核对原图卷积,可以达到锐化的效果。
void main()
{
Mat src = imread("C:/Users/Administrator/Desktop/add/1.jpg");
imshow("src",src);
Mat A=(Mat_<int>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
Mat dst;
filter2D(src,dst,CV_8UC3,A);
imshow("dst",dst);
waitKey(0);
}
可以自己构造一个核,核内的所有元素(即权重)的和为1,即可构成锐化核。如果感兴趣的像素已经与其临近像素有一点差别,卷积一个这样的核,差别就会增加。这样就会让图像锐化,因为该像素的值与临近像素值之间的差距变大。核内的所有元素(即权重)的和为0,就会得到一个边缘检测核,把边缘转为白色,把非边缘区域转为黑色。
拉普拉斯算子有如下几种(《数字图像处理》第三版P99):
,
,
,
若使用的核中间系数为正,将原图加上拉普拉斯变换后的图就可以得到锐化后的图;若使用的核的中间系数为负,将原图减去拉普拉斯变换后的图就可以得到锐化后的图。
void main()
{
Mat src = imread("C:/Users/Administrator/Desktop/add/1.jpg");
imshow("src", src);
Mat A = (Mat_<int>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
Mat dst;
filter2D(src, dst, CV_8UC3, A);
imshow("dst", dst);
Mat cap;
cap = src + dst;
imshow("cap",cap);
waitKey(0);
}
参考: