图像处理之图像直方图

1、什么是图像灰度直方图?什么是直方图均衡化?什么是直方图规定化?

  • 灰度直方图从数学上来说,图像直方图是描述图像的各个灰度级的统计特性,它是图像灰度值的函数,统计图像中各个灰度级出现的次数或频率从图像上来说,灰度直方图是一个二维图像,横坐标为图像中各个像素点的灰度级别,纵坐标表示具有各个灰度级别的像素在图像中出现的次数和频率
  • 图像的灰度直方图是一个离散函数,它表示图像的每一灰度级与该灰度级出现频率的对应关系。
  • 直方图均衡化是指通过某种灰度映射(如:非线性拉伸)使原始图像的直方图变换为在整个灰度范围内均匀分布。
  • 目的:增加像素灰度值的动态范围,增强图像整体对比度。
  • 直方图规定化就是要调整原始图像的直方图去逼近规定的目标直方图。有选择地增强某个灰度范围内的对比度或使图像灰度值满足某种特定的分布。
  • 归一化直方图:各个灰度级出现的次数除以图像的像素总数,即得到各个灰度级出现的概率,从而得到归一化直方图。
  • 代码:知道图像指针unchar *ptr,图像宽int width,高int height,求图像灰度直方图。

OpenCV实现图像直方图:

// RGB三色分量直方图.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"#include <opencv2/core/core.hpp>  //包含核心功能,尤其是底层数据结构和算法函数。
#include <opencv2/highgui/highgui.hpp>   //包含读写图像及视频的函数,以及操作图形用户界面函数。
#include <opencv2/imgproc/imgproc.hpp>   //包含图像处理函数。
#include <iostream>using namespace std;//绘制 RGB 图像分离通道后的每一单通道的直方图
void f_getRGBHist(cv::Mat& img)
{int bins = 256;int hist_size[] = {bins};float range[] = {0, 256};const float* ranges[] = {range};cv::MatND hist_r, hist_g, hist_b;int nImages = 1;int dims = 1;int channels_r[] ={0};cv::calcHist(&img, 1, channels_r, cv::Mat(), hist_r, 1, hist_size, ranges, true, false);int channels_g[] = {1};cv::calcHist(&img, 1, channels_g, cv::Mat(), hist_g, 1, hist_size, ranges, true, false);int channels_b[] = {2}; cv::calcHist(&img, 1, channels_b, cv::Mat(), hist_b, 1, hist_size, ranges, true, false);double max_val_r, max_val_g, max_val_b;double min_val_r, min_val_g, min_val_b;cv::minMaxLoc(hist_r, &min_val_r, &max_val_r, 0, 0);cv::minMaxLoc(hist_g, &min_val_g, &max_val_g, 0, 0);cv::minMaxLoc(hist_b, &min_val_b, &max_val_b, 0, 0);int scale = 1;int hist_height = 256;cv::Mat hist_img = cv::Mat::zeros(hist_height, bins*3, CV_8UC3);for (int i=0; i<bins; i++){float bin_val_r = hist_r.at<float>(i);float bin_val_g = hist_g.at<float>(i);float bin_val_b = hist_b.at<float>(i);int intensity_r = cvRound(bin_val_r*hist_height/max_val_r); //要绘制的高度int intensity_g = cvRound(bin_val_g*hist_height/max_val_g);int intensity_b = cvRound(bin_val_b*hist_height/max_val_b);//cv::rectangle();cv::rectangle(hist_img, cv::Point(i*scale, hist_height-1), cv::Point((i+1)*scale-1,hist_height-intensity_r), CV_RGB(255,0,0));cv::rectangle(hist_img, cv::Point((i+bins)*scale, hist_height-1), cv::Point((i+bins+1)*scale-1,hist_height-intensity_g), CV_RGB(0,255,0));cv::rectangle(hist_img, cv::Point((i+bins*2)*scale, hist_height-1), cv::Point((i+bins*2+1)*scale, hist_height-intensity_b), CV_RGB(0,0,255));}cout << "finish drawing histogram." << endl;cv::imwrite("../RGB_Histogram.bmp", hist_img);cv::namedWindow("RGB Histogram", 1);cv::imshow("RGB Histogram", hist_img);cv::waitKey();
}int _tmain(int argc, _TCHAR* argv[])
{cv::Mat src;src = cv::imread("../baboon.bmp");if (src.data==NULL){cout << "fail to load image." << endl;return 0;}cv::namedWindow("source", 1);cv::imshow("source", src);f_getRGBHist(src);f_getRGBHist2(src);return 0;
}

图1 原图src

图2 RGB三色分量的直方图

int f_getRGBHist2(cv::Mat& src)
{//Mat src;Mat dst;/ 装载图像//src = imread( "../baboon.jpg", 1 );if( !src.data ){ return -1; }Mat gray_Image;cvtColor(src, gray_Image, CV_BGR2GRAY);imshow("gray_Image", gray_Image);imwrite("../gray_Image.bmp", gray_Image);Mat result;//直方图均衡化equalizeHist(gray_Image, result);imshow("equalizeHist", result);imwrite("../equalizeHist.bmp", result);/// BGR彩色图像分割成3个单通道图像 ( R, G 和 B )vector<Mat> rgb_planes;split( src, rgb_planes );/// 设定bin数目int histSize = 255;/// 设定取值范围 ( R,G,B) )float range[] = { 0, 255 } ;const float* histRange = { range };bool uniform = true; bool accumulate = false;Mat r_hist, g_hist, b_hist;/// 计算直方图:calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );// 创建直方图画布int hist_w = 600; int hist_h = 400;int bin_w = cvRound( (double) hist_w/histSize );Mat rgb_hist[3];//初始化for(int i=0; i<3; ++i)  {  rgb_hist[i] = Mat(hist_h, hist_w, CV_8UC3, Scalar::all(0));  }  Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );/// 将直方图归一化到范围 [ 0, histImage.rows ]normalize(r_hist, r_hist, 0, histImage.rows-10, NORM_MINMAX, -1, Mat() );normalize(g_hist, g_hist, 0, histImage.rows-10, NORM_MINMAX, -1, Mat() );normalize(b_hist, b_hist, 0, histImage.rows-10, NORM_MINMAX, -1, Mat() );/// 在直方图画布上画出直方图for( int i = 1; i < histSize; i++ ){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  );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(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  );}/// 显示直方图namedWindow("calcHist Demo", 1);imshow("calcHist Demo", histImage );imwrite("../calcHist_Demo.bmp", histImage );for (int j=0; j<histSize; ++j)  {  int val = saturate_cast<int>(r_hist.at<float>(j));  rectangle(rgb_hist[0], Point(j*2+10, rgb_hist[0].rows), Point((j+1)*2+10, rgb_hist[0].rows-val), Scalar(0,0,255),1,8);  val = saturate_cast<int>(g_hist.at<float>(j));  rectangle(rgb_hist[1], Point(j*2+10, rgb_hist[1].rows), Point((j+1)*2+10, rgb_hist[1].rows-val), Scalar(0,255,0),1,8);  val = saturate_cast<int>(b_hist.at<float>(j));  rectangle(rgb_hist[2], Point(j*2+10, rgb_hist[2].rows), Point((j+1)*2+10, rgb_hist[2].rows-val), Scalar(255,0,0),1,8);  }imshow("R", rgb_hist[0]);  imshow("G", rgb_hist[1]);  imshow("B", rgb_hist[2]);  cv::imwrite("../R_Histogram.bmp", rgb_hist[0]);cv::imwrite("../G_Histogram.bmp", rgb_hist[1]);cv::imwrite("../B_Histogram.bmp", rgb_hist[2]);waitKey(0);return 0;
}

图3 灰度图像(BGR--->GRAY)

图4  经过灰度直方图均衡化处理后的图像

对比图3和图4 ,可以明显的看出图4 的整体对比度要比图3 强很多,亮度也要明亮很多。由此可以看出图像直方图均衡化的作用就是:增加像素灰度值的动态范围,增强图像整体对比度。 由此可见,可以通过图像直方图均衡化的方式来达到图像增强的目的。

图5  R通道的图像直方图

图6  G通道的图像直方图

图7  B通道的图像直方图

图8  灰度图像直方图

//绘制H-S二维直方图
int f_HS_hist(cv::Mat src)
{//cv::Mat src;//src=cv::imread("../baboon.jpg");cv::Mat hsv;cv::cvtColor(src, hsv, CV_BGR2HSV);cv::namedWindow( "HSV", 1 );cv::imshow( "HSV", hsv );cv::waitKey();cv::imwrite("../hsvImg.bmp", hsv );// Quantize the hue to 30 levels// and the saturation to 32 levelsint hbins = 256, sbins = 180;int histSize[] = {hbins, sbins}; //每个维度的直方图尺寸的数组// hue varies from 0 to 179, see cvtColor//定义色调变化范围为 0到179float hranges[] = { 0, 180 };// saturation varies from 0 (black-gray-white) to// 255 (pure spectrum color)float sranges[] = { 0, 256 };const float* ranges[] = { hranges, sranges }; //每一维数值的取值范围cv::MatND hist; //输出的目标直方图// we compute the histogram from the 0-th and 1-st channelsint channels[] = {0, 1};//H 通道, S 通道cv::calcHist( &hsv, //输入的数组1, //数组个数为 1 channels, //通道索引cv::Mat(), //不使用掩模hist, //输出的目标直方图2, //需要计算的直方图维数为2histSize, //存放每个维度的直方图尺寸的数组ranges, //每一维数值的取值范围数组true, //指示直方图是否均匀的标识,true表示均匀false ); //累计标识,false表示直方图在配置阶段会被清零double maxVal=0;cv::minMaxLoc(hist, 0, &maxVal, 0, 0);int scale = 2;cv::Mat histImg = cv::Mat::zeros(sbins*scale, hbins*scale, CV_8UC3);//双层循环,绘制直方图for( int h = 0; h < hbins; h++ ){for( int s = 0; s < sbins; s++ ){float binVal = hist.at<float>(h, s); //直方图直条的值int intensity = cvRound(binVal*255/maxVal); //强度//正式进行绘制cv::rectangle( histImg, cv::Point(h*scale, s*scale),cv::Point( (h+1)*scale - 1, (s+1)*scale - 1),cv::Scalar::all(intensity), CV_FILLED );}}cv::namedWindow( "Source", 1 );cv::imshow( "Source", src );cv::namedWindow( "H-S Histogram", 1 );cv::imshow( "H-S Histogram", histImg );cv::waitKey();cv::imwrite("../H-S_hist.bmp", histImg );return 0;
}

图9 - HSV图像

图10 - H-S直方图

【不经一番彻骨寒,哪有梅花扑鼻香。】

图像处理之图像直方图相关推荐

  1. 【数字图像处理】图像直方图均衡化、空域滤波(均值滤波、中值滤波)、图像锐化(Laplace算子)、图像傅里叶变换实验

    图像直方图均衡化.空域滤波.图像锐化.图像傅里叶变换 一.图像直方图均衡化 二.图像空域滤波 1.均值滤波(滤波次数n→3) 2.中值滤波(滤波次数n→3) 3.图像锐化(Laplace算子) 三.图 ...

  2. 【图像处理】图像直方图+滤波+小波变换+分割处理系统【含GUI Matlab源码 608期】

    ⛄一.图像处理简介 图像处理知识点: 1 数字图像处理及matlab实现知识点总结1-4 2 数字图像处理及matlab实现知识点总结 5-10 ⛄二.部分源代码 unction varargout ...

  3. OpenCV-Python图像直方图计算calcHist函数详解、示例及图形呈现

    ☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░ 一.引言 在前面几篇直方图相关的文章中介绍了直方图均衡.直方图匹配.局部直方图处理.基 ...

  4. cuda图像处理_CUDA随笔之图像直方图(优化历程)

    在忙忙碌碌许久之后,终于有时间写 "CUDA随笔" 系列的第二集了! 这次给大家带来了一个图像处理的应用例子:计算图片的直方图. 虽然使用CUDA可以很轻松地在性能上超越CPU,如 ...

  5. Win8 Metro(C#)数字图像处理--3.3图像直方图计算

    原文:Win8 Metro(C#)数字图像处理--3.3图像直方图计算 /// <summary>/// Get the array of histrgram./// </summa ...

  6. 图像的灰度级数越多越好_MATLAB-数字图像处理 图像直方图归一化

    图像直方图归一化 图像直方图概念: 图像直方图是反映一个图像像素分布的统计表,其实横坐标代表了图像像素的种类,可以是灰度的,也可以是彩色的.纵坐标代表了每一种颜色值在图像中的像素总数或者占所有像素个数 ...

  7. OpenCV与图像处理学习二——图像直方图与色彩空间

    OpenCV与图像处理学习二--图像直方图与色彩空间 2.4 图像直方图(Image Histogram) 2.4.1 直方图的绘制 2.4.2 三通道直方图绘制 2.5 颜色空间 2.5.1 RGB ...

  8. OpenCV图像处理学习二十,图像直方图均衡化原理与实现

    一.图像直方图的概念 图像直方图,是指对整个图像在灰度范围内的像素值(0~255)统计出现频率次数,据此生成的直方图,称为图像直方图.直方图反映了图像灰度的分布情况,是图像的统计学特征.图像的灰度直方 ...

  9. 计算机图像处理实验二 图像直方图及灰度变换

    一.实验目的与要求 1.掌握图像灰度直方图的概念及其计算方法,编写灰度直方图统计程序. 2.通过对图像直方图的分析,学习应用直方图法解决诸如图像二值化等具体问题. 3.熟悉直方图均衡化的计算过程及其应 ...

  10. 图像处理大型科普——图像直方图

    图像处理大型科普--图像直方图 偶尔跟在浙大读研的湖大一姐谈起轮廓识别,她正在做一个能把衣服分类成不同款式的应用,衣服平摊好,然后用手机一扫,马上就能告诉你这是T-SHIRT还是裙子,什么?你敢说这玩 ...

最新文章

  1. 人工智能是人性的罗夏测试
  2. 【bzoj2751】[HAOI2012]容易题(easy) 数论,简单题
  3. python代码怎么运行-python语言怎么运行
  4. Go的strconv一
  5. laravel5.5使用sendCloud邮件服务
  6. 家的味道,家的感觉!!!
  7. 【HDU - 1870】愚人节的礼物(水题模拟 思想类似于栈?)
  8. Spring Boot基础讲解
  9. 布同:pdf自定义分割(断章)
  10. Centos6.X 安装MongoDb
  11. Septentrio RAIM+接收机自主完好性监测实验
  12. ffmpeg编码:xavc 42210bit+mxf
  13. c语言课程设计 工资管理系统
  14. vs2015开发在网页中调用的ocx控件详解(一)
  15. 微博话题墙 html,Js仿微博插入话题功能
  16. Oracle日常性能查看
  17. Mentor-dft 学习笔记 day44-Low-Power Design Test
  18. 传统产业如何在互联网时代创新与转型
  19. Linux 使用 speedtest 测速
  20. 关于static void 函数

热门文章

  1. 系统集成项目管理工程师(中级)考试心得经验
  2. Unity ToLua LuaFramework_UGUI学习笔记
  3. Mac OS读写NTFS
  4. 验证码 工具 Kaptcha 配置参数
  5. 美国国家安全局(NSA)网络攻击主战武器“验证器”
  6. setMinDate出现java.lang.IllegalArgumentException: fromDate:xxx does not preced toDate: xxx异常的简单解决办法
  7. JS设计模式——责任链模式
  8. eclipse格式化代码快捷键
  9. Android wear 睡眠追踪,谷歌Fit应用更新 添加了新的健康中心和睡眠跟踪数据
  10. chrome浏览器安装crx Mouse(鼠标手势)插件