基于C++/opencv 提取图像的直方图

 一个图像是由不同颜色值的像素组成的,像索值在图像中的分布情况是这幅图像的一个重要特征。图像是由像素组成的,在一个单通道的灰度图像中,每个像素的值介于0(黑色)-

255(白色)之间。根据图像的内容,你会发现每个灰度值的像素数目是不同的。

直方图是一个简单的表,它给出了一幅图像或一组图像中拥有给定数值的像素数量。因此,灰度图像的直方图有256个条目(或称为容器)。0号容器给出值为0的像素个数,1号容器给出值为1的像素个数,依此类推。显然,如果你对方图的所有项求和,会得到像素的总数。直方图也可以被归一化,归一化后的所有项之和等于1。在这种情况下,每一项给出的都是拥有特定数值的像素在图像中占的比例。

谢谢原博:http://blog.csdn.net/andrewseu/article/details/49616279

     http://blog.csdn.net/garfielder007/article/details/49931049

以下是两种提取图像直方图的方法:

法一:

 1 // test1_320平滑处理.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include"iostream"
 6 #include<cv.h>
 7 #include <opencv2/core/core.hpp>
 8 #include<opencv2/imgproc/imgproc.hpp>
 9 #include <opencv2/highgui/highgui.hpp>
10 using namespace std;
11 using namespace cv;
12 
13 
14 int _tmain(int argc, _TCHAR* argv[])
15 {
16 IplImage* src = cvLoadImage("Blind.jpg");
17 IplImage* hsv = cvCreateImage(cvGetSize(src), 8, 3);
18 IplImage* h_plane = cvCreateImage(cvGetSize(src), 8, 1);
19 IplImage* s_plane = cvCreateImage(cvGetSize(src), 8, 1);
20 IplImage* v_plane = cvCreateImage(cvGetSize(src), 8, 1);
21 IplImage* planes[] = {h_plane,s_plane};
22 
23 //H分量划分为16个等级,S分量划分为8个等级
24 int h_bins = 16, s_bins = 8;
25 int hist_size[] = { h_bins, s_bins };
26 
27 //H分量的变化范围
28 float h_ranges[] = { 0, 180 };
29 //S分量的变化范围
30 float s_ranges[] = { 0, 255 };
31 float* ranges[] = { h_ranges, s_ranges };
32 //输入图像转到HSV颜色空间
33 cvCvtColor(src, hsv, CV_BGR2HSV);
34 cvCvtPixToPlane(hsv, h_plane, s_plane, v_plane,0);
35 //创建直方图,二维,每个维度上均分
36 CvHistogram * hist = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);
37 //根据H,S两个平面数据统计直方图
38 cvCalcHist(planes, hist, 0, 0);
39 //获取直方图统计的最大值,用于动态显示直方图
40 float max_value;
41 cvGetMinMaxHistValue(hist, 0, &max_value, 0, 0);
42 //设置直方图显示图像
43 int height = 240;
44 int width = (h_bins*s_bins * 6);
45 IplImage* hist_Img = cvCreateImage(cvSize(width, height), 8, 3);
46 cvZero(hist_Img);
47 //用来进行HSV到RGB颜色转换的临时单位图像
48 IplImage * hsv_color = cvCreateImage(cvSize(1, 1), 8, 3);
49 IplImage * rgb_color = cvCreateImage(cvSize(1, 1), 8, 3);
50 int bin_w = width / (h_bins*s_bins);
51 for (int h = 0; h < h_bins;h++)
52 {
53 for (int s = 0; s < s_bins;s++)
54 {
55 int i = h*s_bins + s;
56 //获取直方图中的统计次数,计算显示在图像中的高度
57 float bin_val = cvQueryHistValue_2D(hist, h, s);
58 int intensity = cvRound(bin_val*height / max_value);
59 //获取当前直方图代表的颜色,转换成RGB用于绘制
60 cvSet2D(hsv_color, 0, 0, cvScalar(h*180.f / h_bins, s*255.f / s_bins, 255,0));
61 cvCvtColor(hsv_color, rgb_color, CV_HSV2BGR);
62 CvScalar color = cvGet2D(rgb_color, 0, 0);
63 cvRectangle(hist_Img, cvPoint(i*bin_w, height),
64 cvPoint((i+1)*bin_w,height-intensity),color,-1,8,0);
65 }
66 }
67 cvNamedWindow("Source", 1);
68 cvShowImage("Source", src);
69 cvNamedWindow("H-S Histogram", 1);
70 cvShowImage("H-S Histogram", hist_Img);
71 cvWaitKey(0);
72 return 0;
73 }

 

 法二:

  1 // test2_321.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include<iostream>
  6 #include<opencv2/opencv.hpp>  
  7 #include <opencv2/core/core.hpp>
  8 #include<opencv2/imgproc/imgproc.hpp>
  9 #include <opencv2/highgui/highgui.hpp>
 10 using namespace std;
 11 using namespace cv;
 12 
 13 class HistogramND
 14 {
 15 private:
 16     Mat image;//源图像  
 17     int hisSize[1], hisWidth, hisHeight;//直方图的大小,宽度和高度  
 18     float range[2];//直方图取值范围  
 19     const float *ranges;
 20     Mat channelsRGB[3];//分离的BGR通道  
 21     MatND outputRGB[3];//输出直方图分量  
 22 public:
 23     HistogramND(){
 24         hisSize[0] = 256;
 25         hisWidth = 400;
 26         hisHeight = 400;
 27         range[0] = 0.0;
 28         range[1] = 256.0;
 29         ranges = &range[0];
 30     }
 31 
 32     //导入图片  
 33     bool importImage(String path){
 34         image = imread(path);
 35         if (!image.data)
 36             return false;
 37         return true;
 38     }
 39 
 40     //分离通道  
 41     void splitChannels(){
 42         split(image, channelsRGB);
 43     }
 44 
 45     //计算直方图  
 46     void getHistogram(){
 47         calcHist(&channelsRGB[0], 1, 0, Mat(), outputRGB[0], 1, hisSize, &ranges);
 48         calcHist(&channelsRGB[1], 1, 0, Mat(), outputRGB[1], 1, hisSize, &ranges);
 49         calcHist(&channelsRGB[2], 1, 0, Mat(), outputRGB[2], 1, hisSize, &ranges);
 50 
 51         //输出各个bin的值  
 52         for (int i = 0; i < hisSize[0]; ++i){
 53             cout << i << "   B:" << outputRGB[0].at<float>(i);
 54             cout << "   G:" << outputRGB[1].at<float>(i);
 55             cout << "   R:" << outputRGB[2].at<float>(i) << endl;
 56         }
 57     }
 58 
 59     //显示直方图  
 60     void displayHisttogram(){
 61         Mat rgbHist[3];
 62         for (int i = 0; i < 3; i++)
 63         {
 64             rgbHist[i] = Mat(hisWidth, hisHeight, CV_8UC3, Scalar::all(0));
 65         }
 66         normalize(outputRGB[0], outputRGB[0], 0, hisWidth - 20, NORM_MINMAX);
 67         normalize(outputRGB[1], outputRGB[1], 0, hisWidth - 20, NORM_MINMAX);
 68         normalize(outputRGB[2], outputRGB[2], 0, hisWidth - 20, NORM_MINMAX);
 69         for (int i = 0; i < hisSize[0]; i++)
 70         {
 71             int val = saturate_cast<int>(outputRGB[0].at<float>(i));
 72             rectangle(rgbHist[0], Point(i * 2 + 10, rgbHist[0].rows), 
 73                 Point((i + 1) * 2 + 10, rgbHist[0].rows - val), Scalar(0, 0, 255), 1, 8);
 74             val = saturate_cast<int>(outputRGB[1].at<float>(i));
 75             rectangle(rgbHist[1], Point(i * 2 + 10, rgbHist[1].rows), Point((i + 1) * 2 + 10, 
 76                 rgbHist[1].rows - val), Scalar(0, 255, 0), 1, 8);
 77             val = saturate_cast<int>(outputRGB[2].at<float>(i));
 78             rectangle(rgbHist[2], Point(i * 2 + 10, rgbHist[2].rows), Point((i + 1) * 2 + 10, 
 79                 rgbHist[2].rows - val), Scalar(255, 0, 0), 1, 8);
 80         }
 81 
 82         cv::imshow("R", rgbHist[0]);
 83         imshow("G", rgbHist[1]);
 84         imshow("B", rgbHist[2]);
 85         imshow("image", image);
 86     }
 87 };
 88 
 89 
 90 
 91 
 92 int _tmain(int argc, _TCHAR* argv[])
 93 {
 94     String path = "D:\\LiHong\\Blind Way Recognition\\MyProject\\test2_321\\test2_321\\Blind.jpg";
 95     /*cv::Mat img = cv::imread("Blind.jpg");*/
 96     HistogramND hist;
 97     /*if (!img.data)
 98     {
 99         return -1;
100     }*/
101     if (!hist.importImage(path)){
102         cout << "Import Error!" << endl;
103         return -1;
104     }
105     hist.splitChannels();
106     hist.getHistogram();
107     hist.displayHisttogram();
108     cv::waitKey();
109 
110 
111     return 0;
112 }

posted @ 2017-03-21 14:49  Shaine  阅读(5563)  评论(0编辑  收藏  举报