直方图均衡化程序实现

时间:2021-05-21 02:04:31



  原理参见网址:

   http://zh.wikipedia.org/wiki/%E7%9B%B4%E6%96%B9%E5%9B%BE%E5%9D%87%E8%A1%A1%E5%8C%96

  首先需要先配置好OpenCV的开发环境,直方图均衡化程序如下。

程序如下:

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

using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{

//cv::Mat src = cv::imread(argv[1], 0);
cv::Mat src = cv::imread("pic.bmp", 0); //=0 Return a grayscale image. >0 Return a 3-channel color image
int height = src.rows;
int width = src.cols;

int v_min = 1000;
int v_max = -1;

/*The method returns a Matlab-style zero array initializer and used to quickly form a constant array as a function parameter,
part of a matrix expression, or as a matrix initializer*/
cv::Mat p = cv::Mat::zeros(256, 1, CV_32F); //Mat::zeros(int rows, int cols, int type) CV_32F: 32位浮点型

for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
int value = src.at<uchar>(i, j); //遍历取各个像素的灰度值
if(value < v_min)
v_min = value;
if(value > v_max)
v_max = value;
p.at<float>(value, 0) += 1; //统计各个灰度级出现的次数
}
}
std::cout << v_min << ' ' << v_max << std::endl;

p /= (height*width); //归一化: 计算矩阵p各个元素与总像素的比值


cv::Mat c = cv::Mat::zeros(256, 1, CV_32F); //0-255 代表256个灰度值
for(int i = 0; i < 256; i++)
{
float p_sum = 0;
for(int j = 0; j <= i; j++)
p_sum += p.at<float>(j, 0); //直方图均衡化的作用是累计
c.at<float>(i, 0) = p_sum;
}


cv::Mat y = cv::Mat::zeros(256, 1, CV_32F);
for(int i = 0; i < 256; i++)
{
y.at<float>(i, 0) = c.at<float>(i, 0) * (v_max - v_min) + v_min; //将0-1的范围扩展到v_min与v_max范围之间
}


cv::Mat dst = src.clone(); //对原图像矩阵做拷贝
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
int value = src.at<uchar>(i, j);

dst.at<uchar>(i, j) = (int)(y.at<float>(value, 0) + 0.5); //对值取4舍5入
}
}

cv::imwrite("dst.bmp", dst);
return 0;
}