calHist()-使用OpenCV和C++计算直方图

news2024/12/23 9:16:16

calHist()-使用OpenCV和C++计算直方图

在计算机视觉中,几乎处处都使用直方图。对于阈值计算,我们使用灰度直方图。对于白平衡,我们使用直方图。对于图片中的对象跟踪,比如CamShift技术,我们使用颜色直方图,采用颜色直方图作为特征。

在更抽象的意义上,从梯度直方图形成 HOG 和 SIFT 描述符。

直方图也是一种视觉词袋表示,广泛用于图像搜索引擎和机器学习中。而且,这很可能不是您第一次在研究中看到直方图。

那么,为什么直方图会派上用场呢?

因为直方图描绘了一组数据频率分布。事实证明,查看这些频率分布是开发简单图像处理技术的主要方法…以及真正强大的机器学习算法。

这篇博文将总结图像直方图,以及如何使用 OpenCV 和 C++ 从视频中计算颜色直方图。

1. 什么是直方图

可以将直方图视为显示图像强度分布的图形。X 轴为像素值(通常范围为 0 到 255),Y 轴为图片中的像素数。

这只是查看图像的不同方式。当您查看图像的直方图时,您可能会感觉到图像的对比度、亮度、强度分布等。

今天几乎所有的图像处理软件都包含直方图功能。

请添加图片描述

2. OpenCV C++实现

2.1 OpenCV 中的 calHist() 函数

cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])

使用calHist函数来实现直方图,参数解析:

1. images:这是`uint8`或`float32`源图像。
1. channels:它是计算直方图的通道索引。如果输入是灰度图像,则值为[0]。要计算彩色图像中蓝色、绿色或红色通道的直方图,请传递[0] 、[1]或[2] 。
1. mask:计算直方图的区域,None表示整幅图像区域
1. histSize:Bin数目,必须用方括号括起来。传递[256]表示全像素范围
1. range:通常是[0,256];

2.2 代码

#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>


const int histSize = 256;

void drawHistogram(cv::Mat& b_hist,cv::Mat& g_hist,cv::Mat& r_hist)
{
    int hist_w = 512;
    int hist_h = 400;
    int bin_w = cvRound((double)hist_w / histSize);

    cv::Mat histImage(hist_h, hist_w, CV_8UC3, cv::Scalar(0, 0, 0));

    cv::normalize(b_hist, b_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
    cv::normalize(g_hist, g_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
    cv::normalize(r_hist, r_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());

    for (int i = 1; i < histSize; i++) 
    {
      cv::line(
          histImage,
          cv::Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
          cv::Point(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i))),
          cv::Scalar(255, 0, 0), 2, 8, 0);
      cv::line(
          histImage,
          cv::Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
          cv::Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))),
          cv::Scalar(0, 255, 0), 2, 8, 0);
      cv::line(
          histImage,
          cv::Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
          cv::Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))),
          cv::Scalar(0, 0, 255), 2, 8, 0);
    }

    cv::namedWindow("calcHist Demo", cv::WINDOW_AUTOSIZE);
    cv::imshow("calcHist Demo", histImage);

}
int main(int argc, char **argv) 
{
  cv::Mat src, dst;

  cv::VideoCapture cap;
  if (argc != 2)
    cap.open(0);
  else
    cap.open(argv[1]);

  if (!cap.isOpened()) {
    std::cerr << "Failed to load webcam/Video ...\n";
    return -1;
  }

  for (;;) 
  {
    if(!cap.read(src)) 
    {
      std::cerr << "Cannot read file\n";
      break;
    }
    cv::imshow("Src", src);
    std::vector<cv::Mat> bgr_planes;
    cv::split(src, bgr_planes);


    float range[] = {0, 256};
    const float *histRange = {range};

    bool uniform = true;
    bool accumulate = false;

    cv::Mat b_hist, g_hist, r_hist;

    cv::calcHist(&bgr_planes[0], 1, 0, cv::Mat(), b_hist, 1, &histSize,
                 &histRange, uniform, accumulate);
    cv::calcHist(&bgr_planes[1], 1, 0, cv::Mat(), g_hist, 1, &histSize,
                 &histRange, uniform, accumulate);
    cv::calcHist(&bgr_planes[2], 1, 0, cv::Mat(), r_hist, 1, &histSize,
                 &histRange, uniform, accumulate);

    drawHistogram(b_hist,g_hist,r_hist);

    if (cv::waitKey(30) == 27)
      break;
  }

  return 0;
}

2.3 代码解析

  • 首先读取我们的输入文件,使用cap.read()方法逐帧读取视频。
  • 使用split()函数,将多通道数组(即 BGR)划分为单独的单通道数组,并将其存储在bgr_planes.
  • 然后我们计算每个通道的直方图并将值存储在变量b_hist, g_hist, r_hist中。
  • 在直方图中,我们希望我们的Bin具有相同的大小,并且我们希望在开始时清除我们的直方图,因此,我们将uniformaccumulate设置为true
  • 计算直方图后,我们创建一个图像histImage来显示我们的直方图。
  • 然后我们在每个通道的每个像素处使用cv::line绘制线,即b_hist, g_hist, r_hist

2.4 输出

在这里插入图片描述

3. OpenCV Python实现

3.1 灰度直方图

calHist函数接收以下参数

cv2.calcHist([img], channels, mask, bins, ranges)

  • 图像列表
  • 通道列表
  • mask
  • bins数目
  • ranges,例如[0, 255]

在这里插入图片描述

from matplotlib import pyplot as plt
import cv2 as cv

img = cv.imread('lego.png')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

hist = cv.calcHist([gray], [0], None, [256], [0, 256])

plt.figure()
plt.title('Grayscale histogram')
plt.xlabel('Bins')
plt.ylabel('# of pixels')
plt.plot(hist)
plt.xlim([0, 256])
plt.ylim([0, 2000])
plt.show()

cv.waitKey(0)

3.2 彩色直方图

在这里插入图片描述

在这里插入图片描述

# Color histogram
from matplotlib import pyplot as plt
import cv2 as cv

img = cv.imread('lego.png')
chans = cv.split(img)
colors = 'b', 'g', 'r'

plt.figure()
plt.title('Flattened color histogram')
plt.xlabel('Bins')
plt.ylabel('# of pixels')

for (chan, color) in zip(chans, colors):
    hist = cv.calcHist([chan], [0], None, [256], [0, 255])
    plt.plot(hist, color=color)
    plt.xlim([0, 256])
    plt.ylim([0, 1200])

plt.show()
cv.waitKey(0)

3.3 模糊案例

# Blurring
import cv2 as cv

def trackbar(x):
    x = cv.getTrackbarPos('blur x','window')
    y = cv.getTrackbarPos('blur x','window')
    blurred = cv.blur(img, (x, y))
    cv.imshow('window', blurred)
    cv.displayOverlay('window', f'blur = ({x}, {y})')

img = cv.imread('lego.png')
cv.imshow('window', img)
cv.createTrackbar('blur x', 'window', 0, 4, trackbar)
cv.createTrackbar('blur y', 'window', 0, 4, trackbar)

cv.waitKey(0)
cv.destroyAllWindows()

参考目录

https://opencv-tutorial.readthedocs.io/en/latest/histogram/histogram.html
https://anothertechs.com/programming/cpp/opencv/calculate-histogram/

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

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

相关文章

SpringCloud Alibaba 之 Config配置中心,Redis分布式锁详解

目录 1.服务配置中心 1.1 服务配置中心介绍 1.2 Nacos Config 实践 1.2.1 Nacos config 入门案例 1.2.2 Nacos 配置动态刷新 1.2.3 配置共享 1.2.4 nacos 几个概念 2.分布式锁 2.1 分布式锁介绍 2.2 Redisson 2.2.1 Redisson 实践 2.2.2 Redisson 原理 1.服务配置中心…

HTTPS协议详解

https是http over TLS&#xff08;transport security layer&#xff09;的缩写。也即说明http协议是不安全的&#xff0c;是TLS协议保证的安全。协议层级图如下: 我们常说https协议是安全的&#xff0c;主要是指两点&#xff1a; 第一&#xff0c;通信两端可以进行身份验证。…

复习一周,面了京东和百度,不小心都拿了Offer...

我个人情况是5年软件测试经验&#xff0c;在家复习了一周&#xff0c;面了京东和百度&#xff0c;都顺利拿下offer&#xff0c;下面是我的面试经历分享&#xff0c;希望能带来一些不一样的启发和帮助。 两家公司最常问的就是下面这些问题&#xff1a; 请介绍一下你之前做过哪些…

万用表位数的定义以及对应的ADC位数

万用表的精度通常会用几位半来描述&#xff1a; 比如大部分普通的万用表是 3 / 的精度&#xff0c;也就是俗称的3位半。 也就是说这个万用表最多显示4个数字&#xff0c;其中3位可以显示完整的0~9&#xff0c; 而这位是4个数字中的最高位&#xff0c;2代表只能显示0和1两个数…

【OAI】OAI5G核心网VPP-UPF网元分析

文章目录 VPP_UPF_CONFIG_GENERATION.mdVPP UPF Configuration GenerationEnvironment variablesInterfacesInterface Configuration ExamplesCentral UPFA-UPFI-UPFUL CL FEATURE_SET.mdVPP_UPG_CLI参考文献 VPP_UPF_CONFIG_GENERATION.md VPP UPF Configuration Generation …

(十三)地理数据库创建——进一步定义数据库①

地理数据库创建——进一步定义数据库① 目录 地理数据库创建——进一步定义数据库① 1.建立索引1.1建立属性索引1.2修改空间索引 2.创建子类和属性域2.1属性域2.2子类型2.3属性分割和合并2.4属性域操作2.4.1建立属性域2.4.2修改属性域2.4.3关联属性域 2.5子类型操作2.5.1建立子…

动态规划--青蛙跳台阶

青蛙跳台阶 前言青蛙跳台阶题目最优解结构性质画图分析发现规律验证规律 动规表达式青蛙跳台阶与斐波那契数列的不同之处 递归实现代码实现测试结果递归过程画图分析 非递归实现代码实现对比分析 前言 斐波那契数列每次学都有不一样的体会&#xff0c;从最开始简单理解就是&am…

无监督域适应 (UDA)(2)

本帖介绍UDA 的一个分支&#xff1a;bi-classifier adversarial learning。 一、回顾 在介绍 bi-classifier adversarial learning 之前&#xff0c;先来回忆一下 adversarial generation framework, 因为前者是基于后者的改进。 如图1所示&#xff0c;左边表示的是1&#xf…

DeepSORT 论文精读

摘要 SORT&#xff08;Simple Online and Realtime Tracking&#xff09; we integrate appearance information to improve the performance of SORT 集成外观信息来提高SORT的表现 we are able to track objects through longer periods of occlusions, effectively reduci…

JVM学习05:内存模型

JVM学习05&#xff1a;内存模型 1、java内存模型 很多人将java 内存结构与java 内存模型傻傻分不清&#xff0c;java 内存模型是 **Java Memory Model&#xff08;JMM&#xff09;**的意思。 JMM 定义了一套在多线程读写共享数据时&#xff08;成员变量、数组&#xff09;时…

UE4/5对背景音乐的调整设置

音乐是一个游戏必不可少的因素。 而在游戏设置中&#xff0c;必不可少的就有对背景音乐的声音大小进行设置&#xff0c;而我们需要的就是如何对背景音乐进行设置&#xff1a; 准备两个蓝图&#xff0c;分别是音效类和音效类混合。 然后打开音效类&#xff0c;我们可以看见下图…

如何用postman进行http接口测试,这篇文章绝对会颠覆你的认知

目录 前言 优点&#xff1a; 1、什么是POSTMAN 2、新建一个项目 2、新增一个用例 3、添加请求信息 4、post请求参数 5、添加头信息 6、预处理和结果检查 7、全局变量与环境变量 8、导出用例为代码 9、批量执行用例 前言 HTTP的接口测试工具有很多&#xff0c;可以进…

贪心法——黑白连线问题

一、问题描述 黑白连线Time Limit: 1000 MSMemory Limit: 1000 KB Description 给定直线上2n个点的序列P[1,2,… ,2n]&#xff0c;每个点P[i]要么是白点要么是黑点&#xff0c;其中共有n个白点和n个黑点&#xff0c; 相邻两个点之间距离均为1&#xff0c;请设计一个算法将每…

第六章:C语言的数组

在我的生活中&#xff0c;有许许多多的东西&#xff0c;有强迫症的小伙伴们&#xff0c;喜欢把它们分类到一个地方保存&#xff0c;这样一来&#xff0c;用的时候就按分类的形式来找自己需要的东西&#xff0c;而C语言也是如此&#xff0c;当有多个整形的数字是&#xff0c;就可…

steam搬砖详细解说,CSGO游戏搬砖的18个疑问?

看到这边文章进来的都是想了解steam搬砖&#xff0c;做个副业&#xff0c;我希望你可以认真把这个看完再考虑要不要做&#xff0c;适不适合自己去做&#xff0c;首先steam搬砖这个项目是需要有周转本金的&#xff0c;因为需要购买饰品道具&#xff0c;至于多少&#xff0c;这个…

7种《软件测试用例设计方法》解读及工作场景解析

1、等价类划分法 等价类划分法是一种将输入、输出、内部值等划分为若干个等价类的黑盒测试设计技术。在这种方法中&#xff0c;我们假设同一等价类的数据会被程序以相同的方式处理。 例如&#xff1a;一个允许输入年龄的程序&#xff0c;允许的年龄范围是1到100。在这种情况下…

Vue Test Utils前端单元测试

含义 单元测试&#xff08;unit testing&#xff09;&#xff0c;是指对软件中的最小可测试单元进行检查和验证。在提供了经过测试的单元的情况下&#xff0c;系统集成过程将会大大地简化。流行框架 Mocha (https://mochajs.cn/)、Jest (https://www.jestjs.cn/) Mocha Chai…

asp.net web api 后端服务器在调试时跨域问题的解决方案

跨域在发布时&#xff0c;在iis设置中 https://www.cnblogs.com/babietongtianta/p/6488985.html 在开发调试时&#xff0c;program.cs中添加 和各种方法&#xff0c;都不可以。 后来在iisexpress中设置&#xff0c;解决了。 在右下角iisexpress 右键 双击打开applicationho…

PCL学习十:Segmentation-分割

参考引用 Point Cloud Library黑马机器人 | PCL-3D点云 PCL点云库学习笔记&#xff08;文章链接汇总&#xff09; 1. 引言 点云分割是根据空间、几何和纹理等特征对点云进行划分&#xff0c;使得同一划分区域内的点云拥有相似的特征。点云的有效分割往往是许多应用的前提&#…

【OAI】部署5GSA独立组网网络切片例程及例程解析

文章目录 摘要引言关键技术介绍5G核心网核心网网元功能 网络切片OAIDocker官方例程详解整体介绍具体详解网络切片架构部署概览与说明1-41.预先准备5.部署OAI 5G核心网6.获取基站仿真docker镜像7.部署基站仿真8.通信测试9.分析结果10. 使用多切片的UE11. 解除部署11.1解除RAN部署…