Opencv中的直方图(2)计算图像的直方图函数calcHist()的使用

news2024/11/13 16:05:45
  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

计算一组数组的直方图。
函数 cv::calcHist 计算一个或多个数组的直方图。用于递增直方图bin的元组的元素是从相同位置的相应输入数组中获取的。下面的示例展示了如何为彩色图像计算一个2D色调-饱和度直方图。

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
int main( int argc, char** argv )
{
    Mat src, hsv;
    if( argc != 2 || !(src=imread(argv[1], IMREAD_COLOR)).data )
        return -1;
    cvtColor(src, hsv, COLOR_BGR2HSV);
    // Quantize the hue to 30 levels
    // and the saturation to 32 levels
    int hbins = 30, sbins = 32;
    int histSize[] = {hbins, sbins};
    // hue varies from 0 to 179, see cvtColor
    float hranges[] = { 0, 180 };
    // saturation varies from 0 (black-gray-white) to
    // 255 (pure spectrum color)
    float sranges[] = { 0, 256 };
    const float* ranges[] = { hranges, sranges };
    MatND hist;
    // we compute the histogram from the 0-th and 1-st channels
    int channels[] = {0, 1};
    calcHist( &hsv, 1, channels, Mat(), // do not use mask
             hist, 2, histSize, ranges,
             true, // the histogram is uniform
             false );
    double maxVal=0;
    minMaxLoc(hist, 0, &maxVal, 0, 0);
    int scale = 10;
    Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3);
    for( int h = 0; h < hbins; h++ )
        for( int s = 0; s < sbins; s++ )
        {
            float binVal = hist.at<float>(h, s);
            int intensity = cvRound(binVal*255/maxVal);
            rectangle( histImg, Point(h*scale, s*scale),
                        Point( (h+1)*scale - 1, (s+1)*scale - 1),
                        Scalar::all(intensity),
                        -1 );
        }
    namedWindow( "Source", 1 );
    imshow( "Source", src );
    namedWindow( "H-S Histogram", 1 );
    imshow( "H-S Histogram", histImg );
    waitKey();
}

函数原型1

void cv::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

  • 参数 images 源数组。它们都应该具有相同的深度(CV_8U, CV_16U 或 CV_32F),并且具有相同的尺寸。每一个都可以有任意数量的通道。
  • 参数nimages 源图像的数量。
  • 参数channels 用于计算直方图的各维通道列表。第一个数组的通道编号从 0 到 images[0].channels()-1,第二个数组的通道编号从 images[0].channels() 到 images[0].channels() + images[1].channels()-1,依此类推。
  • 参数mask O可选掩码。如果矩阵不为空,它必须是一个与 images[i] 同尺寸的8位数组。非零的掩码元素标记了计入直方图的数组元素。
  • 参数hist 输出直方图,它是一个稠密或稀疏的多维数组。
  • 参数dims 直方图的维数,必须是正数且不大于 CV_MAX_DIMS(在当前 OpenCV 版本中等于 32)。
  • 参数histSize 直方图每个维度的大小数组。
  • 参数ranges 每个维度直方图bin边界的数组。当直方图是均匀的(uniform=true)时,对于每个维度 i,只需指定第0个直方图bin的下(包含)边界 L0 和最后一个直方图bin histSize[i]-1 的上(不包含)边界 UhistSize[i]−1。也就是说,在均匀直方图的情况下,ranges[i] 是一个包含2个元素的数组。当直方图不是均匀的(uniform=false)时,ranges[i] 包含 histSize[i]+1 个元素:L0, U0=L1, U1=L2, …, UhistSize[i]−2=LhistSize[i]−1, UhistSize[i]−1。不在 L0 和 UhistSize[i]−1 之间的数组元素不会被计入直方图。
  • 参数uniform 指示直方图是否是均匀的标志(参见上面的描述)。
  • 参数accumulate 累积标志。如果设置,那么在分配直方图开始时不将其清空。此功能使您能够从几组数组中计算单个直方图,或随时间更新直方图。

函数原型2

这是一个重载的成员函数,为了方便而提供。它与上述函数的不同之处仅在于它接受的参数。
这个变体使用 SparseMat 作为输出。

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

函数原型3

这是一个重载的成员函数,为了方便而提供。它与上述函数的不同之处仅在于它接受的参数。
这个变体只支持均匀直方图。
ranges 参数要么是一个空向量,要么是一个展平的向量,包含 histSize.size() * 2 个元素(即 histSize.size() 个元素对)。每对元素的第一个和第二个元素分别指定下界和上界。

void cv::calcHist
(
	InputArrayOfArrays 	images,
	const std::vector< int > & 	channels,
	InputArray 	mask,
	OutputArray 	hist,
	const std::vector< int > & 	histSize,
	const std::vector< float > & 	ranges,
	bool 	accumulate = false 
)		

代码示例


#include <iostream>
#include <opencv2/opencv.hpp>

int main()
{
    // 加载图像
    cv::Mat image = cv::imread( "/media/dingxin/data/study/OpenCV/sources/images/qiu.jpg", cv::IMREAD_COLOR );

    if ( image.empty() )
    {
        std::cerr << "Error: Image not found or unable to read." << std::endl;
        return -1;
    }

    // 将图像从BGR转换到HSV颜色空间
    cv::Mat hsv;
    cvtColor( image, hsv, cv::COLOR_BGR2HSV );

    // 定义直方图参数
    int hue_bins   = 180;  // 色调范围是从0到179
    int sat_bins   = 256;  // 饱和度范围是从0到255
    int histSize[] = { hue_bins, sat_bins };

    // H和S的范围
    float hue_range[]     = { 0, 180 };
    float sat_range[]     = { 0, 256 };
    const float* ranges[] = { hue_range, sat_range };

    // 指定我们要计算直方图的两个通道(Hue和Saturation)
    int channels[] = { 0, 1 };

    // 创建一个空的直方图
    cv::Mat hist;
    calcHist( &hsv, 1, channels, cv::Mat(),              // 图像,图像数量,通道,掩码
              hist, 2, histSize, ranges, true, false );  // 2D直方图,直方图尺寸,范围

    // 对直方图进行归一化,使其值在 0 到 255 之间
    cv::normalize( hist, hist, 0, 255, cv::NORM_MINMAX, -1, cv::Mat() );

    int hist_w = 512;
    int hist_h = 400;
    int bin_w  = cvRound( ( double )hist_w / hue_bins );
    cv::Mat histImage( hist_h, hist_w, CV_8UC3, cv::Scalar( 0, 0, 0 ) );

    for ( int h = 0; h < hue_bins; h++ )
        for ( int s = 0; s < sat_bins; s++ )
        {
            double binVal = hist.at< float >( h, s );  // 获取直方图值
            int val       = cvRound( binVal );         // 四舍五入
            cv::rectangle( histImage, cv::Point( h * bin_w, hist_h ), cv::Point( ( h + 1 ) * bin_w, hist_h - val ), cv::Scalar( 255, 0, 0 ), -1 );
        }
    cv::imshow( "original image", image );
    cv::imshow( "Hue-Saturation Histogram", histImage );
    cv::waitKey( 0 );

    return 0;
}

运行结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2103082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++设计模式——Template Method模板方法模式

一&#xff0c;模板方法模式的定义 模板方法模式是一种行为型设计模式&#xff0c;它先定义了一个算法的大致框架&#xff0c;然后将算法的具体实现步骤分解到多个子类中。 模板方法模式为算法设计了一个抽象的模板&#xff0c;算法的具体代码细节由子类来实现&#xff0c;从…

Spring Boot中如何禁用Actuator端点安全性?

Spring Boot中如何禁用Actuator端点安全性&#xff1f; 1、为什么考虑禁用&#xff1f;2、如何禁用&#xff1f;方法一&#xff1a;自定义Security配置&#xff08;推荐&#xff09;方法二&#xff1a;绕过安全性&#xff08;不推荐&#xff09; 3、注意事项4、总结 &#x1f4…

Golang | Leetcode Golang题解之第393题UTF-8编码验证

题目&#xff1a; 题解&#xff1a; const mask1, mask2 1 << 7, 1<<7 | 1<<6func getBytes(num int) int {if num&mask1 0 {return 1}n : 0for mask : mask1; num&mask ! 0; mask >> 1 {nif n > 4 {return -1}}if n > 2 {return n}r…

AI机械键盘,罗技推出首款AI机械键盘K98M

在这个智能化日益普及的时代&#xff0c;我们的生活中充斥着各种智能设备。 从智能手机到智能家居&#xff0c;现在连键盘也加入了智能化的行列。罗技&#xff0c;作为知名的电脑配件制造商&#xff0c;最近推出了他们的首款AI机械键盘K98M。这款键盘集成了百度文心一言提供的…

C++设计模式——Observer观察者模式

一&#xff0c;观察者模式的定义 观察者模式是一种行为型设计模式&#xff0c;又被称为"发布-订阅"模式&#xff0c;它定义了对象之间的一对多的依赖关系&#xff0c;当一个对象的状态发生变化时&#xff0c;所有依赖于它的对象都会收到通知并自动更新。 观察者模式…

13、Django Admin创建两个独立的管理站点

admin文件 from .models import Epic, Event, EventHero, EventVillain from django.contrib.admin import AdminSiteclass EventAdminSite(AdminSite):site_header "Events管理"site_title "欢迎您&#xff01;"index_title "管理员"even…

AI自动生成PPT哪个软件好?如何自动生成专业级PPT?

新学期伊始&#xff0c;准备开学演讲稿的你是否还在为制作PPT而烦恼&#xff1f;别担心&#xff0c;现在有了AI的帮助&#xff0c;生成专业且吸引人的PPT变得轻而易举。 本文将为你揭秘4种高效的AI自动生成PPT的方法&#xff0c;让你在新学期的演讲中脱颖而出。无论是简洁明了…

畅游5G高速网络:联发科集成Wi-Fi6E与蓝牙5.2的系统级单芯片MT7922

这周末,除非外面下钞票,否则谁也拦不住我玩《黑神话悟空》(附:两款可以玩转悟空的显卡推荐) IPBrain平台君 集成电路大数据平台 2024年09月03日 17:28 北京 联发科一直以创新技术追赶市场需求…… “不努力向前游就会被海浪拍回岸边…” 芯片设计公司产品层出不穷,想要站…

Redis集群搭建以及用idea连接集群

一、redis的集群搭建&#xff1a; 判断一个是集群中的节点是否可用,是集群中的所用主节点选举过程,如果半数以上的节点认为当前节点挂掉,那么当前节点就是挂掉了,所以搭建redis集群时建议节点数最好为奇数&#xff0c;搭建集群至少需要三个主节点,三个从节点,至少需要6个节点。…

Datawhle X 李宏毅苹果书AI夏令营深度学习笔记之——卷积神经网络

卷积神经网络简介 卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;是一种深度学习模型&#xff0c;尤其擅长处理图像和视频等高维度的数据。CNN 通过模仿人类视觉系统的工作方式&#xff0c;自动学习数据中的空间层次结构&#xff0c;使得它在计算机视…

我找到了一个让ChatGPT稳定通过草莓测试的方法,百试百灵!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…

windows C++ 并行编程-并发和UWP(三)

控制执行线程 Windows 运行时使用 COM 线程模型。 在此模型中&#xff0c;根据对象处理其同步的方式&#xff0c;对象被托管在不同的单元中。 线程安全对象托管在多线程单元 (MTA) 中。 必须通过单个线程访问的对象托管在单线程单元 (STA) 中。 在具有 UI 的应用程序中&#…

系统找不到指定的文件怎么解决?

把U盘插在电脑上&#xff0c;当我打开U盘中的文件时&#xff0c;弹窗提示系统找不到指定的文件&#xff0c;这是什么情况&#xff1f;有谁遇到过吗&#xff1f;大家有没有解决办法&#xff1f; 这个问题可能大家并不陌生&#xff0c;可能也曾遇到过&#xff0c;造成问题出现的原…

DriveLM的baseline复现

DriveLM是一篇很有意思的工作&#xff0c;把自动驾驶跟MLLM结合到一起了&#xff0c;实现端到端的感知or决策规划。 Repo&#xff1a;https://github.com/OpenDriveLab/DriveLM 该工作是基于nuScenes数据集做的&#xff0c;官方paper里给出了数据的具体构建方式&#xff0c;感…

云计算之ECS

目录 一、ECS云服务器 1.1 ECS的构成 1.2 ECS的实例规格 1.3 镜像 1.4 磁盘 1.5 安全组 1.6 网络 1.7 产品结构 二、块存储介绍 2.1 快存储定义 2.2 块存储性能指标 2.3 快存储常用操作-云盘扩容 2.4 块存储常见问题 三、快照介绍 3.1 快照定义 3.2 快照常见问题…

《python语言程序设计》第8章第12题生物信息:找出基因,生物学家使用字母A C T和G构成字符2串建模一个基因组(下)

一、上一个版本 抱歉各位兄弟我感觉这道题我现在的能力有限,不纠结了跳过去.等第3刷的时候解决吧. 可能彼岸就在眼前,但是我累了.等下次吧 这个版本中div_text函数已经可以很好的划分字符串了 但是我发现了一个问题.它间隔字符效果如下 genome_text TTATGTTTTAAGGATGGGGCGTTAG…

CSS - 搜索框小动效

点击搜索框动画变长&#xff0c;搜索框有内容不变&#xff0c;无内容失去焦点&#xff0c;变回原来模样。<div :class"type true ? s_r_z : s_r" click"onChange"><div class"input_s"><input blur"handleBlur" v-mo…

QTC++联合编程之解决代码语句块折叠并中文注释代码块

目录&#xff1a; 一&#xff0c;前言二&#xff0c;解决方法2.1直接折叠代码段落&#xff0c;不命名2.2折叠代码段落并注释&#xff08;中/英文&#xff09;命名2.3使用模板 三&#xff0c;参考文章 一&#xff0c;前言 如果从C#或者从其他语言学习过&#xff0c;一定会感叹ID…

Android实习面经整理第一篇

蔚来Android实习面经 一面(2024/3/11 35min) 自我介绍聊我的本专业说一说MVP架构,MVVM架构 MVP:V层持有P层,用户点击View,把数据发给P层,P层持有M层,然后P层把V层的数据发给M层获取其他数据,最后M层获取完数据后把数据还给P层,更新V层。P层也有V层的引用。MVVM:V层…

使用ElementUI + Vue框架实现学生管理系统前端页面设计

目录 一.什么是ElementUI&#xff1f; 二.使用ElementUI和Vue-cli搭建前端页面 三.具体步骤 1.创建vue-cli项目 2.分析 3.创建组件 四.总结 一.什么是ElementUI&#xff1f; ElementUI是一种网站快速成型工具&#xff0c;一套为开发者&#xff0c;设计师准备的基于Vue2.…