【opencv】之直方图的应用
来源:互联网 发布:dnf制裁秒淘宝能解么 编辑:程序博客网 时间:2024/05/22 09:50
这一篇我们来学习下直方图的应用,主要有直方图的拉伸、直方图均衡化以及利用直方图寻找相似图像。
1. 直方图拉伸
图像对比度增强分为两类:直接对比度增强和间接对比度增强。直方图拉伸和直方图均衡化是两种最常用的间接对比度增强方法。直方图拉伸是通过对比度拉伸对直方图进行调整,从而扩大“前景”和背景灰度的差别,以达到增强对比度的目的。
公式如下:
设f(x,y)为输入图像,则
最小灰度级A=min[f(x,y)]
最大灰度级B=max[f(x,y)]
将A和B分别线性映射到0和255,最终得到的图像为: g(x,y)=(255/(B-A))[f(x,y)-A]
以下为代码实现:
/*------------------------------------【程序说明】-------------------------------------描述:直方图拉伸2015/10/16 by czp 2015/10/18 【修改】由于现有的图片像素区间在【0,255】,无法进行拉伸,故进行反向运算,得到sky-lancer1.jpg---------------------------------------------------------------------------------------*//*--------------------------------【程序头文件部分】----------------------------------描述:包含程序所依赖的文件--------------------------------------------------------------------------------------*/#include <iostream>#include "highgui.h"#include <opencv2/opencv.hpp>/*--------------------------------【命名空间部分】-------------------------------------描述:包含程序所使用的命名空间--------------------------------------------------------------------------------------*/using namespace cv;using namespace std;/*--------------------------------【类Histogram1D】-------------------------------------描述:计算一维直方图--------------------------------------------------------------------------------------*/class Histogram1D{private:int histSize[1];//项的数量float hranges[2];const float*ranges[1];int channels[1];public:Histogram1D(){histSize[0] = 256;hranges[0] = 0.0;hranges[1] = 255.0;ranges[0] = hranges;channels[0] = 0;}MatND getHistogram(const Mat &image){MatND hist;calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);return hist;}Mat getHistogramImage(const Mat &image){MatND hist = getHistogram(image);double maxVal = 0;double minVal = 0;minMaxLoc(hist, &minVal, &maxVal, 0, 0);Mat histImg(histSize[0], histSize[0], CV_8U, Scalar(255));int hpt = static_cast<int>(0.9*histSize[0]);for (int h = 0; h < histSize[0]; h++){float binVal = hist.at<float>(h);int intensity = static_cast<int>(binVal*hpt / maxVal);line(histImg, Point(h, histSize[0]), Point(h, histSize[0] - intensity), Scalar::all(0));}return histImg;}};/*--------------------------------【main()函数】---------------------------------------描述:控制台应用程序入口--------------------------------------------------------------------------------------*/int main(){int PixMax_array[3] = { 0, 0, 0 }, PixMin_array[3] = { 255, 255, 255 }; //存储像素的最大值和最小值float DifferenceOfMaxMin[3];int i, j, nl, nc;Mat srcImg = imread("sky-lancer1.jpg", 1); //读入原图像,这里只研究彩色图像if (!srcImg.data){ printf("读取图片错误!!\n"); return false; }Mat dstImg = srcImg.clone();//遍历图像,寻找最大和最小值nl = dstImg.rows; //行数nc = dstImg.cols; //列数for (i = 0; i < nl; i++){for (j = 0; j < nc; j++){if (dstImg.at<Vec3b>(i, j)[0] < PixMin_array[0]){ PixMin_array[0] = dstImg.at<Vec3b>(i, j)[0]; }if (dstImg.at<Vec3b>(i, j)[1] < PixMin_array[1]){ PixMin_array[1] = dstImg.at<Vec3b>(i, j)[1]; }if (dstImg.at<Vec3b>(i, j)[2] < PixMin_array[2]){ PixMin_array[2] = dstImg.at<Vec3b>(i, j)[2]; }if (dstImg.at<Vec3b>(i, j)[0] > PixMax_array[0]){ PixMax_array[0] = dstImg.at<Vec3b>(i, j)[0]; }if (dstImg.at<Vec3b>(i, j)[1] > PixMax_array[1]){ PixMax_array[1] = dstImg.at<Vec3b>(i, j)[1]; }if (dstImg.at<Vec3b>(i, j)[2] > PixMax_array[2]){ PixMax_array[2] = dstImg.at<Vec3b>(i, j)[2]; }}}//遍历图像,进行直方图拉伸for (i = 0; i < 3; i++){DifferenceOfMaxMin[i] = 255.0/(float)(PixMax_array[i] - PixMin_array[i]);}for (i = 0; i < nl; i++){for (j = 0; j < nc; j++){dstImg.at<Vec3b>(i, j)[0] = (int)(DifferenceOfMaxMin[0] * (dstImg.at<Vec3b>(i, j)[0] - PixMin_array[0]));dstImg.at<Vec3b>(i, j)[1] = (int)(DifferenceOfMaxMin[1] * (dstImg.at<Vec3b>(i, j)[1] - PixMin_array[1]));dstImg.at<Vec3b>(i, j)[2] = (int)(DifferenceOfMaxMin[2] * (dstImg.at<Vec3b>(i, j)[2] - PixMin_array[2]));}} namedWindow("srcImg");namedWindow("dstImg");imshow("srcImg", srcImg);waitKey(5000);imshow("dstImg", dstImg);waitKey(5000);//查看各个通道的直方图是否有变化(以通道0为例子)vector<Mat> mv,nv;split(srcImg,mv);split(dstImg, nv);Histogram1D hm, hn;namedWindow("Histogram_m");imshow("Histogram_m", hm.getHistogramImage(mv.at(0)));waitKey(5000);namedWindow("Histogram_n");imshow("Histogram_n", hn.getHistogramImage(nv.at(0)));waitKey(5000);}效果图:
参考文章:http://blog.csdn.net/guoyk1990/article/details/8104130
2.直方图均衡化
如果一幅图像的像素占有很多的灰度级而且分布均匀,那么这样的图像往往有高对比度和多变的灰度色调。直方图均衡化就是为了达到这种效果。它的基本思想是对图像中像素个数多的灰度级进行展宽,而对图像中像素个数少的灰度进行压缩,从而扩展像原取值的动态范围,提高了对比度和灰度色调的变化,使图像更加清晰。【百度百科】
简单的说,均衡化就是“把一个分布(给定的直方图)映射到另一个分布(一个更宽更统一的强度值分布),所以强度值分布会在整个范围内展开”。直方图均衡化是通过累计分布函数来实现的。
详细的原理参见:直方图原理OpenCV提供了一个简单易用的函数来执行直方图均衡化。
cv::equalizeHist(Mat &srcImage,Mat &dstImage);
其中输入输出均为单通道图像。
代码及其实现:
//------------------------------------【程序功能】-----------------------------------------------// 描述:直方图均衡化//-----------------------------------------------------------------------------------------------//----------------------------------【头文件包含部分】-------------------------------------------// 描述:包含程序所依赖的文件//-----------------------------------------------------------------------------------------------#include <iostream>#include "highgui.h"#include <opencv2/opencv.hpp>//-----------------------------------【命名空间声明】--------------------------------------------// 描述:包含程序所使用的命名空间//-----------------------------------------------------------------------------------------------using namespace cv;using namespace std;// 定义直方图的类class Histogram1D{private:int histSize[1];//项的数量float hranges[2];const float*ranges[1];int channels[1];public:Histogram1D(){histSize[0] = 256;hranges[0] = 0.0;hranges[1] = 255.0;ranges[0] = hranges;channels[0] = 0;}MatND getHistogram(const Mat &image){MatND hist;calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);return hist;}Mat getHistogramImage(const Mat &image){MatND hist = getHistogram(image);double maxVal = 0;double minVal = 0;minMaxLoc(hist, &minVal, &maxVal, 0, 0);Mat histImg(histSize[0], histSize[0], CV_8U, Scalar(255));int hpt = static_cast<int>(0.9*histSize[0]);for (int h = 0; h < histSize[0]; h++){float binVal = hist.at<float>(h);int intensity = static_cast<int>(binVal*hpt / maxVal);line(histImg, Point(h, histSize[0]), Point(h, histSize[0] - intensity), Scalar::all(0));}return histImg;}};//-------------------------------------【main()函数】-----------------------------------------------//描述:控制台应用程序的入口//--------------------------------------------------------------------------------------------------int main(){Mat srcImage = imread("sky-lancer.jpg", 0), dstImage; //读入灰度图像if (!srcImage.data) {printf("读取图像错误!"); return false;}equalizeHist(srcImage, dstImage);//处理前和处理后的图像对比namedWindow("srcImage");imshow("srcImage", srcImage);waitKey(5000);namedWindow("dstImage");imshow("dstImage", dstImage);waitKey(5000);//处理前和处理后的直方图对比Histogram1D h;namedWindow("srcHistogram");/*split(srcImage, nv);*/imshow("srcHistogram", h.getHistogramImage(srcImage));waitKey(5000);namedWindow("EqualizationOfHistogram");imshow("EqualizationOfHistogram", h.getHistogramImage(dstImage));waitKey(5000);}
- 【opencv】之直方图的应用
- opencv直方图的应用
- OpenCV成长之路(5):图像直方图的应用
- OpenCV成长之路(5):图像直方图的应用
- OpenCV成长之路(5):图像直方图的应用
- OpenCV学习之直方图统计应用【转】
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- leetcode系列(35)Roman to Integer & Integer to Roman
- centOS下mongodb的安装
- Javassist介绍
- web服务器是如何工作的
- 第7讲 项目1----求正差值
- 【opencv】之直方图的应用
- deep learning lecture
- 写这些东西目的在于温故而知新
- Android性能优化典范第2季
- OpenCV—图像分割中的分水岭算法原理与应用
- Spark: FetchFailedException: unable to create channel..
- LeetCode 16 3Sum Closest(最接近的3个数的和)
- 生成不同随机数
- I/O failure during classpath scanning in spring MVC