zoukankan      html  css  js  c++  java
  • OpenCV绘制图像中RGB三个通道的直方图

    一开始是看《OpenCV计算机视觉编程攻略(第2版)》这本书学做直方图,但是书本里说直方图的部分只详细说了黑白图像(单通道)的直方图绘制方法,RGB图像的直方图只说了如何计算,没有说计算完之后如何绘制,自己想了很久也没想到正确的绘制方法。

    去查OpenCV的官方文档,里面的例子只说了如何绘制H和S两通道的直方图,很多函数的用法也没搞清楚。

    后来在网上看别人的程序,找到有绘制HSV三通道直方图的程序,花了一点时间一行一行地看,并且结合自己已经学过的知识把程序改成绘制RGB三通道的直方图的程序。

    histogram.h:

    #ifndef HISTOGRAM_H
    #define HISTOGRAM_H
    
    #include <opencv2opencv.hpp>
    
    #include <iostream>
    #include <string>
    
    class Histogram
    {
    private:
        int histSize[3];        //直方图中箱子的数量
        float hranges[2];    //值范围
        const float * ranges[3];        //值范围的指针
        int channels[3];        //要检查的通道数量
    
    public:
        Histogram();
        cv::Mat getHistogram(const cv::Mat & image);
        std::vector<cv::Mat> getHistogramImage(const cv::Mat & image, int zoom = 1);
        static std::vector<cv::Mat> getImageOfHistogram(const cv::Mat & hist, int zoom);
    };
    
    #endif

    histogram.cpp:

    #include "histogram.h"
    
    Histogram::Histogram()
    {
        histSize[0] = 256;
        histSize[1] = 256;
        histSize[2] = 256;
        hranges[0] = 0.0;
        hranges[1] = 256.0;
        ranges[0] = hranges;
        ranges[1] = hranges;
        ranges[2] = hranges;
        channels[0] = 0;
        channels[1] = 1;
        channels[2] = 2;
    }
    
    cv::Mat Histogram::getHistogram(const cv::Mat & image)
    {
        cv::Mat hist;
    
        hranges[0] = 0.0;
        hranges[1] = 256.0;
        channels[0] = 0;
        channels[1] = 1;
        channels[2] = 2;
    
        cv::calcHist(&image, 1, channels, cv::Mat(), hist, 3, histSize, ranges);
    
        return hist;
    }
    
    std::vector<cv::Mat> Histogram::getHistogramImage(const cv::Mat & image, int zoom)
    {
        cv::Mat hist = getHistogram(image);
    
        return Histogram::getImageOfHistogram(hist, zoom);
    }
    
    std::vector<cv::Mat> Histogram::getImageOfHistogram(const cv::Mat & hist, int zoom)
    {
        int scale = 2;
    
        float hist_b[256];  
        float hist_g[256];  
        float hist_r[256];  
    memset(hist_b,
    0, 256 * sizeof(float)); memset(hist_g, 0, 256 * sizeof(float)); memset(hist_r, 0, 256 * sizeof(float)); //计算三个通道的直方图 for(int b = 0; b < 256; b ++ ) { for(int g = 0; g < 256; g ++) { for(int r = 0; r < 256; r ++) { float binVal = hist.at<float>(b, g, r); hist_b[b] += binVal; hist_g[g] += binVal; hist_r[r] += binVal; } } } //获得三个通道直方图中的最大值 double max_b = 0.0, max_g = 0.0,max_r = 0.0; for(int i = 0; i < 256; i ++) { if(hist_b[i] > max_b) { max_b = hist_b[i]; } } for(int i = 0; i < 256; i ++) { if(hist_g[i] > max_g) { max_g = hist_g[i]; } } for(int i = 0; i < 256; i ++) { if(hist_r[i] > max_r) { max_r = hist_r[i]; } } //初始化空的图 cv::Mat b_img = cv::Mat::zeros(256, 256 * scale, CV_8UC3); cv::Mat g_img = cv::Mat::zeros(256, 256 * scale, CV_8UC3); cv::Mat r_img = cv::Mat::zeros(256, 256 * scale, CV_8UC3); //绘制三个通道的直方图 for(int i = 0; i < 256; i ++) { int intensity = cvRound(hist_b[i] * b_img.rows / max_b); cv::rectangle(b_img, cv::Point(i * scale, b_img.rows - intensity), cv::Point((i + 1) * scale - 1, b_img.rows - 1), cv::Scalar(255, 0 ,0), 1); } for(int i = 0; i < 256; i ++) { int intensity = cvRound(hist_g[i] * g_img.rows / max_g); cv::rectangle(g_img, cv::Point(i * scale, g_img.rows - intensity), cv::Point((i + 1) * scale - 1, g_img.rows - 1), cv::Scalar(0, 255, 0), 1); } for(int i = 0; i < 256; i ++) { int intensity = cvRound(hist_r[i] * r_img.rows / max_r); cv::rectangle(r_img, cv::Point(i * scale, r_img.rows - intensity), cv::Point((i + 1) * scale - 1, r_img.rows - 1), cv::Scalar(0, 0, 255), 1); } std::vector<cv::Mat> imgs; imgs.push_back(b_img); imgs.push_back(g_img); imgs.push_back(r_img); return imgs; }

    main.cpp:

    #include <opencv2opencv.hpp>
    
    #include <iostream>
    #include <string>
    
    #include "histogram.h"
    
    using namespace std;
    
    int main()
    {
        cv::Mat image = cv::imread("animal.jpg");
        cv::imshow("image", image);
    
        Histogram h;
        std::vector<cv::Mat> imgs = h.getHistogramImage(image);
    
        cv::namedWindow("B");  
        cv::imshow("B", imgs[0]);  
        cv::namedWindow("G");  
        cv::imshow("G", imgs[1]);      
        cv::namedWindow("R");  
        cv::imshow("R", imgs[2]);  
    
        cv::waitKey();
    
        return 0;
    }

    运行结果:

     

    参考资料:

    http://blog.csdn.net/ljbkiss/article/details/7420429

  • 相关阅读:
    WCF 、Web API 、 WCF REST 和 Web Service 的区别
    BusyIndicator using MVVM 忙碌状态指示器的的实现
    复制文件夹的方法 .net
    SQL/LINQ/Lamda
    CSLA验证规则总结
    C++中GB2312字符串和UTF-8之间的转换
    如何用VC编写供PB调用的DLL
    【转】lucene4.3.0 配置与调试
    cygwin主要命令
    【转】eclipse中window->preference选项中没有tomcat的解决方法
  • 原文地址:https://www.cnblogs.com/chujian1120/p/5512276.html
Copyright © 2011-2022 走看看