直方图 Histogram
这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。
通过这种方法,亮度可以更好地在直方图上分布。
这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。
这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。
这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。
E.G -参见下图,这里位深为2,所以每个像素的位深为
0 到 3.
Sample Image (Depth = 2 bits) |
直方图是表现了每个像素值分布。可以看到上图5个像素值为0,7个像素值为1,9个像素值为2,4个像素值为3。
这些信息的分布如下
用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数 |
图像的直方图通常表示为如下图的就是上面图的直方图。
图像直方图 |
直方图均衡化
直方图均衡被定义为均衡的图像的强度分布或压扁的强度分布曲线。
直方图均衡是用来改善图像的对比度。上述图像的直方图均衡化理想状况如下图。
直方图均衡化 |
上图是理想状况,实际上,达到完美的直方图均衡化是不可能的。可以接近完美实现直方图均衡。
在OpenCV中,有一个内置的OpenCV函数来均衡直方图。
灰度图像直方图均衡化
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, const char** argv )
{
Mat img = imread("C:/MyPic.JPG", CV_LOAD_IMAGE_COLOR); //open and read the image
if (img.empty())
{
cout << "Image cannot be loaded..!!" << endl;
return -1;
}
cvtColor(img, img, CV_BGR2GRAY); //change the color image to grayscale image
Mat img_hist_equalized;
equalizeHist(img, img_hist_equalized); //equalize the histogram
//create windows
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
namedWindow("Histogram Equalized", CV_WINDOW_AUTOSIZE);
//show the image
imshow("Original Image", img);
imshow("Histogram Equalized", img_hist_equalized);
waitKey(0); //wait for key press
destroyAllWindows(); //destroy all open windows
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
新的OpenCV函数
- void cvtColor( InputArray src, OutputArray dst, int code, int dstCn=0 )
这个函数是将图像从一个色彩空间变换到另外一个色彩空间。OpenCV一般是以BGR色彩空间的形式载入。
上例中, 欲把图像变换到灰度空间中。采用CV_BGR2GRAY为第3参数。如果想转换到HSV色彩空间需要用CV_BGR2HSV作为参数。
下面是对上面函数的每个参数简单说明:
- InputArray src- 输入图像(8或16位深无符号整形或者32为浮点型图像)
- OutputArray dst - 输出图像(与输入图像大小及位深一致)
-
int code- 是一个掩码,表示由src到dst之间是怎么转的,比如是彩色转为灰度,还是彩色转为HSI模式;
- CV_BGR2HSV
- CV_HSV2BGR
- CV_RGB2HLS
- CV_HLS2RGB
- CV_BGR2GRAY
- CV_GRAY2BGR
- int dstCn - 最后的dstCn表示dst图像的波段数,这个值默认是0,它可以从参数code中推断。通道数,默认为0的时候,目标图像通道数自动从源图像继承以及色彩空间。初学者推荐设置为默认值。
- void equalizeHist( InputArray src, OutputArray dst )
这个函数是单通道图像的直方图(灰度图)。
通过均衡化直方图,亮度归一化。其结果是,对比度得到提高。
- InputArray src - 8位深单通道图像
- OutputArray dst - 输出的图像与输入图像大小与数据类型相同(应和源图像大小及位深一致)
彩色图片直方图均衡化
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, const char** argv )
{
Mat img = imread("MyPic.JPG", CV_LOAD_IMAGE_COLOR); //open and read the image
if (img.empty()) //if unsuccessful, exit the program
{
cout << "Image cannot be loaded..!!" << endl;
return -1;
}
vector<Mat> channels;
Mat img_hist_equalized;
cvtColor(img, img_hist_equalized, CV_BGR2YCrCb); //change the color image from BGR to YCrCb format
split(img_hist_equalized,channels); //split the image into channels
equalizeHist(channels[0], channels[0]); //equalize histogram on the 1st channel (Y)
merge(channels,img_hist_equalized); //merge 3 channels including the modified 1st channel into one image
cvtColor(img_hist_equalized, img_hist_equalized, CV_YCrCb2BGR); //change the color image from YCrCb to BGR format (to display image properly)
//create windows
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
namedWindow("Histogram Equalized", CV_WINDOW_AUTOSIZE);
//show the image
imshow("Original Image", img);
imshow("Histogram Equalized", img_hist_equalized);
waitKey(0); //wait for key press
destroyAllWindows(); //destroy all open windows
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
新OpenCV函数
- cvtColor(img, img_hist_equalized, CV_BGR2YCrCb)
把'img'的BGR色彩空间变换到YCrCb色彩空间保存到
'
img_hist_equalized
'.
- void split(const Mat& m, vector<Mat>& mv )
有些时候处理多通道图像时不是很方便,在这种情况下,可以利用split() 分别复制每个通道到多个单通道图像,如果需要,split()函数将复制m(即源多通道图像)的各个通道到图像vector里
'
mv
'。用法很简单,src 是一幅多通道的图像。 mv 保存各个通道,每个通道存放到一个 mat 中。
参数表
- const Mat& m - 输入的多通道图像。
- vector<Mat>& mv - mv保存各个通道,每个通道存放到一个 mat 中
- equalizeHist(channels[0], channels[0]);
用来使灰度图象直方图均衡化。
- 第一个参数--输入的 8-比特 单信道图像
- 第二个参数--输出的图像与输入图像大小与数据类型相同
- 只对第一个通道感兴趣 (Y) ,因为此通道代表了强度。而其他两个通道(Cr 及 Cb)代表颜色。所以采用OpenCV内置函数'equalizeHist(..)' 把第一个通道直方图均衡化,而其他另外俩通道不便保持不变。
- void merge(const vector<Mat>& mv, OutputArray dst )
merge 与split 函数相反。可以将多个单通道图像合成一幅多通道图像。
功能是将多个单通道图像合并为单个多通道图像。
参数表
- const vector<Mat>& mv - 向量是多通道。所有的通道的图像大小以及位深必须一致。
- OutputArray dst - 存储多通道图像