您的位置:首页 > 编程语言

灰度图像直方图的规定化的原理及代码实现

2017-11-23 12:44 295 查看
图像增强的首要目标是改善图像, 以使图像更适合于特定应用。 图像增强的方法主要取决于图像希望达到的特定效果, 一般来说, 图像增强的方法分为两大类: 基于图像灰度值统计的方法和基于图像空间频率的方法[1]。 用灰度直方图增强图像对比度是基于图像灰度值统计的一种重要方法, 它以概率论为基础的, 常用的实现算法主要是直方图均衡化和直方图规定化。

直方图均衡化主要用于增强动态范围较小的图像的反差, 基本思想是把原始图的直方图变换为均匀分布的形式, 这样就增强了像素灰度值的动态范围, 从而达到增强图像整体对比度 的 效果。
直方图均衡化的优点是能自动地增强整个图像的对比度, 但它的具体的增强效果不好控制, 处理的结果总是得到全局均衡化的直方图。 实际中有时需要变换直方图使之成为某个需要 的 形状, 从而有选择地增强某个灰度值范围内的对比度或使图像灰度值的分布满足特定的要求,
这时可以采用比较灵活的直方图规定化方法。

基本原理:

直方图规定化的目的就是调整原始图像的直方图使之符合某一规定直方图的要求.设 Pr(r)和Pz(z)分别表示原始灰度图像和目标图像的灰度分布概率密度函数.根据直方图规
定化的特点与要求,应使原始图像的直方图具有Pz(z)所表示的形状。因此.建立Pr(r)和
Pz(z)之间的关系是直方图规定化必须解决的问题。

根据直方图均衡化理论,首先对原始图像进行直方图均衡化处理.即求变换函数



现假定直方图规定化的目标图像已经实现,因此,对于目标图像也采用同样的方法进行均衡化处理,因而有



上式的逆变换为



上式表明,可通过均衡化后的灰度级v求出目标函数的灰度级z。由于对目标图像和原始图像都进行了均衡化处理,因此具有相同的分布密度,即



因而可以用原始图像均衡化以后的灰度级s代表v,即



所以可以依据原始图像均衡化后的图像的灰度值得到目标图像的灰度级z。

直方图的规定划的方法步骤:

1.分别计算原图像与目标图像的累计概率分布

2.分别对原图像与目标图像进行直方图均衡化操作

3.利用组映射关系使原图像直方图按照规定进行变换:

原理的图示:






下面放上源代码:

#include<opencv2\opencv.hpp>
#include<cmath>
#include<iostream>
using namespace cv;
using namespace std;

Mat MyHistMatch(Mat &srcImage, Mat &TargetImage)
{

int nRows = srcImage.rows;
int nCols = srcImage.cols;

int nSrcSumPix[256];
int nTargetSumPix[256];
double nSrcProDis[256];
double nTargetProDis[256];
//int srcGrayLevel[256];
int HistMatchMap[256];
double nSrcSumProDis[256];
double nTargetSumProDis[256];
int EqualizeSrcSumPix[256];
int EqualizeTargetSumPix[256];
int matchFlag = 0;

for (int i = 0; i < 256; i++)
{
nSrcSumPix[i] = 0;
nTargetSumPix[i] = 0;
nSrcProDis[i] = 0.0;
nTargetProDis[i] = 0.0;
//srcGrayLevel[i] = 0;
HistMatchMap[i] = 0;
nSrcSumProDis[i] = 0.0;
nTargetSumProDis[i] = 0.0;
EqualizeSrcSumPix[i] = 0;
EqualizeTargetSumPix[i] = 0;
}

for (int i = 0; i < nRows; i++)
{
for (int j = 0; j < nCols; j++)
{
nSrcSumPix[(int)srcImage.at<uchar>(i, j)]++;
nTargetSumPix[(int)TargetImage.at<uchar>(i, j)]++;
}
}

for (int i = 0; i < 256; i++)
{
nSrcProDis[i] = (double)nSrcSumPix[i] / (nRows * nCols);
nTargetProDis[i] = (double)nTargetSumPix[i] / (nRows * nCols);
}

nSrcSumProDis[0] = nSrcProDis[0];
nTargetSumProDis[0] = nTargetProDis[0];

for (int i = 1; i < 256; i++)
{
nSrcSumProDis[i] = nSrcSumProDis[i - 1] + nSrcProDis[i];
nTargetSumProDis[i] = nTargetSumProDis[i - 1] + nTargetProDis[i];
}

for (int i = 0; i < 256; i++)
{
EqualizeSrcSumPix[i] = cvRound((double)nSrcSumProDis[i] * 255);
EqualizeTargetSumPix[i] = cvRound((double)nTargetSumProDis[i] * 255);
}

for (int i = 0; i < 256; i++)
{
cout << "EqualizeSrcSumPix[" << i << "]=" << EqualizeSrcSumPix[i]<<"  " << "EqualizeTargetSumPix[" << i << "]=" << EqualizeTargetSumPix[i]<< endl;
}

for (int i = 0; i < 256; i++)
{
int minMatchPara = 20;
for (int j = 0; j < 256; j++)
{

if (minMatchPara > abs(EqualizeSrcSumPix[i] - EqualizeTargetSumPix[j]))
{
minMatchPara = abs(EqualizeSrcSumPix[i] - EqualizeTargetSumPix[j]);
matchFlag = j;
}
}
HistMatchMap[i] = matchFlag;
}

Mat resultImage(nRows, nCols, srcImage.type());
for (int i = 0; i < nRows; i++)
{

for (int j = 0; j < nCols; j++)
{

resultImage.at<uchar>(i, j) = HistMatchMap[(int)srcImage.at<uchar>(i, j)];
}
}
return resultImage;
}
int main()
{
Mat srcImage = imread("flower.jpg");
Mat dstImage = imread("sea.jpg");
if (!srcImage.data || !dstImage.data)
{
printf("could not load images...\n");
return -1;
}

resize(dstImage, dstImage, Size(srcImage.rows, srcImage.cols), 0, 0, CV_INTER_LINEAR);
Mat srcGray, dstGray;
cvtColor(srcImage, srcGray, CV_BGR2GRAY);
cvtColor(dstImage, dstGray, CV_BGR2GRAY);
imshow("srcGray", srcGray);
imshow("dstGray", dstGray);
Mat resultImage = MyHistMatch(srcGray,dstGray);
imshow("res", resultImage);
waitKey(0);
return 0;
}


原图:



目标图:



效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐