颜色特征提取(一)——颜色直方图(opencv实现)

article/2025/9/28 13:27:01

    直方图——再讲颜色直方图之前,先简单介绍一下直方图。  直方图作为一种简单有效的基于统计特性的特征描述子,在计算机视觉领域广泛使用。它的优点主要体现在两个方面:一是对于任意一个图像区域,直方图特征的提取简单方便;其二,直方图表征图像区域的统计特性,可以有效表示多模态的特征分布,并且本身具备一定的旋转不变性。因此,在计算机视觉领域,基于不同底层特征的各种新颖直方图描述子层出不穷,包括亮度直方图,颜色直方图,HOG,局部二值模式直方图[等。其中颜色直方图是目标跟踪领域最为广泛使用的描述子,然而传统的颜色直方图对光照变化敏感,同时目标区域内像素位置分布被完全忽略。

  颜色特征——是一种全局特征,描述了图像或图像区域所对应的景物的表面性质。一般颜色特征是基于像素点的特征,此时所有图像或图像区域的像素都有各自的贡献。由于颜色对图像或图像区域的方向、大小等变化不敏感,所以颜色特征不能很好地捕捉图像中对象的局部特征。另外,仅使用颜色特征查询时,如果数据库很大,常会将许多不需要的图像也检索出来。颜色直方图是最常用的表达颜色特征的方法,其优点是不受图像旋转和平移变化的影响,进一步借助归一化还可以不受图像尺度变化的影响,其缺点是没有表达出颜色空间分布的信息。

 

(颜色直方图)

       A color histogram of an image represents the distribution of the composition of colors in the image. It shows dif-ferent types of colors appeared and the number of pixels in each type of the colors appeared. The relation between a color histogram and a luminance histogram is that a color histogram can be also expressed as “Three Color Histogr-ams”, each of which shows the brightness distribution of each individual Red/Green/Blue color channel.

颜色直方图在OpenCV的的实现:

    OpenCV里面提供的计算图像直方图的API函数calcHist,用法:

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

OpenCV官网参数详细注释

parameters: 
第一个参数:源输入(图像)数组,必须是深度和大小均相同的CV_8U或者CV_32F(即uchar或者float)图片,每一个可以是任意通道的; 
第二个参数:源输入数组中的图片个数; 
第三个参数:用来计算直方图的通道维数的数组,第一张图片的通道由0到arrays[0].channels()-1列出,第二张图片的通道从arrays[0].channels()到arrays[0].channels()+arrays[1].channels()-1,以此类推,而该参数就是从通道序列中选取一子序列,参与直方图计算的是子序列而不是所有通道序列; 
第四个参数:可选的掩模,如果该矩阵不是空的,则必须是8位的并且与arrays[i]的大小相等,掩模的非零值标记需要在直方图中统计的数组元素; 
第五个参数:输出直方图,是一个稠密或者稀疏的dims维的数组; 
第六个参数:直方图的维数,必须为正,并且不大于CV_MAX_DIMS(当前的OpenCV版本中为36,即最大可以统计36维的直方图); 
第七个参数:用于指出直方图数组每一维的大小的数组,即指出每一维的bin的个数的数组; 
第八个参数:用于指出直方图每一维的每个bin的上下界范围(数组)的数组,当直方图是均匀的(uniform =true)时,对每一维i指定直方图的第0个bin的下界和最后一个即第histSize[i]-1个bin的上界,也就是说对均匀直方图来说,每一个ranges[i]都是一个两个元素的数组【指出该维的上下界】。当直方图不是均匀的时,每一个ranges[i]数组都包含histSize[i]+1个元素; 
第九个参数:直方图是否均匀的标志;【指定直方图每个bin统计的是否是相同数量的灰度级】; 
第十个参数:累加标志;
 

calcHist函数的channels参数和narrays以及dims共同来确定用于计算直方图的图像;首先dims是最终的直方图维数,narrays指出了arrays数组中图像的个数,其中每一幅图像都可以是任意通道的【只要最终dims不超过36即可】。

如果channels参数为0,则narrays和dims必须相等,否则弹出assert,此时计算直方图的时候取数组中每幅图像的第0通道。当channels不是0的时候,用于计算直方图的图像是arrays中由channels指定的通道的图像,channels与arrays中的图像的对应关系,如channels的参数说明的,将arrays中的图像从第0幅开始按照通道摊开排列起来,然后channels中的指定的用于计算直方图的就是这些摊开的通道。

假设有arrays中只有一幅三通道的图像image,那么narrays应该为1,如果是想计算3维直方图【最大也只能是3维的】,想将image的通道2作为第一维,通道0作为第二维,通道1作为第三维,则可以将channels设置为channesl={2,0,1};这样calcHist函数计算时就按照这个顺序来统计直方图。

 

OpenCV实现计算HSV空间颜色直方图程序:

 

#include "stdafx.h"
/*计算hsv图像的直方图*/
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"using namespace std;
using namespace cv;class CalcHistogram
{
private:int histSize[3];         //直方图项的数量float hranges[2];        //h通道像素的最小和最大值float sranges[2];float vranges[2];const float *ranges[3];  //各通道的范围int channels[3];         //三个通道int dims;public:CalcHistogram(int hbins = 30, int sbins = 32, int vbins = 32){histSize[0] = hbins;histSize[1] = sbins;histSize[2] = vbins;hranges[0] = 0; hranges[1] = 180;sranges[0] = 0; sranges[1] = 256;vranges[0] = 0; vranges[1] = 256;ranges[0] = hranges;ranges[1] = sranges;ranges[2] = vranges;channels[0] = 0;channels[1] = 1;channels[2] = 2;dims = 3;}Mat getHistogram(const Mat &image);void getHistogramImage(const Mat &image);
};Mat CalcHistogram::getHistogram(const Mat &image)
{Mat hist;calcHist(&image,1,channels,Mat(),hist,dims,histSize,ranges,true,      //直方图每一维的histSize是均匀的false);return hist;
}void CalcHistogram::getHistogramImage(const Mat &image)
{Mat hist = getHistogram(image);int scale = 4;int hbins = histSize[0];int sbins = histSize[1];int vbins = histSize[2];float *hist_sta = new float[sbins];float *hist_val = new float[vbins];float *hist_hue = new float[hbins];memset(hist_val, 0, vbins * sizeof(float));memset(hist_sta, 0, sbins * sizeof(float));memset(hist_hue, 0, hbins * sizeof(float));for (int s = 0; s < sbins; s++){for (int v = 0; v < vbins; v++){for (int h = 0; h<hbins; h++){float binVal = hist.at<float>(h, s, v);hist_hue[h] += binVal;hist_val[v] += binVal;hist_sta[s] += binVal;}}}double max_sta = 0, max_val = 0, max_hue = 0;for (int i = 0; i<sbins; ++i){if (hist_sta[i]>max_sta)max_sta = hist_sta[i];}for (int i = 0; i<vbins; ++i){if (hist_val[i]>max_val)max_val = hist_val[i];}for (int i = 0; i<hbins; ++i){if (hist_hue[i]>max_hue)max_hue = hist_hue[i];}Mat sta_img = Mat::zeros(240, sbins*scale + 20, CV_8UC3);Mat val_img = Mat::zeros(240, vbins*scale + 20, CV_8UC3);Mat hue_img = Mat::zeros(240, hbins*scale + 20, CV_8UC3);for (int i = 0; i<sbins; ++i){int intensity = cvRound(hist_sta[i] * (sta_img.rows - 10) / max_sta);rectangle(sta_img, Point(i*scale + 10, sta_img.rows - intensity), Point((i + 1)*scale - 1 + 10, sta_img.rows - 1), Scalar(0, 255, 0), 1);}for (int i = 0; i<vbins; ++i){int intensity = cvRound(hist_val[i] * (val_img.rows - 10) / max_val);rectangle(val_img, Point(i*scale + 10, val_img.rows - intensity), Point((i + 1)*scale - 1 + 10, val_img.rows - 1), Scalar(0, 0, 255), 1);}for (int i = 0; i<hbins; ++i){int intensity = cvRound(hist_hue[i] * (hue_img.rows - 10) / max_hue);rectangle(hue_img, Point(i*scale + 10, hue_img.rows - intensity), Point((i + 1)*scale - 1 + 10, hue_img.rows - 1), Scalar(255, 0, 0), 1);}imshow("Shist", sta_img);imshow("Vhist", val_img);imshow("Hhist", hue_img);delete[] hist_sta;delete[] hist_val;delete[] hist_hue;
}int main()
{Mat src = imread("C:\\Users\\59235\\Desktop\\image\\girl1.jpg"), hsv;if (!src.data){cout << "error, the image is not built!" << endl;return -1;}cvtColor(src, hsv, CV_BGR2HSV);imshow("src", src);imshow("hsv", hsv);CalcHistogram h;h.getHistogram(hsv);h.getHistogramImage(hsv);waitKey();return 0;
}

亦或者是用实现RGB空间的颜色直方图:

//计算图像RGB空间的颜色直方图
#include<opencv2\opencv.hpp>  
#include<iostream>  
using namespace std;
using namespace cv;class HistogramND {
private:Mat image;//源图像  int hisSize[1], hisWidth, hisHeight;//直方图的大小,宽度和高度  float range[2];//直方图取值范围  const float *ranges;Mat channelsRGB[3];//分离的BGR通道  MatND outputRGB[3];//输出直方图分量  
public:HistogramND() {hisSize[0] = 256;hisWidth = 400;hisHeight = 400;range[0] = 0.0;range[1] = 255.0;ranges = &range[0];}//导入图片  bool importImage(String path) {image = imread(path);if (!image.data)return false;return true;}//分离通道  void splitChannels() {split(image, channelsRGB);}//计算直方图  void getHistogram() {calcHist(&channelsRGB[0], 1, 0, Mat(), outputRGB[0], 1, hisSize, &ranges);calcHist(&channelsRGB[1], 1, 0, Mat(), outputRGB[1], 1, hisSize, &ranges);calcHist(&channelsRGB[2], 1, 0, Mat(), outputRGB[2], 1, hisSize, &ranges);//输出各个bin的值  for (int i = 0; i < hisSize[0]; ++i) {cout << i << "   B:" << outputRGB[0].at<float>(i);cout << "   G:" << outputRGB[1].at<float>(i);cout << "   R:" << outputRGB[2].at<float>(i) << endl;}}//显示直方图  void displayHisttogram() {Mat rgbHist[3];for (int i = 0; i < 3; i++){rgbHist[i] = Mat(hisWidth, hisHeight, CV_8UC3, Scalar::all(0));}normalize(outputRGB[0], outputRGB[0], 0, hisWidth - 20, NORM_MINMAX);normalize(outputRGB[1], outputRGB[1], 0, hisWidth - 20, NORM_MINMAX);normalize(outputRGB[2], outputRGB[2], 0, hisWidth - 20, NORM_MINMAX);for (int i = 0; i < hisSize[0]; i++){int val = saturate_cast<int>(outputRGB[0].at<float>(i));rectangle(rgbHist[0], Point(i * 2 + 10, rgbHist[0].rows), Point((i + 1) * 2 + 10, rgbHist[0].rows - val), Scalar(0, 0, 255), 1, 8);val = saturate_cast<int>(outputRGB[1].at<float>(i));rectangle(rgbHist[1], Point(i * 2 + 10, rgbHist[1].rows), Point((i + 1) * 2 + 10, rgbHist[1].rows - val), Scalar(0, 255, 0), 1, 8);val = saturate_cast<int>(outputRGB[2].at<float>(i));rectangle(rgbHist[2], Point(i * 2 + 10, rgbHist[2].rows), Point((i + 1) * 2 + 10, rgbHist[2].rows - val), Scalar(255, 0, 0), 1, 8);}cv::imshow("R", rgbHist[0]);imshow("G", rgbHist[1]);imshow("B", rgbHist[2]);imshow("image", image);}
};int main() {string path = "C:\\Users\\59235\\Desktop\\image\\girl1.jpg";HistogramND hist;if (!hist.importImage(path)) {cout << "Import Error!" << endl;return -1;}hist.splitChannels();hist.getHistogram();hist.displayHisttogram();waitKey(0);return 0;
}

实验结果:

 H(hue):                    S(saturation):          V(value) :                  HSV空间的颜色直方图:

RGB空间颜色直方图:

RGB与HSV空间的比较:

(1)模型区别:

RBG模型:原点到白色顶点的中轴线是灰度线,r、g、b三分量相等,强度可以由三分量的向量表示

 

HSV模型:按色彩、深浅、明暗来描述的。H是色彩S是深浅, S = 0时,只有灰度;V是明暗,表示色彩的明亮程度,但与光强无直接联系。

(2)优缺点:

RGB空间:在图像处理中,最常用的颜色空间是RGB模型,常用于颜色显示和图像处理,三维坐标的模型形式,非常容易被理解。但RGB颜色空间的均匀性非常差,且两种颜色之间的直觉差异色差不能表示为改颜色空间中两点间的距离。

HSV空间:相对于RGB空间,HSV空间能够非常直观的表达色彩的明暗,色调,以及鲜艳程度,方便进行颜色之间对的对比,也方便感情的传达。但缺点是不能直接把颜色值传达给显示器,在转换过程中消耗系统资源。


http://chatgpt.dhexx.cn/article/co5JnPKl.shtml

相关文章

一般颜色直方图

颜色直方图是一种用于图像处理和分析的图表&#xff0c;它可以显示图像中不同颜色的数量。通常&#xff0c;颜色直方图会将颜色分成几个色调区间&#xff0c;每个区间对应一个条形图&#xff0c;其中条形图的高度表示该色调区间中的像素数量。通过颜色直方图&#xff0c;你可以…

网络爬虫Jsoup

简介 网络爬虫&#xff08;又称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;更经常的称为网页追逐者&#xff09;&#xff0c;是一种按照一定的规则&#xff0c;自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、…

【Java】Jsoup爬虫快速入门案例

1、前言 该技术博客是根据B站狂神说Java教程的笔记总结&#xff0c;希望能为大家带来帮助&#xff01; 2、Jsoup实战案例 爬虫可以理解为爬取数据&#xff0c;所谓爬取数据就是&#xff1a; 获取请求返回的页面信息&#xff0c;筛选出我们想要的数据 如果想要爬取数据&#…

android爬虫框架jsoup,Android笔记之JSoup爬虫入门

前言 闲扯一些没用的&#xff0c;写这篇文章之前是有点私心的&#xff0c;因为之前评论某简书大v的文章是鸡汤&#xff0c;瞬间被拉黑&#xff0c;连个解释和说明的机会都没有&#xff0c;文章语言干涩&#xff0c;内容平平&#xff0c;于是就好奇到底是些什么样的人喜欢和吹捧…

Java的Jsoup爬虫

Java的Jsoup爬虫&#xff0c;爬携程酒店评分&#xff0c;保存数据库中 前言一、Jsoup爬虫pom二、逻辑代码部分1.首先我们要先确定爬取的东西&#xff0c;这边我就以携程的酒店评分为例子。2.Jsoup进行解析具体要求爬的内容3.接下来我们就是将爬取的数据存入数据库中 总结 前言 …

使用Jsoup爬虫爬取相关图片

一、Jsoup概述 jsoup 是一款Java 的HTML解析器&#xff0c;可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API&#xff0c;可通过DOM&#xff0c;CSS以及类似于jQuery的操作方法来取出和操作数据。 主要功能&#xff1a; 1. 从一个URL&#xff0c;文件或字符串…

jsoup爬虫实战详解之新浪

** jsoup爬虫实战详解之新浪 ** 今天分享一个之前困扰了一段时间的关于jsoup爬取新浪网页信息的踩坑总结。 在实现以上功能的之前我门首先要了解两个重点&#xff1a;1.关于jsoup的爬取细节以及教程&#xff0c;爬取时所要了解jsoup的相关标签&#xff1a;具体的自己大家感兴…

Java JSOUP爬虫学习分享

昨天从狂神大佬那学习了如何用jsoup爬去网站数据&#xff0c;现在整理了一下给大家分享一下。 先创建一个名叫JsoupPojo的实体类用来装入数据。 Data public class JsoupPojo {private String src;private String name; } 下面是将用来爬取的方法封装成了一个工具类 Compon…

java jsoup爬虫

前言&#xff1a;在日常开发中&#xff0c;我们必定是与我们的数据源打交道&#xff0c;我们的数据源无非就那么几个 1.数据库2.爬虫数据 3.第三方系统交互&#xff0c;这里介绍java 中网页版的爬虫jsoup的使用 1.首先导入我们的jar包 maven坐标如下 org.jsoup jsoup 1.13.1 c…

Jsoup爬虫并解析网页

Jsoup爬虫并解析网页 京东搜索 java&#xff0c;爬取有关java的商品信息 1、获取请求 String url"https://search.jd.com/Search?keywordjava";2、解析网页。&#xff08;Jsoup返回的Document对象就是浏览器的Document对象&#xff09; 所有js中操作Document对象的…

Jsoup爬虫入门实战

一、Jsoup介绍 jsoup 是一款基于 Java 的HTML解析器&#xff0c;它提供了一套非常省力的API&#xff0c;不但能直接解析某个URL地址、HTML文本内容&#xff0c;而且还能通过类似于DOM、CSS或者jQuery的方法来操作数据&#xff0c;所以 jsoup 也可以被当做爬虫工具使用。 相关…

Jsoup爬虫实例

一、简介 jsoup 是一款Java 的HTML解析器&#xff0c;可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API&#xff0c;可通过DOM&#xff0c;CSS以及类似于jQuery的操作方法来取出和操作数据。&#xff08;来源百度&#xff09; 二、准备 首先你需要找到一个你…

使用Jsoup实现网络爬虫

一、什么是Jsoup&#xff1f; jsoup是一款Java的HTML解析器、可以通过URL获取DOM元素并解析&#xff0c;也可对HTML文本内容进行解析&#xff0c;jsoup提供了一套非常简单的方法&#xff0c;类似于CSS、JQuery的操作方法对元素或者是数据进行操作。 二、Jsoup的特点及作用 从…

Java学习笔记:爬虫-用Jsoup解析网页

什么是爬虫 1、爬虫&#xff1a;程序代替人的人工操作&#xff0c;自动获取网页内容&#xff0c;并且从其中提取出来有价值信息。 2、原始&#xff1a;调用Http的类向服务器发出请求&#xff0c;获得HTML&#xff0c;然后用正则表达式等去分析。缺点&#xff1a;难度高。 3、…

jsoup爬虫

文章目录 1、jsoup爬虫简单介绍2、相关代码2.1导入pom依赖2.2、图片爬取2.3、图片本地化 3、百度云链接爬虫 1、jsoup爬虫简单介绍 jsoup 是一款 Java 的HTML 解析器&#xff0c;可通过DOM&#xff0c;CSS选择器以及类似于JQuery的操作方法来提取和操作Html文档数据。 这两个…

解析卷积神经网络学习笔记——魏秀参

第二章 CNN基本部件 1.理解批处理和随机梯度下降&#xff1a; 训练模型时随机选取n个训练样本作为一个batch&#xff08;批输入&#xff09;&#xff0c;那么经过设计好的卷积神经网络就可以输出n个预测值&#xff0c;对这n个预测值求其损失函数&#xff08;注意损失函数绝不是…

【干货】卷积神经网络Alex-Net、VGG-Nets、Network-In-Network案例分析

目录 Alex-Net 网络模型 VGG-Nets 网络模型 Network-In-Network 本文将以 Alex-Net、VGG-Nets、Network-In-Network 为例&#xff0c;分析几类经典的卷积神经网络案例。 在此请读者注意&#xff0c;此处的分析比较并不是不同网络模型精度的“较量”&#xff0c;而是希望读者…

2018年国内十大技术突破:22纳米光刻机、大型航天器回收

https://www.toutiao.com/a6639830026990649860/ 2018-12-28 08:11:39 盘点这一年的核心技术&#xff1a;22纳米光刻机、450公斤人造蓝宝石、0.12毫米玻璃、大型航天器回收、盾构机“弃壳返回”、远距离虹膜识别……哪一个不夺人眼球&#xff01; 1 智能水刀削铁断金 10月份的…

AI的螺旋式上升?今日头条AI掌门人马维英离职,“重返”清华从事培育科研工作

2020-07-29 01:22:49 作者 | 蒋宝尚 编辑 | 丛 末 据媒体报道&#xff0c;字节跳动副总裁、人工智能实验室主任马维英离职&#xff0c;将到清华大学智能产业研究院任职&#xff0c;加入正在筹备该产业院的原百度总裁张亚勤团队。 对于马维英离职一事&#xff0c;字节跳动也做…

超全深度学习细粒度图像分析:项目、综述、教程一网打尽

在本文中&#xff0c;来自旷视科技、南京大学和早稻田大学的研究者对基于深度学习的细粒度图像分析进行了综述&#xff0c;从细粒度图像识别、检索和生成三个方向展开论述。此外&#xff0c;他们还对该领域未来的发展方向进行了讨论。 &#xff08;CV&#xff09;是用机器来理解…