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

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

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

histogram.h:

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

histogram.cpp:

#include "histogram.h"

Histogram::Histogram()
{
histSize[] = ;
histSize[] = ;
histSize[] = ;
hranges[] = 0.0;
hranges[] = 256.0;
ranges[] = hranges;
ranges[] = hranges;
ranges[] = hranges;
channels[] = ;
channels[] = ;
channels[] = ;
} cv::Mat Histogram::getHistogram(const cv::Mat & image)
{
cv::Mat hist; hranges[] = 0.0;
hranges[] = 256.0;
channels[] = ;
channels[] = ;
channels[] = ; cv::calcHist(&image, , channels, cv::Mat(), hist, , 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 = ; float hist_b[];
float hist_g[];
float hist_r[];
memset(hist_b, , * sizeof(float));
memset(hist_g, , * sizeof(float));
memset(hist_r, , * sizeof(float)); //计算三个通道的直方图
for(int b = ; b < ; b ++ )
{
for(int g = ; g < ; g ++)
{
for(int r = ; r < ; 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 = ; i < ; i ++)
{
if(hist_b[i] > max_b)
{
max_b = hist_b[i];
}
}
for(int i = ; i < ; i ++)
{
if(hist_g[i] > max_g)
{
max_g = hist_g[i];
}
}
for(int i = ; i < ; i ++)
{
if(hist_r[i] > max_r)
{
max_r = hist_r[i];
}
} //初始化空的图
cv::Mat b_img = cv::Mat::zeros(, * scale, CV_8UC3);
cv::Mat g_img = cv::Mat::zeros(, * scale, CV_8UC3);
cv::Mat r_img = cv::Mat::zeros(, * scale, CV_8UC3); //绘制三个通道的直方图
for(int i = ; i < ; 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 + ) * scale - , b_img.rows - ), cv::Scalar(, ,), );
}
for(int i = ; i < ; 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 + ) * scale - , g_img.rows - ), cv::Scalar(, , ), );
}
for(int i = ; i < ; 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 + ) * scale - , r_img.rows - ), cv::Scalar(, , ), );
} 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 <opencv2\opencv.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[]);
cv::namedWindow("G");
cv::imshow("G", imgs[]);
cv::namedWindow("R");
cv::imshow("R", imgs[]); cv::waitKey(); return ;
}

运行结果:

参考资料:

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

OpenCV绘制图像中RGB三个通道的直方图的更多相关文章

  1. Java基于opencv实现图像数字识别(三)—灰度化和二值化

    Java基于opencv实现图像数字识别(三)-灰度化和二值化 一.灰度化 灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值:因此,灰度图像每个像素点只需一个字 ...

  2. C#使用OpenCV剪切图像中的圆形和矩形

    前言 本文主要介绍如何使用OpenCV剪切图像中的圆形和矩形. 准备工作 首先创建一个Wpf项目--WpfOpenCV,这里版本使用Framework4.7.2. 然后使用Nuget搜索[Emgu.C ...

  3. opencv 访问图像像素的三种方式

    访问图像中的像素 访问图像像素有三种可行的方法方法一:指针访问指针访问访问的速度最快,Mat类可以通过ptr函数得到图像任意一行的首地址,同时,Mat类的一些属性也可以用到公有属性 rows和cols ...

  4. (转)使用Python和OpenCV检测图像中的物体并将物体裁剪下来

    原文链接:https://blog.csdn.net/liqiancao/article/details/55670749 介绍 硕士阶段的毕设是关于昆虫图像分类的,代码写到一半,上周五导师又给我新的 ...

  5. opencv 替换图像中的一部分

    首先选取图像中的Roi区域,然后对Roi区域进行赋值,那么原图像相应的区域也跟着变化了: dst = src.clone(); cv::Mat Roi(dst, cv::Rect(x, y, cut_ ...

  6. opencv 5 图像转换(3 重映射 仿射变换 直方图均衡化)

    重映射 实现重映射(remap函数) 基础示例程序:基本重映射 //---------------------------------[头文件.命名空间包含部分]------------------- ...

  7. 利用OpenCV检测图像中的长方形画布或纸张并提取图像内容

    基于知乎上的一个答案.问题如下: 也就是在一张照片里,已知有个长方形的物体,但是经过了透视投影,已经不再是规则的长方形,那么如何提取这个图形里的内容呢?这是个很常见的场景,比如在博物馆里看到一幅很喜欢 ...

  8. OpenCV 绘制图像直方图

    OpenCV绘制图像直方图,版本2.4.11 直方图可展示图像中的像素分布,是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数.可以借助观察该直方图了解需要如何调整亮度分布.这种直方 ...

  9. 多通道(比方RGB三通道)卷积过程

    今天一个同学问 卷积过程好像是对 一个通道的图像进行卷积, 比方10个卷积核,得到10个feature map, 那么输入图像为RGB三个通道呢,输出就为 30个feature map 吗, 答案肯定 ...

随机推荐

  1. Go语言中的string知识点

    1.Go语言String的本质就是一个[]byte,所以他们之间可以互相转换,byte数组的长度就是字符串的长度. func StringTest1() { str := "Hello,Wo ...

  2. 在Magento 2中创建管理员菜单

    在Magento 2中创建管理员菜单 第1步:创建menu.xml 第2步:添加菜单项 第3步:刷新Magento缓存 第1步:创建menu.xml 创建名为:menu.xml文件的管理菜单文件 ap ...

  3. Java EE 开发环境搭建

    1 Windows 1.1 JDK 下载: 下载地址:https://developer.oracle.com/java 安装文件:jdk-8u201-windows-x64.exe JDK 并不是越 ...

  4. Vue(基础八)_导航守卫(组件内的守卫)

    一.前言 主要通过一个例子演示三个钩子的作用: 1.beforeRouteEnter()                                                         ...

  5. ZooKeeper 概述

    ZooKeeper:分布式应用程序的分布式协调服务 ZooKeeper:是用于分布式应用程序的分布式开源协调服务 可以简单理解:ZooKeeper = 文件系统 + 通知机制 从设计模式角度理解:Zo ...

  6. VMware 设置网络

    在VMware上安装 系统完成后,设置虚拟网络 这里的VMware 版本为 14. 本文以window server 2016 为例. 在虚拟机上菜单栏中, 编辑  >> 虚拟网络编辑器 ...

  7. DirectX11 With Windows SDK--07 添加光照与常用几何模型

    前言 对于3D游戏来说,合理的光照可以让游戏显得更加真实.接下来会介绍光照的各种分量,以及常见的光照模型.除此之外,该项目还用到了多个常量缓冲区,因此还会提及HLSL的常量缓冲区打包规则以及如何设置多 ...

  8. CSS Grid基于网格的二维布局系统(详细教程)

    .grid-wrap{ display: inline-flex; padding: 20px; background: #f4f4f4; word-break: initial; } .handle ...

  9. [再寄小读者之数学篇](2014-10-08 乘积型 Sobolev 不等式)

    $$\bex n\geq 2, 1\leq p<n\ra \sen{f}_{L^\frac{np}{n-p}(\bbR^n)} \leq C\prod_{k=1}^n \sen{\p_k f}_ ...

  10. 「WC2018」通道

    没有代码能力... LOJ #2339 Luogu P4220 UOJ #347 题意 给定三棵树$ T1,T2,T3$,求一个点对$ (x,y)$使得$ T1.dist(x,y)+T2.dist(x ...