学习资料参考:
张平.《OpenCV算法精解:基于Python与C++》.[Z].北京.电子工业出版社.2017.
灰度直方图
简而言之,就是一幅图的每个像素的取值次数的统计图。利用矩阵表示就是一个行矩阵。
可采用库函数calcHist()
进行统计实现。
线性变换
线性变换的基本模式为
O(r,c)=a∗I(r,c)+b,0<=r<rows,0<=c<colsO(r,c) = a * I(r,c) + b,0 <= r < rows,0 <= c < colsO(r,c)=a∗I(r,c)+b,0<=r<rows,0<=c<cols.
示例:
当a=1,b=0a=1,b=0a=1,b=0时,即为原图的副本。
当a=2,b=0a=2,b=0a=2,b=0时,将原图的灰度级范围扩大两倍,提高对比度。
当a=0.5,b=0a=0.5,b=0a=0.5,b=0时,将原图的灰度级范围缩小两倍,降低对比度。
函数实现
- 方式一
Mat::convert(输出矩阵,输出矩阵的数据类型,a,b);
- 方式二
Mat Out = 2 * I;
直接利用乘法计算。 - 方式三
convertScaleAbs(输入矩阵,输出矩阵,a,b);
与方式一的唯一不同之处在于这里默认的输入矩阵与输出矩阵的数据类型是相同的。
应用
上述是对整个灰度级范围使用了相同的参数。但实际应用种我们需要对不同的区域进行灰度级对比度不同的处理以达到增强或减弱的功能。
直方图正规化
前文中的a与b需要人为的确定值,那么自动获取值是需要解决的问题。
原理
若给定某图像III,高HHH,宽WWW,I(r,c)I(r,c)I(r,c)表示III的第rrr行第ccc列的灰度值,最小灰度值记为IminI_{min}Imin,最大灰度值记为ImaxI_{max}Imax,则I(r,c)I(r,c)I(r,c)介于 IminI_{min}Imin和ImaxI_{max}Imax之间。而我们的目标是输出图像灰度值满足在 OminO_{min}Omin和OmaxO_{max}Omax之间。我们可做如下变换:
且令Omin=0,Omax=255O_{min} = 0,O_{max}=255Omin=0,Omax=255,上述表达式就是直方图的正规化。
实现
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main() {
Mat I = imread("p3.jpg", IMREAD_GRAYSCALE);
//找原图的最大值和最小值
double Imax, Imin;
minMaxLoc(I, &Imin, &Imax, NULL, NULL);
//设置目标图的最大最小值
double Omin = 0, Omax = 255;
//设置a和b
double a = (Omax - Omin) / (Imax - Imin);
double b = Omin - a * Imin;
//线性变换
Mat O;
convertScaleAbs(I, O, a, b);
imshow("I", I);
imshow("O", O);
waitKey(0);
return 0;
}
运行结果(原图来自网络)