OpenCV绘制图像中RGB三个通道的直方图
一开始是看《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三个通道的直方图的更多相关文章
- Java基于opencv实现图像数字识别(三)—灰度化和二值化
Java基于opencv实现图像数字识别(三)-灰度化和二值化 一.灰度化 灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值:因此,灰度图像每个像素点只需一个字 ...
- C#使用OpenCV剪切图像中的圆形和矩形
前言 本文主要介绍如何使用OpenCV剪切图像中的圆形和矩形. 准备工作 首先创建一个Wpf项目--WpfOpenCV,这里版本使用Framework4.7.2. 然后使用Nuget搜索[Emgu.C ...
- opencv 访问图像像素的三种方式
访问图像中的像素 访问图像像素有三种可行的方法方法一:指针访问指针访问访问的速度最快,Mat类可以通过ptr函数得到图像任意一行的首地址,同时,Mat类的一些属性也可以用到公有属性 rows和cols ...
- (转)使用Python和OpenCV检测图像中的物体并将物体裁剪下来
原文链接:https://blog.csdn.net/liqiancao/article/details/55670749 介绍 硕士阶段的毕设是关于昆虫图像分类的,代码写到一半,上周五导师又给我新的 ...
- opencv 替换图像中的一部分
首先选取图像中的Roi区域,然后对Roi区域进行赋值,那么原图像相应的区域也跟着变化了: dst = src.clone(); cv::Mat Roi(dst, cv::Rect(x, y, cut_ ...
- opencv 5 图像转换(3 重映射 仿射变换 直方图均衡化)
重映射 实现重映射(remap函数) 基础示例程序:基本重映射 //---------------------------------[头文件.命名空间包含部分]------------------- ...
- 利用OpenCV检测图像中的长方形画布或纸张并提取图像内容
基于知乎上的一个答案.问题如下: 也就是在一张照片里,已知有个长方形的物体,但是经过了透视投影,已经不再是规则的长方形,那么如何提取这个图形里的内容呢?这是个很常见的场景,比如在博物馆里看到一幅很喜欢 ...
- OpenCV 绘制图像直方图
OpenCV绘制图像直方图,版本2.4.11 直方图可展示图像中的像素分布,是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数.可以借助观察该直方图了解需要如何调整亮度分布.这种直方 ...
- 多通道(比方RGB三通道)卷积过程
今天一个同学问 卷积过程好像是对 一个通道的图像进行卷积, 比方10个卷积核,得到10个feature map, 那么输入图像为RGB三个通道呢,输出就为 30个feature map 吗, 答案肯定 ...
随机推荐
- 洛谷P3953逛公园
题目 作为\(NOIp2017D1T3\) 这个题还是很良心的,至少相对于\(NOIp2018\)来说,希望\(NOIp2019\)不会这么坑吧. 这个题可以作为记忆化搜索的进阶题了,做这个题的方法也 ...
- git 忽略部分文件类型的同步
场景 利用 pycharm 进行代码操作的时候会自动创建 .idea/ 文件夹 特么我每次随便做点操作.这里面的东西也会随着自动改一些 一开始开始无视 如果是多人协同开发会导致代码合并相关的问题 因此 ...
- 【JVM】类加载机制
原文:[深入Java虚拟机]之四:类加载机制 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段.它们开始的顺序如下图所示: 类加 ...
- 修改帝国cms栏目后,如何更新
修改栏目后,要依次做如下更新: 1. 2. 3. 如果只是修改了栏目里的属性,只需要做第三步就行了
- 首次使用Oracle SQL Developer 提示: enter the full pathname for java.exe
https://www.cnblogs.com/520future/p/7699095.html 首次使用Oracle SQL Developer 提示: enter the full pathnam ...
- Numpy系列(四)- 索引和切片
Python 中原生的数组就支持使用方括号([])进行索引和切片操作,Numpy 自然不会放过这个强大的特性. 单个元素索引 1-D数组的单元素索引是人们期望的.它的工作原理与其他标准Python序 ...
- Numpy系列(十)- 掩码数组
简介 有时候数据集中存在缺失.异常或者无效的数值,我们可以标记该元素为被屏蔽(无效)状态. import numpy as np import numpy.ma as ma x = np.array( ...
- 《从Paxos到ZooKeeper分布式一致性原理与实践》学习笔记
第一章 分布式架构 1.1 从集中式到分布式 集中式的特点: 部署结构简单(因为基于底层性能卓越的大型主机,不需考虑对服务多个节点的部署,也就不用考虑多个节点之间分布式协调问题) 分布式系统是一个硬件 ...
- 携程apollo系列-客户端集成
本文讲解如何在 Java 程序中集成 Apollo 配置, 主要涉及到一些基础用法. 对于一些高级用法, 比如如何加密/解密配置项 (可用于数据库密码配置), 如何动态切换数据源地址,如何动态切换日志 ...
- SQL Server 常用的系统函数
Ø 简介 本文主要列举 SQL Server 中常用的一些系统函数,帮助我们在编写 SQL 时忘了某个函数的用法方便查阅.主要分为以下几类函数,更多函数可参考官网. 1. 字符串函数 2. ...