天天看点

图像处理学习之直方图均衡

     直方图均衡是图像处理中一种增强对比度的方法。其过程用一句话来概括就是把一个给定的分布的直方图转成另外一个分布的直方图。这里给定的分布的直方图就是原图的直方图,转换后的直方图的分布其范围更宽。(有兴趣研究直方图原理以及推导过程参考​​http://www.doc88.com/p-8979039804387.html​​)

直方图均衡的步骤

       1、 统计直方图

统计直方图,即统计每个色度的像素个数。通常的灰度范围为0-255.

       2、 计算分布密度

计算每个灰度的分布,即将每个灰度的像素个数除以整张图片的像素个数即得到每个灰度在这张图片中出现的密度。

       3、 计算累积直方图

计算每个区间的累积直方图,例如 计算L处的值就是计算[0, L]范围内的灰度在整张图片中出现的密度。

      4、 计算映射值

利用累计直方图计算变换后的灰度。

       5、 映射

将原来的灰度映射为变换后的灰度,即得到均衡后的图像。

例子

#include "stdafx.h"
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2\core\core.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//直方图均衡函数
void HistNorSigle(Mat &Img)
{
  int nRows = Img.rows;
  int nCols = Img.cols;

  uchar *ptr;

  int nCorTab[256];
  int temp = 0;

  memset(nCorTab, 0, sizeof(int)*256);

  //1、计算直方图
  for (int i = 0; i < nRows; ++i)
  {
    ptr = Img.ptr<uchar>(i);
    for (int j = 0; j < nCols; ++j)
    {
      temp = ptr[j];
      nCorTab[temp]++;
    }
  }

  float nSrcSize = static_cast<float>(nRows*nCols);
  float fCorTab[256];
  memset(fCorTab, 0, sizeof(float)*256);

  for (int i = 0; i < 256; ++i)
  {
    //2、计算分布密度
    fCorTab[i] = nCorTab[i]/nSrcSize;
    
    //3、计算累积分布
    if (i > 0)
    {
      fCorTab[i] += fCorTab[i-1];
    }

    //4、计算映射值
    nCorTab[i] = static_cast<int>(255*fCorTab[i] + 0.5);
  }

  //5、映射
  for (int i = 0; i < nRows; ++i)
  {
    ptr = Img.ptr<uchar>(i);
    for (int j = 0; j < nCols; ++j)
    {
      temp = ptr[j];
      ptr[j] = static_cast<uchar>(nCorTab[temp]);
    }
  }

}

void HistNormolize(Mat &cvSrc)
{
  int nRows = cvSrc.rows;
  int nCols = cvSrc.cols;

  int nChls = cvSrc.channels();

  Mat cvImgR(nRows, nCols, CV_8UC(1), Scalar::all(0));
  Mat cvImgG(nRows, nCols, CV_8UC(1), Scalar::all(0));
  Mat cvImgB(nRows, nCols, CV_8UC(1), Scalar::all(0));

  uchar *pSrc;
  uchar *pDsR, *pDsG, *pDsB;

  for (int i = 0; i < nRows; ++i)
  {
    pSrc = cvSrc.ptr<uchar>(i);
    
    pDsR = cvImgR.ptr<uchar>(i);
    pDsG = cvImgG.ptr<uchar>(i);
    pDsB = cvImgB.ptr<uchar>(i);

    for (int j = 0; j < nCols; ++j)
    {
      pDsB[j] = pSrc[j*nChls];
      pDsG[j] = pSrc[j*nChls+1];
      pDsR[j] = pSrc[j*nChls+2];
    }
  }
  
  HistNorSigle(cvImgB);
  HistNorSigle(cvImgG);
  HistNorSigle(cvImgR);
  
  for (int i = 0; i < nRows; ++i)
  {
    pSrc = cvSrc.ptr<uchar>(i);
    
    pDsR = cvImgR.ptr<uchar>(i);
    pDsG = cvImgG.ptr<uchar>(i);
    pDsB = cvImgB.ptr<uchar>(i);

    for (int j = 0; j < nCols; ++j)
    {
      pSrc[j*nChls] = pDsB[j];
      pSrc[j*nChls+1] = pDsG[j];
      pSrc[j*nChls+2] = pDsR[j];
    }
  }

}

int _tmain(int argc, _TCHAR* argv[])
{
  //Mat mInputImage = imread("E:\\openCV\\useMat\\resource\\baidu.png");
  Mat mInputImage = imread("E:\\openCV\\useMat\\resource\\shamo.png");
  imshow("原图", mInputImage);
  
  HistNormolize(mInputImage);
  imshow("增强图", mInputImage);
  waitKey(60000);
  
  return 0;
}      

执行效果

图像处理学习之直方图均衡