直方图均衡化的 C++ 实现(基于 openCV)
这是数字图像处理课的大作业,完成于 2013/06/17,需要调用 openCV 库,完整源码和报告如下:
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <string> /* 灰度级结点 */
typedef struct {
int pixels; // 灰度级对应像素个数
float rate; // 像素比例
float accuRate; // 累计像素比例
int map; // 到均衡化后的灰度级的映射
} levNode; void histeqGray(IplImage* pGray, int levels, int argc);
IplImage* histImage(IplImage* pSrc, int histWidth, int histHeight, int nScale); int main(int argc, char* argv[])
{
int levels;
std::string imgName, inTmp;
if (argc == ) {
levels = atoi(argv[]);
imgName = argv[];
}
else if (argc == )
imgName = argv[];
else {
printf("usage: histeq [levels] image_name \n");
return -;
} IplImage* pSrc = cvLoadImage(imgName.c_str(), CV_LOAD_IMAGE_UNCHANGED);
int channel = pSrc->nChannels; IplImage* pChnl[] = { NULL }; for (int i = ; i < channel; ++i)
pChnl[i] = cvCreateImage(cvGetSize(pSrc), pSrc->depth, ); cvSplit(pSrc, pChnl[], pChnl[], pChnl[], pChnl[]); for (int i = ; i < channel; ++i)
histeqGray(pChnl[i], levels, argc); IplImage* pEql = cvCreateImage(cvGetSize(pSrc), pChnl[]->depth, pSrc->nChannels); cvMerge(pChnl[], pChnl[], pChnl[], pChnl[], pEql); inTmp = imgName + "_Eql.jpg";
cvSaveImage(inTmp.c_str(), pEql); //cvNamedWindow(imgName.c_str(), CV_WINDOW_AUTOSIZE);
cvShowImage(imgName.c_str(), pSrc);
//cvNamedWindow(inTmp.c_str(), CV_WINDOW_AUTOSIZE);
cvShowImage(inTmp.c_str(), pEql); IplImage* pSrcGray = cvCreateImage(cvGetSize(pSrc), IPL_DEPTH_8U, );
if (pSrc->nChannels == )
cvCvtColor(pSrc, pSrcGray, CV_BGR2GRAY);
else
cvCopyImage(pSrc, pSrcGray);
IplImage* pEqlGray = cvCreateImage(cvGetSize(pEql), IPL_DEPTH_8U, );
if (pSrc->nChannels == )
cvCvtColor(pEql, pEqlGray, CV_BGR2GRAY);
else
cvCopyImage(pEql, pEqlGray);
imgName += "_Hist.jpg";
inTmp += "_Hist.jpg";
int nScale = ;
int histWidth = /*pSrc->width * nScale*/ * nScale;
int histHeight = /*pSrc->height*/;
IplImage* pSrcGrayHist = histImage(pSrcGray, histWidth, histHeight, nScale);
IplImage* pEqlGrayHist = histImage(pEqlGray, histWidth, histHeight, nScale);
cvSaveImage(imgName.c_str(), pSrcGrayHist);
cvSaveImage(inTmp.c_str(), pEqlGrayHist);
cvShowImage(imgName.c_str(), pSrcGrayHist);
cvShowImage(inTmp.c_str(), pEqlGrayHist); cvWaitKey(); cvReleaseImage(&pEql);
cvReleaseImage(&pEqlGray);
for (int i = ; i < channel; ++i)
cvReleaseImage(&pChnl[i]);
cvReleaseImage(&pSrc);
cvReleaseImage(&pSrcGray); return ;
} /*
* 直方图均衡化函数
* pGray为输入的灰度图
* levels为均衡化的灰度级
*/
void histeqGray(IplImage* pGray, int levels, int argc)
{
int depth = pGray->depth;
printf("%d \n", depth);
int width = pGray->width;
int height = pGray->height;
int sumPixels = width * height; // 总像素数
printf("%d \n", sumPixels);
int values = static_cast<int>(pow((float), depth)); // 根据图像深度计算像素取值范围
if (argc == ) levels = values;
printf("%d \n", levels); int outDepth;
/*if (levels <= 2)
outDepth = 1;
else*/ if (levels <= )
outDepth = ;
else if (levels <= )
outDepth = ; assert(levels <= values);
int intervals = values / levels; // 根据像素取值范围和灰度级求每个灰度级的像素间隔
levNode* levNodes = (levNode*)calloc(levels, sizeof(levNode)); // 生成灰度结点
//for (int lev = 0; lev < levels; ++lev) printf("%d \n", levNodes[lev].pixels);
//char* pValues = pGray->imageData; /* 统计每个灰度级的像素个数 */
for (int y = ; y < height; ++y)
for (int x = ; x < width; ++x) {
CvScalar scal = cvGet2D(pGray, y, x);
int val = (int)scal.val[];
//printf("%d \n", val);
for (int lev = ; lev < levels; ++lev) {
if ( val >= intervals*lev && val < intervals*(lev+)) {
++levNodes[lev].pixels; break;
}
}
} int sum = ;
for (int lev = ; lev < levels; ++lev)
sum += levNodes[lev].pixels;
printf("%d \n", sum); /* 计算每个灰度级像素比例和累计比例 */
levNodes[].accuRate = levNodes[].rate = levNodes[].pixels / (float)sumPixels;
levNodes[].map = (int)(levNodes[].accuRate * (levels - ) + 0.5);
printf("%d \n", levNodes[].pixels);
for (int lev = ; lev < levels; ++lev) {
levNodes[lev].rate = levNodes[lev].pixels / (float)sumPixels;
levNodes[lev].accuRate = levNodes[lev-].accuRate + levNodes[lev].rate;
levNodes[lev].map = (int)(levNodes[lev].accuRate * (levels - ) + 0.5);
}
printf("%f \n", levNodes[levels-].accuRate); /* 生成均衡化后的图像 */
for (int y = ; y < height; ++y)
for (int x = ; x < width; ++x) {
CvScalar scal = cvGet2D(pGray, y, x);
int val = (int)scal.val[];
//printf("%d \n", val);
for (int lev = ; lev < levels; ++lev) {
if (val >= intervals*lev && val < intervals*(lev+)) {
scal.val[] = levNodes[lev].map;
//printf("%f \n", scal.val[0]);
cvSet2D(pGray, y, x, scal);
break;
}
}
}
pGray->depth = outDepth; free(levNodes);
} /*
* 绘制直方图函数
*/
IplImage* histImage(IplImage* pSrc, int histWidth, int histHeight, int nScale)
{
int histSize = static_cast<int>(pow((float), pSrc->depth));
CvHistogram* pHist = cvCreateHist(/*pSrc->nChannels*/, &histSize, CV_HIST_ARRAY);
cvCalcHist(&pSrc, pHist); IplImage* pHistImg = cvCreateImage(cvSize(histWidth, histHeight), IPL_DEPTH_8U, );
cvRectangle(pHistImg, cvPoint(,), cvPoint(pHistImg->width,pHistImg->height), CV_RGB(,,), CV_FILLED); float histMaxVal = ;
cvGetMinMaxHistValue(pHist, , &histMaxVal); for(int i = ; i < histSize; i++)
{
float histValue= cvQueryHistValue_1D(pHist, i); // 像素为i的直方块大小
int nRealHeight = cvRound((histValue / histMaxVal) * histHeight); // 要绘制的高度
cvRectangle(pHistImg,
cvPoint(i*nScale, histHeight - ),
cvPoint((i + )*nScale - , histHeight - nRealHeight),
cvScalar(i),
CV_FILLED
);
}
//cvFillConvexPoly cvReleaseHist(&pHist);
return pHistImg;
}
一、直方图均衡化概述
直方图均衡化是一种图像增强方法,其基本思想是把给定图像的直方图分布改造成均匀分布的直方图,从而增加象素灰度值的动态范围,达到增强图像整体对比度的效果。由信息学的理论来解释,具有最大熵(信息量)的图像为均衡化图像。
直方图均衡化可表示为:,t为某个象素变换后的灰度级,s为该象素变换前的灰度级。
该灰度变换函数应满足如下两个条件:
1)f(s)在范围内是单值递增函数;
2)对有
条件1:保证原图各灰度级在变换后仍保持从黑到白(或从白到黑)的排列顺序;
条件2:保证变换前后灰度值动态范围的一致性。
可以证明累积分布函数(cumulative distribution function CDF)满足上述两个条件并能将s的分布转换为t的均匀分布。
事实上,s的CDF就是原始图的累积直方图,即:
其中、
、k=0,1,…,L-1
根据这个公式,可以直接算出直方图均衡化后各象素的灰度值。需要取整,以满足数字图象的要求。
二、算法步骤
步骤 |
运算 |
1 |
列出原始图灰度级 |
2 |
统计原始直方图各灰度级象素数 |
3 |
计算原始直方图(像素比例) |
4 |
计算累积直方图 |
5 |
取整 |
6 |
确定映射对应关系( |
7 |
计算新的直方图 |
三、算法测试
1、灰度图
2、彩色图
四、结果分析
(1)对于灰度图和彩色图,算法结果都不错,直方图显示像素分布很广、很平均。
(2)直方图均衡化的优点:自动增强整个图像的对比度。
(3)直方图均衡化的不足:具体增强效果不易控制,处理的结果总是得到全局均衡化的直方图。
直方图均衡化的 C++ 实现(基于 openCV)的更多相关文章
- 图像增强 | CLAHE 限制对比度自适应直方图均衡化
1 基本概述 CLAHE是一个比较有意思的图像增强的方法,主要用在医学图像上面.之前的比赛中,用到了这个,但是对其算法原理不甚了解.在这里做一个复盘. CLAHE起到的作用简单来说就是增强图像的对比度 ...
- 【图像增强】CLAHE 限制对比度自适应直方图均衡化
文章目录: 目录 1 基本概述 2 竞赛中的CLAHE实现 3 openCV绘制直方图 4 对比度Contrast 5 Contrast Stretching 6 Histogram Equaliza ...
- OpenCV图像增强算法实现(直方图均衡化、拉普拉斯、Log、Gamma)
http://blog.csdn.net/dcrmg/article/details/53677739 1. 基于直方图均衡化的图像增强 直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶 ...
- opencv 彩色图像亮度、对比度调节 直方图均衡化
直接上代码: #include <Windows.h> #include <iostream>// for stand I/O #include <string> ...
- OpenCV——直方图均衡化(用于图像增强)
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespac ...
- 【图像处理】基于OpenCV底层实现的直方图匹配
image processing 系列: [图像处理]图片旋转 [图像处理]高斯滤波.中值滤波.均值滤波 直方图匹配算法.又称直方图规定化.简单说.就是依据某函数.或者另外一张图片的引导,使得原图改变 ...
- opencv图像直方图均衡化及其原理
直方图均衡化是什么有什么用 先说什么是直方图均衡化,通俗的说,以灰度图为例,原图的某一个像素为x,经过某个函数变为y.形成新的图.新的图的灰度值的分布是均匀的,这个过程就叫直方图均衡化. 图像直方图均 ...
- opencv 5 图像转换(3 重映射 仿射变换 直方图均衡化)
重映射 实现重映射(remap函数) 基础示例程序:基本重映射 //---------------------------------[头文件.命名空间包含部分]------------------- ...
- opencv —— equalizeHist 直方图均衡化实现对比度增强
直方图均匀化简介 从这张未经处理的灰度图可以看出,其灰度集中在非常小的一个范围内.这就导致了图片的强弱对比不强烈. 直方图均衡化的目的,就是把原始的直方图变换为在整个灰度范围(0~255)内均匀分布的 ...
随机推荐
- git github usage
以gerrit-trigger-plugin为例,下面的链接都是从相应页面上直接拷贝的. 法一:不用github的账号,打开这个库在github上的主页,运行下面命令即可 read only 运行命令 ...
- js验证表单大全2
屏蔽右键 很酷 oncontextmenu="return false" ondragstart="return false"onselectstart=&q ...
- python——random模块
用法示例: import random # 1)随机小数 print(random.random()) # 获取大于0且小于1 之间的小数 random.random() print(random.u ...
- python函数补充
一 作用域 作用域介绍 python中的作用域分4种情况: L:local,局部作用域,即函数中定义的变量: E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局 ...
- MySql存储过程、函数
存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...
- Java基础—运算符(转载)
转载自:Java运算符 计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操纵变量.我们可以把运算符分成以下几组: 算术运算符 关系运算符 位运算符 逻辑运 ...
- 【整理学习Hadoop】H D F S 一个分布式文件系统
Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时,它和其他的分布式文件系统的区别 ...
- win10 chrome 调试
下载NPAPI版本的flash player: http://www.adobe.com/support/flashplayer/debug_downloads.html#fp13 禁 ...
- 谷歌机器学习速成课程---降低损失 (Reducing Loss):随机梯度下降法
在梯度下降法中,批量指的是用于在单次迭代中计算梯度的样本总数.到目前为止,我们一直假定批量是指整个数据集.就 Google 的规模而言,数据集通常包含数十亿甚至数千亿个样本.此外,Google 数据集 ...
- Python 9 sqlalchemy ORM
一.ORM介绍: orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型 ...