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 吗, 答案肯定 ...
随机推荐
- git 学习(1) ----- git 本地仓库操作
最近在项目中使用git了,在实战中才知道,以前学习的git 知识只是皮毛,需要重新系统的学一下,读了一本叫 Learn Git in a Month of Lunches 的书籍,这本书通俗易懂,使 ...
- [SimplePlayer] 7. 多线程处理
在前面的文章中,我们分别实现了视频图像解码.播放,音频解码.播放,现在则需要把这些功能组合起来.总体上来说,整个程序的功能可以分为两条线路:视频以及音频,两条线之间除了后续的同步操作之外基本没有任何关 ...
- Qt 自定义按钮
自定义控件的实现思路如下: a1.新建一个类,该类继承QPushbutton,由于QPushbutton继承于QWidget,因此可以直接在该继承类里面进行布局管理和挂载控件: a2.新建两个QLab ...
- Go语言公开或未公开的标识符
Go语言公开或未公开的标识符的基本概念 Go语言支持从包里公开或者隐藏标志符,通过这个特性,可以让用户按照自己的规则控制标识符的可见性. Go语言中的可见性,是通过声明类型的大小写来进行区别的. 例如 ...
- Python之——CentOS 6.5安装Python2.7.14
Python之——CentOS 6.5安装Python2.7.14 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/l1028386804/art ...
- Dubbo2.6.5入门——简单的HelloWorld
建立父工程 打开idea,新建一个空的maven工程,作为整个项目的父工程. <?xml version="1.0" encoding="UTF-8"?& ...
- NOI-OJ 1.12 ID:10 素数对
整体思路 本题涉及大量素数的使用,故使用埃拉拖色尼算法提前计算出素数表可以避免大量.重复的计算. 判断素数对很简单,使用两个变量p1和p2代表素数表中的第一个和第二个素数,依次在表中向后移动,判断p2 ...
- SPFA+SLF+LLL
关于SLF优化 朴素SPFA使用常规队列(FIFO)更新距离,并没有考虑优化出队顺序(dis值小的优先出队)可以在一开始就把各个点的dis值限值小,从而避免大量的松弛操作,从而提高效率.这就是SLF( ...
- vue-resource的使用,前后端数据交互
vue-resource的使用,前后端数据交互 1:导入vue与vue-resource的js js下载: https://pan.baidu.com/s/1fs5QaNwcl2AMEyp_kUg ...
- 第十节:利用async和await简化异步编程模式的几种写法
一. async和await简介 PS:简介 1. async和await这两个关键字是为了简化异步编程模型而诞生的,使的异步编程跟简洁,它本身并不创建新线程,但在该方法内部开启多线程,则另算. 2. ...