主要介绍利用OpenCV工具提取一幅图像中的颜色直方图特征。所谓颜色直方图,指的是一幅图像中的颜色分布,与图像中的特定的物体无关,只是用来表示人的眼睛观察到的图像中的颜色分布情况,例如说,一幅图中红色占了多少比例,绿色占了多少比例等。

我们知道,计算机色彩显示器采用R、G、B相加混色的原理,通过发射出三种不同强度的电子束,使屏幕内侧覆盖的红、绿、蓝磷光材料发光而产生色彩。在RGB颜色空间中,任意色光F都可以用RGB三色不同分量的相加混合而成。也就是说,图像中每个像素的颜色值都可以用一个三元值(R,G,B)来表示,例如(0,0,0)表示黑色,(0,0,255)表示蓝色,……每个分量的大小从0~255.

那么,我们可以知道一张彩色图像可以由R、G、B三个通道堆叠而成。可以想象成将三张大小相同的纸叠放,然后人眼从上往下看到的图像就是原来的彩色图像。这里,假设图像的分辨率为720576,那么每个通道的长为720,宽为576,单位是像素,总的像素个数就是3720*576.

下面具体介绍颜色直方图,横轴表示bins,也就是颜色分为多少块。假设bins=256,也就是横坐标上每个点表示一个数值,纵坐标表示一幅图中有多少个像素点的值是该数值。如果bins=16,也就是把颜色范围0~255从小到大分为16块,然后图像中落在每块对应的范围的像素点的个数就是每块对应的直方图的高度。

因为opencv默认一张图像是由R、G、B三个通道堆叠形成的,所以首先提取出每个通达的直方图,最后将三个直方图揉在一块。

其中,最主要的就是一个calcHist函数,

void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )

参数较多。

第一个参数表示输入的图像;

第二个参数表示输入的图像个数,一般是 1;

第三个参数表示需要处理的是图像的第几个通道;

第四个参数表示掩模,一般是Mat();

第五个参数是要输出的直方图数组;

第六个参数表示需要统计的直方图通道个数,一般是1;

第七个参数histSize表示划分的区间数,即bins的个数;

第八个参数表示像素的变化范围;后两个参数分别表示是否归一化,和是否累计计算像素个数。

重点关注我标红的参数即可。

代码展示:

#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;int main()
{//读取本地的一张图片Mat srcimage = imread("F:\\6030.png");imshow("原图", srcimage);int channels = 0;int histsize[] = { 256 };float midranges[] = { 0,255 };const float *ranges[] = { midranges };MatND  dsthist;    //要输出的直方图//重点关注calcHist函数,即为计算直方图的函数calcHist(&srcimage, 1, &channels, Mat(), dsthist, 1, histsize, ranges, true, false);  Mat b_drawImage = Mat::zeros(Size(256, 256), CV_8UC3);double g_dhistmaxvalue;minMaxLoc(dsthist, 0, &g_dhistmaxvalue, 0, 0);for (int i = 0;i < 256;i++) {//这里的dsthist.at<float>(i)就是每个bins对应的纵轴的高度int value = cvRound(256 * 0.9 *(dsthist.at<float>(i) / g_dhistmaxvalue)); line(b_drawImage, Point(i, b_drawImage.rows - 1), Point(i, b_drawImage.rows - 1 - value), Scalar(255, 0, 0));}imshow("B通道直方图", b_drawImage);channels = 1;calcHist(&srcimage, 1, &channels, Mat(), dsthist, 1, histsize, ranges, true, false);Mat g_drawImage = Mat::zeros(Size(256, 256), CV_8UC3);for (int i = 0;i < 256;i++) {int value = cvRound(256 * 0.9 *(dsthist.at<float>(i) / g_dhistmaxvalue));line(g_drawImage, Point(i, g_drawImage.rows - 1), Point(i, g_drawImage.rows - 1 - value), Scalar(0, 255, 0));}imshow("G通道直方图", g_drawImage);channels = 2;calcHist(&srcimage, 1, &channels, Mat(), dsthist, 1, histsize, ranges, true, false);Mat r_drawImage = Mat::zeros(Size(256, 256), CV_8UC3);for (int i = 0;i < 256;i++) {int value = cvRound(256 * 0.9 *(dsthist.at<float>(i) / g_dhistmaxvalue));line(r_drawImage, Point(i, r_drawImage.rows - 1), Point(i, r_drawImage.rows - 1 - value), Scalar(0, 0, 255));}imshow("R通道直方图", r_drawImage);add(b_drawImage, g_drawImage, r_drawImage);   //将三个直方图叠在一块imshow("RGB直方图", r_drawImage);waitKey(0);return 0;
}

接下来,绘制HSV颜色空间的直方图。有了RGB颜色直方图,还要HSV干什么。下面介绍HSV颜色空间模型。

HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。HSV即色相(Hue)、饱和度(Saturation)、亮度(Value),色相即颜色的基本属性,饱和度指色彩的纯度,越高则色彩越纯,亮度指色彩的明亮程度。

在RGB颜色空间中,三种颜色分量的取值与所生成的颜色之间的联系并不直观。而HSV颜色空间,更类似于人类感觉颜色的方式,封装了关于颜色的信息:“这是什么颜色?深浅如何?明暗如何?”HSV颜色空间规定的取值范围: H:0360,S:01,V:0~1

在OpenCV中,H:0180,S:0255,V:0~255, H/2,S255,V255

也就是说,这里H通道的取值是和其他两个通道有所不同的,它的范围是0180,因为如果为了堆叠三个通道,强行设置256个bins,那么在第180255个bins上,H通道上会出现为空的情况。

HSV颜色空间特征的提取方法和RGB类似,关键一点就是要将原图像转化为HSV颜色空间的图像,之后再对三个通道分别进行直方图绘制操作即可。

代码展示:

#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;int main()
{Mat srcimage = imread("F:\\6030.png");imshow("原图", srcimage);Mat srcimageHSV;//图像转化HSV颜色空间图像cvtColor(srcimage, srcimageHSV, COLOR_BGR2HSV);imshow("HSV空间图像", srcimageHSV);int channels = 0;int histsize[] = { 256 };float midranges[] = { 0,255 };const float *ranges[] = { midranges };MatND  dsthist;calcHist(&srcimageHSV, 1, &channels, Mat(), dsthist, 1, histsize, ranges, true, false);Mat b_drawImage = Mat::zeros(Size(256, 256), CV_8UC3);double g_dhistmaxvalue;   minMaxLoc(dsthist, 0, &g_dhistmaxvalue, 0, 0);for (int i = 0;i < 256;i++) {int value = cvRound(256 * 0.9 *(dsthist.at<float>(i) / g_dhistmaxvalue));line(b_drawImage, Point(i, b_drawImage.rows - 1), Point(i, b_drawImage.rows - 1 - value), Scalar(255, 0, 0));}imshow("H通道直方图", b_drawImage);channels = 1;calcHist(&srcimageHSV, 1, &channels, Mat(), dsthist, 1, histsize, ranges, true, false);Mat g_drawImage = Mat::zeros(Size(256, 256), CV_8UC3);for (int i = 0;i < 256;i++) {int value = cvRound(256 * 0.9 *(dsthist.at<float>(i) / g_dhistmaxvalue));line(g_drawImage, Point(i, g_drawImage.rows - 1), Point(i, g_drawImage.rows - 1 - value), Scalar(0, 255, 0));}imshow("S通道直方图", g_drawImage);channels = 2;calcHist(&srcimageHSV, 1, &channels, Mat(), dsthist, 1, histsize, ranges, true, false);Mat r_drawImage = Mat::zeros(Size(256, 256), CV_8UC3);for (int i = 0;i < 256;i++) {int value = cvRound(256 * 0.9 *(dsthist.at<float>(i) / g_dhistmaxvalue));line(r_drawImage, Point(i, r_drawImage.rows - 1), Point(i, r_drawImage.rows - 1 - value), Scalar(0, 0, 255));}imshow("V通道直方图", r_drawImage);add(b_drawImage, g_drawImage, r_drawImage);imshow("HSV直方图", r_drawImage);waitKey(0);return 0;
}

说明:HSV三个通道的直方图绘制,我为了区分,用了红绿蓝三种颜色,和RGB通道没有关系。颜色可以自己在程序中更改。其实每个通道都是从不同的角度(色相、饱和度、亮度)来分析图像的。

OpenCV-提取图像中的颜色直方图(RGB、HSV)相关推荐

  1. opencv提取图像中的颜色直方图(RGB、HSV)

    本篇博客主要介绍利用opencv工具提取一幅图像中的颜色直方图特征.所谓颜色直方图,指的是一幅图像中的颜色分布,与图像中的特定的物体无关,只是用来表示人的眼睛观察到的图像中的颜色分布情况,例如说,一幅 ...

  2. 利用OpenCV提取图像中的矩形区域(PPT屏幕等)

    ** 前言 ** 最近参加了大创项目,题目涉及到计算机视觉,学姐发了个修正图像的博客链接,于是打算用这个题目入门OpenCV. 分析问题 照片中的PPT区域总是沿着x,y,z三个轴都有倾斜(如下图), ...

  3. OpenCV提取图像中的垂直线(或者水平线)

    操作过程: 1) 读取原图: 2) 转为灰度图像: 3) 转为二值图像: 4) 定义结构元素: 5) 开操作. void GetLine() {Mat src, grayImg, binImg, de ...

  4. Python Opencv cv2提取图像中某种特定颜色区域(例如黑字白纸背景下的红色公章提取),并将纯色背景透明化

    拜拜PHOTOSHOP- 领导突然让我帮他把公章从图片中抠出来,在确保了不是要做坏事的情况下,我打开了PHOTOSHOP,用魔棒工具一点一点抠,但由于魔棒工具的原理是对比临近区域像素差值,导致封闭字体 ...

  5. Opencv学习笔记(二) 提取图像中的水平线和垂直线

    提取图像中的水平线和垂直线属于基础的形态学操作的应用,原理:根据要提取图形来定义一个特定的结构元素,然后以这个结构相素去遍历图像,进行一系列形态学操作,以此过滤掉其他特征的图形,达到提取的效果. 示例 ...

  6. 使用Python,OpenCV寻找图像中的轮廓

    使用Python和OpenCV查找图像中的形状 1. 效果图 2. 步骤 3. 源码 参考 这篇博客将讨论使用Python和OpenCV查找图像中的形状,具体是 cv2.inRange在图像中查找形状 ...

  7. 用 OpenCV 检测图像中各物体大小

    我们需要定义一个比值,它测量每个给定指标的像素个数. 我将其称为「像素/度量」比率,在下一节中我将更正式地定义它. 1.「像素/度量」比率 为了确定图像中物体的大小,我们首先需要使用一个参考物体进行「 ...

  8. opencv 识别长方形_使用OpenCV检测图像中的矩形

    本文实例为大家分享了OpenCV检测图像中矩形的具体代码,供大家参考,具体内容如下 前言 1.OpenCV没有内置的矩形检测的函数,如果想检测矩形,要自己去实现. 2.我这里使用的OpenCV版本是3 ...

  9. 利用OpenCV检测图像中的多个水果

    OpenCV检测图像中的多个水果 最近面试碰到一个图像算法题,要求: (1)检测一副图像中的多个苹果并标识出来. (2)标识时需要将图像中苹果按照从大到小给定序号,显示出来. 基于以上两点,准备利用C ...

最新文章

  1. 200万?程序员刚拿下华为Offer,这些技巧你必须知道!
  2. Android 学习笔记--android——AsyncTask在Android4.X的机制问题
  3. php 获取js变量
  4. 我眼中的Linux设备树(六 memorychosen节点)
  5. sql语法中 什么值需要用单引号‘’修饰?
  6. Java中已经存在了十几年的一个bug...
  7. css 做幻灯片效果
  8. CSS 布局 - Overflow
  9. 白宫发布太空系统网络安全防护指令
  10. win10虚拟服务器安装xp,win10系统安装自带的xp虚拟机的处理技巧
  11. Bin Code Editor格式化JSON编辑器
  12. 人口logistic模型公式_人口指数增长模型和Logistic模型
  13. CF 86D 莫队(卡常数)
  14. 基于javaweb学生就业管理系统的设计与实现(论文+程序设计+数据库文件)下载
  15. When Hybrid Cloud Meets Flash Crowd: Towards Cost-Effective Service Provisioning--INFOCOM 2015
  16. 我们认为2是第一个素数,3是第二个素数,5是第三个素数,依次类推。 现在,给定两个整数n和m,0<n<=m<=200,你的程序要计算第n个素数到第m个素数之间所有的素数的和,包括第n个素数和第m个素
  17. matlab 区域生长算法生成二值图像边界区域
  18. 译言网、东西网创始人赵嘉敏访谈
  19. 文心ERNIE 3.0 Zeus千亿参数大模型,一键生成“学术范儿”论文标题
  20. 宜人贷-iOS客户端组件化介绍

热门文章

  1. Think In Java | 01 面向对象
  2. OSM地图本地发布(二)-----数据准备
  3. 在CSDN的六载时光,2021年博客之星由谁决定
  4. 传智php52期,感谢一路有你——传智PHP52期就业
  5. 蒙特卡罗算法和拉斯维加斯算法比较
  6. linux 硬盘掉载后重新挂载
  7. Linux下载神器XDM,堪比IDM
  8. CSS 用一个div写个旋转的齿轮(maybe船舵)
  9. errno和strerror
  10. PHP菜鸟如何开始学习PHP语言