一般而言,图片有RGB三通道,每个通道用一个byte表示,取值范围在0到255之间。对于每个通道,我们都可以计算图像的直方图,其实就是统计每个像素值的出现频率,如下图所示:
直方图均衡化的效果,即把原图的三通道的直方图变成均匀分布,每种像素值出现的次数都差不多,下面是直方图均衡化后的效果(直方图是用光影查看的,生成效果图的代码见后):
可以看到,图片的直方图很均匀。
直方图均衡化的代码:
- bool GFImage::HistogramEqualization()
- {
- vector<vector<uchar> > pixMaps;
- CalculateMapFunByHisEq(pixMaps);
- for (int ch = 0; ch < GetChannel(); ch++)
- {
- uchar * pData = GetData();
- for (int r = 0;r < GetHeight(); r++)
- {
- uchar * pLine = pData + r * GetWidthStep();
- for (int c = 0; c < GetWidth(); c++)
- {
- uchar val = pLine[GetChannel() * c + ch];
- pLine[GetChannel() * c + ch] = pixMaps[ch][val];
- }
- }
- }
- return true;
- }
- bool GFImage::CalculateMapFunByHisEq(vector<vector<uchar> >& vMappings) const
- {
- vMappings.resize(GetChannel());
- for (int i = 0; i < vMappings.size(); i++)
- {
- vMappings[i].resize(256);
- }
- vector<GFHistogram> vHistograms;
- vHistograms.resize(GetChannel());
- for (int i = 0;i < GetChannel(); i++)
- {
- vHistograms[i].Calculate(*this, 256, i);
- }
- double tmp;
- for (int ch = 0; ch < GetChannel(); ch++)
- {
- tmp = vHistograms[ch].GetFrequencyAt(0) * 255;
- vMappings[ch][0] = (uchar)tmp;
- for (int j = 1;j < 256; j++)
- {
- tmp = tmp + vHistograms[ch].GetFrequencyAt(j) * 255;
- vMappings[ch][j] = (uchar)tmp;
- }
- }
- return true;
- }
调用时
- string strImagePath = "lena.jpg";
- GFImage image1(strImagePath);
- image1.ShowImage("ori");
- image1.HistogramEqualization();
- image1.ShowImage("res");
- cv::waitKey();
其中GFImage封装了opencv的图像类,GFHistogram是自定义的直方图类。详细代码可参考 这里
转自http://blog.csdn.net/wutongthucs/article/details/8118199