1  图像直方图

1.1  定义

  统计各个像素值,在整幅图像中出现次数的一个分布函数。

      

1.2  标准化

$\quad p_r(r_k) = \frac{n_k}{MN} \qquad k = 0, 1, 2, ..., L -1 $

  $r_{k}$ - 第 k 个像素灰度值;  $n_{k}$ - 像素灰度值为 rk 的像素数目;

  MN - 图像中总的像素个数;  [0, L-1] - 像素灰度值的范围

1.3  直方图均衡化

1.3.1  定义 

直方图均衡化,是将给定图像的直方图改造成均匀分布的直方图,从而扩大像素灰度值的动态范围,达到增强图像对比度的效果。

$\quad s_k = \frac{(L - 1)}{MN} \sum\limits_{j=0}^k n_j \qquad k = 0, 1, 2, ..., L - 1 $

       

       

1.3.2  实例

一幅灰度值范围是[0, 7],64行64列的数字图像,其灰度分布如下表所示,求直方图均衡化之后的灰度分布。

  r(k)  n(k)  P(rk)
 r(0) = 0  790   0.19
 r(1) = 1  1023  0.25
 r(2) = 2  850  0.21
 r(3) = 3  656  0.16
 r(4) = 4  329  0.08
 r(5) = 5  245  0.06
 r(6) = 6  122  0.03
 r(7) = 7  81  0.02

根据上述公式得, s(0)=1.33≈1,s(1)=3.08≈3,s(2)≈5,s(3)≈6,s(4)≈6,s(5)≈7,s(6)≈7,s(7)≈7

因为 r(k) -> s(k),所以 s(0)=1 对应有790个像素值。因为r(3), r(4) 分别对应 s(3), s(4),且 s(3)=s(4)=6,

故像素值为6的像素数为 (656+329)个,同理可计算像素值为7的像素数。

将不同像素值对应的的像素数除以MN(图像的像素总数),便得到均衡化之后的灰度直方图,如下所示:

2  四个参数

  H1 和 H2 为两个待比较的直方图。1) 和 2) 的值越大,二者越匹配;而 3) 和 4) 的值越小,两者越匹配。

1) Correlation

2) Intersection

3) Chi-square

4) Bhattacharyya distance

3  OpenCV中的函数

3.1  equalizeHist

void equalizeHist (   InputArray src,  // 输入图像   OutputArray dst  // 输出图像);

源码:

void cv::equalizeHist( InputArray _src, OutputArray _dst )
{CV_Assert( _src.type() == CV_8UC1 );if (_src.empty())return;CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),ocl_equalizeHist(_src, _dst))Mat src = _src.getMat();_dst.create( src.size(), src.type() );Mat dst = _dst.getMat();Mutex histogramLockInstance;const int hist_sz = EqualizeHistCalcHist_Invoker::HIST_SZ;int hist[hist_sz] = {0,};int lut[hist_sz];EqualizeHistCalcHist_Invoker calcBody(src, hist, &histogramLockInstance);EqualizeHistLut_Invoker      lutBody(src, dst, lut);cv::Range heightRange(0, src.rows);if(EqualizeHistCalcHist_Invoker::isWorthParallel(src))parallel_for_(heightRange, calcBody);elsecalcBody(heightRange);int i = 0;while (!hist[i]) ++i;int total = (int)src.total();if (hist[i] == total){dst.setTo(i);return;}float scale = (hist_sz - 1.f)/(total - hist[i]);int sum = 0;for (lut[i++] = 0; i < hist_sz; ++i){sum += hist[i];lut[i] = saturate_cast<uchar>(sum * scale);}if(EqualizeHistLut_Invoker::isWorthParallel(src))parallel_for_(heightRange, lutBody);elselutBody(heightRange);
}

View Code

3.2  calcHist

void cv::calcHist(     const Mat *      images,int              nimages,const int *      channels,InputArray      mask,OutputArray      hist,int              dims,const int *      histSize,const float **  ranges,bool              uniform = true,bool              accumulate = false )     

View Code

3.3  compareHist

double cv::compareHist (     InputArray      H1,InputArray      H2,int                 method
)  

View Code

4  实例

4.1  直方图计算

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv2/imgproc/imgproc.hpp"using namespace cv;int main( int, char** argv )
{Mat src, dst;// 1) Load imagesrc = imread("left.png");if(src.empty()) {return -1;}// 2)  Separate the image in 3 places ( B, G and R )std::vector<Mat> bgr_planes;split( src, bgr_planes );// 3)  Establish the number of binsint histSize = 256;// 4)  Set the ranges (for B,G,R)float range[] = { 0, 256 } ;const float* histRange = { range };bool uniform = true;bool accumulate = false;Mat b_hist, g_hist, r_hist;// 5)  Compute the histogramscalcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );// 6) Draw the histograms for B, G and Rint hist_w = 512;int hist_h = 400;int bin_w = cvRound( (double) hist_w/histSize );Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );// 7) Normalize the result to [ 0, histImage.rows ]normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );// 8) Draw for each channelfor( int i = 1; i < histSize; i++ ){line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),Scalar( 255, 0, 0), 2, 8, 0  );line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),Scalar( 0, 255, 0), 2, 8, 0  );line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),Scalar( 0, 0, 255), 2, 8, 0  );}// 9) Displayimshow("calcHist Demo", histImage );waitKey(0);
}

4.2  直方图均衡化

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>using namespace cv;
using namespace std;int main( int, char** argv )
{Mat src, dst;const char* source_window = "Source image";const char* equalized_window = "Equalized Image";// Load imagesrc = imread( argv[1], 1 );if( src.empty() ){ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;return -1;}// Convert to grayscale
  cvtColor( src, src, COLOR_BGR2GRAY );// Apply Histogram Equalization
  equalizeHist( src, dst );// Display results
  namedWindow( source_window, WINDOW_AUTOSIZE );namedWindow( equalized_window, WINDOW_AUTOSIZE );imshow( source_window, src );imshow( equalized_window, dst );// Wait until user exits the programwaitKey(0);return 0;}

View Code

4.3  直方图比较

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>using namespace std;
using namespace cv;/*** @function main*/
int main( int argc, char** argv )
{Mat src_base, hsv_base;Mat src_test1, hsv_test1;Mat src_test2, hsv_test2;Mat hsv_half_down;/// Load three images with different environment settingsif( argc < 4 ){printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_setting1> <image_settings2>\n");return -1;}src_base = imread( argv[1], 1 );src_test1 = imread( argv[2], 1 );src_test2 = imread( argv[3], 1 );/// Convert to HSV
    cvtColor( src_base, hsv_base, COLOR_BGR2HSV );cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV );cvtColor( src_test2, hsv_test2, COLOR_BGR2HSV );hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) );/// Using 50 bins for hue and 60 for saturationint h_bins = 50; int s_bins = 60;int histSize[] = { h_bins, s_bins };// hue varies from 0 to 179, saturation from 0 to 255float h_ranges[] = { 0, 180 };float s_ranges[] = { 0, 256 };const float* ranges[] = { h_ranges, s_ranges };// Use the o-th and 1-st channelsint channels[] = { 0, 1 };/// Histograms
    MatND hist_base;MatND hist_half_down;MatND hist_test1;MatND hist_test2;/// Calculate the histograms for the HSV imagescalcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() );calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false );normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() );calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false );normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() );calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false );normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );/// Apply the histogram comparison methodsfor( int i = 0; i < 4; i++ ){int compare_method = i;double base_base = compareHist( hist_base, hist_base, compare_method );double base_half = compareHist( hist_base, hist_half_down, compare_method );double base_test1 = compareHist( hist_base, hist_test1, compare_method );double base_test2 = compareHist( hist_base, hist_test2, compare_method );printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 );}printf( "Done \n" );return 0;
}

View Code

参考资料

<Digital Image Processing> 3rd

OpenCV Tutorials / Image Processing (imgproc module) / Histogram Calculation

转载于:https://www.cnblogs.com/xinxue/p/5290660.html

OpenCV 之 直方图处理相关推荐

  1. Python,OpenCV进行直方图反投影

    Python,OpenCV进行直方图反投影 1. 效果图 2. 源码 参考 这篇博客将介绍Python,OpenCV中的直方图反投影.直方图反投影用于图像分割或在图像中查找感兴趣的对象. 简单地说,它 ...

  2. OpenCV中直方图反向投影算法详解与实现

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达本文转自:opencv学堂 一:直方图交叉 OpenCV中直方图反向 ...

  3. OpenCV equalizeHist直方图均衡化的实例(附完整代码)

    OpenCV equalizeHist直方图均衡化的实例 OpenCV equalizeHist直方图均衡化的实例 OpenCV equalizeHist直方图均衡化的实例 #include &quo ...

  4. OpenCV imgproc直方图的实例(附完整代码)

    OpenCV imgproc直方图的实例 OpenCV imgproc直方图的实例 OpenCV imgproc直方图的实例 #include <opencv2/imgproc.hpp> ...

  5. OpenCV梯度直方图HOG的实例(附完整代码)

    OpenCV梯度直方图HOG的实例 OpenCV梯度直方图HOG的实例 OpenCV梯度直方图HOG的实例 #include "opencv2/imgproc.hpp" #incl ...

  6. OpenCV中直方图对比

    OpenCV中直方图对比 对于两幅图片先求得其直方图然后在对两个直方图进行比较.而两幅直方图相似度的标准为d(H1,H2)\color{#f00}d(H1,H2)d(H1,H2),而对于该值的计算有四 ...

  7. OpenCV中直方图的计算和绘制

    OpenCV中直方图的计算和绘制 主要记录一下几个关键的API: cvRound(输入一个浮点数 );//返回一个整型数,取整的方法为四舍五入 split(输入多通道图像,数组或者vector变量. ...

  8. OpenCV中直方图均衡化

    OpenCV中直方图均衡化 首先知道直方图是个什么鬼?在一幅图像中,直方图所体现的是每个像素值在所有的像素中所占的比例:例值为127的像素点的个数/图像总的像素点的个数\color{#f00}值为12 ...

  9. Python+OpenCV:直方图反向投影(Histogram Backprojection)

    Python+OpenCV:直方图反向投影(Histogram Backprojection) Algorithm in Numpy 1. First we need to calculate the ...

  10. Python+OpenCV:直方图均衡化(Histogram Equalization)

    Python+OpenCV:直方图均衡化(Histogram Equalization) ####################################################### ...

最新文章

  1. java 注解类说明
  2. 【Android】Android中使用JNI调用底层C++代码
  3. 【数据挖掘】贝叶斯公式应用 拼写纠正示例分析 ( 先验概率 | 似然概率 | 后验概率 )
  4. mysql允许远程访问
  5. 微信小游戏背后的技术优化
  6. json套json_JSON –拯救杰克逊
  7. 两分钟让你变成jar包制作高手
  8. discuz php 扩展环境 不支持,配置php扩展memcache
  9. 关于个人博客转移的那些事
  10. Java集合Collection之实现原理解读(Map)
  11. NNDL 实验三 线性回归
  12. iOS动态库和静态库的运用
  13. 微信无法绑定手机号的解决方案
  14. MPB:遗传发育所刘永鑫等-易扩增子:易用、可重复和跨平台的扩增子分析流程...
  15. 使用three建立一个正方体
  16. VC删除IE缓存、COOKIE及浏览记录
  17. MPC+MPD听音乐
  18. 倒计时最后3天,抢永久0服务费微信直连商户
  19. 2021-03-08~09~10~11~12 大数据课程笔记 day47day48day49day50day51
  20. oracle database各个版本地址

热门文章

  1. 【Linux】一步一步学Linux——shopt命令(214)
  2. WinXP下 扫雷程序逆向分析 --扫雷辅助(一)
  3. 中国互联网的“去中心化”与“中心化”之战
  4. 【读书笔记】阅读的危险
  5. nbu还原oracle,NBU恢复oracle
  6. arcgis重心迁移分析_山东省植被覆盖度变化与气候因子相关性分析
  7. 使用线程自己join自己完成线程门栓
  8. 将数据传入重定向网页
  9. Failed to get response from /vue-cli-version-marker
  10. pixhawk博客导读