当前位置: 首页 > news >正文

OpenCV如何实现背投(58)

 返回:OpenCV系列文章目录(持续更新中......)

上一篇:OpenCV直方图比较(57)
下一篇:OpenCV如何模板匹配(59)

目标

在本教程中,您将学习:

  • 什么是背投以及它为什么有用
  • 如何使用 OpenCV 函数 cv::calcBackProject 计算背投
  • 如何使用 OpenCV 函数 cv::mixChannels 混合图像的不同通道

cv::mixChannels 和 cv::calcBackProject 都是 OpenCV 库中常用的图像处理函数,主要应用于通道处理、直方图反向投影等操作。

cv::mixChannels 是一个通道处理函数,它可以在不同的图像通道之间进行拷贝、转换和简单操作等处理。该函数的主要思路是,定义一个通道映射表来指定源和目标图像之间的通道拷贝关系,并在映射表中指定每个通道的源图像和目标图像之间的通道位置和通道数。通过 mixChannels 函数,我们可以实现在不同通道间进行像素值的传递和处理等图像操作。

cv::calcBackProject 是一个直方图反向投影函数,它可以用于将某个模型区域的像素在目标图像中得到的直方图投影回去,以便进行目标检测和跟踪等操作。该函数主要思路是,首先使用 calcHist 函数计算模型区域的直方图,然后在目标图像中使用 calcBackProject 函数计算每个像素点在该直方图上的投影分布,并生成反向投影图像。利用反向投影图像,我们可以定位目标区域,并识别出图像中存在的目标区域。

因此,cv::mixChannels 和 cv::calcBackProject 函数通常会一起使用。通过 mixChannels 函数进行通道拷贝和转换处理,然后利用 calcBackProject 函数生成反向投影图像,可以实现更加精确的目标区域定位和识别。这些函数广泛用于计算机视觉和图像处理等领域中的特定应用和算法中。

理论

什么是背投?

  • 背投是一种记录给定图像的像素与直方图模型中像素分布的拟合程度的方法。
  • 为简化起见:对于“背投”,您可以计算要素的直方图模型,然后使用它在影像中查找此要素。
  • 应用示例:如果您有肉色直方图(例如,色相饱和度直方图),则可以使用它来查找图像中的肉色区域:

它是如何工作的?

  • 我们通过使用皮肤示例来解释这一点:
  • 假设您已经根据下图获得了皮肤直方图(色相饱和度)。此外,直方图将是我们的模型直方图(我们知道它代表了肤色的样本)。您应用了一些蒙版来仅捕获皮肤区域的直方图
  •  

  • 现在,让我们想象一下,你得到另一个手部图像(测试图像),如下所示:(及其各自的直方图):

     

  • 我们想要做的是使用我们的模型直方图(我们知道它代表皮肤色调)来检测测试图像中的皮肤区域。步骤如下
    1. 在我们的测试图像的每个像素即p(i,j)中,收集数据并找到该像素的相应箱位置即 h{i,j}, s{i,j} )。
    2. 在相应的 bin 中查找模型直方图  h{i,j}, s{i,j}  - 并读取 bin 值。
    3. 将此图柱值存储在新图像 (BackProjection) 中。此外,您可以考虑先对模型直方图进行归一化,以便您可以看到测试图像的输出。
    4. 应用上述步骤,我们得到以下测试图像的 BackProjection 图像:

  1. 在统计方面,存储在 BackProjection 中的值表示测试图像中的像素属于皮肤区域的概率,基于我们使用的模型直方图。例如,在我们的测试图像中,较亮的区域更有可能是皮肤区域(实际上确实如此),而较暗区域的可能性较小(请注意,这些“黑暗”区域属于带有一些阴影的表面,这反过来又会影响检测)。

C++代码
 

  • 这个程序是做什么的?
    • 加载图像
    • 将原始格式转换为 HSV 格式,并仅分离用于直方图的 Hue 通道(使用 OpenCV 函数 cv::mixChannels )
    • 让用户输入用于计算直方图的箱数。
    • 计算直方图(并在条柱更改时更新它)和同一图像的背投。
    • 在窗口中显示背投和直方图。

  • 可下载代码
    • 单击此处获取基本版本(在本教程中解释)。
    • 对于稍微花哨的东西(使用 H-S 直方图和 floodFill 为皮肤区域定义蒙版),您可以查看改进的演示
    • ...或者,您可以随时查看示例中的经典 CamshiftDemo。
  • 代码一览:
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"#include <iostream>using namespace cv;
using namespace std;Mat hue;
int bins = 25;void Hist_and_Backproj(int, void* );int main( int argc, char* argv[] )
{CommandLineParser parser( argc, argv, "{@input |Back_Projection_Theory0.jpg| input image}" );samples::addSamplesDataSearchSubDirectory("doc/tutorials/imgproc/histograms/back_projection/images");Mat src = imread(samples::findFile(parser.get<String>( "@input" )) );if( src.empty() ){cout << "Could not open or find the image!\n" << endl;cout << "Usage: " << argv[0] << " <Input image>" << endl;return -1;}Mat hsv;cvtColor( src, hsv, COLOR_BGR2HSV );hue.create(hsv.size(), hsv.depth());int ch[] = { 0, 0 };mixChannels( &hsv, 1, &hue, 1, ch, 1 );const char* window_image = "Source image";namedWindow( window_image );createTrackbar("* Hue bins: ", window_image, &bins, 180, Hist_and_Backproj );Hist_and_Backproj(0, 0);imshow( window_image, src );// Wait until user exits the programwaitKey();return 0;
}void Hist_and_Backproj(int, void* )
{int histSize = MAX( bins, 2 );float hue_range[] = { 0, 180 };const float* ranges[] = { hue_range };Mat hist;calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, ranges, true, false );normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );Mat backproj;calcBackProject( &hue, 1, 0, hist, backproj, ranges, 1, true );imshow( "BackProj", backproj );int w = 400, h = 400;int bin_w = cvRound( (double) w / histSize );Mat histImg = Mat::zeros( h, w, CV_8UC3 );for (int i = 0; i < bins; i++){rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ),Scalar( 0, 0, 255 ), FILLED );}imshow( "Histogram", histImg );
}

解释

读取输入图像:

CommandLineParser parser( argc, argv, "{@input |Back_Projection_Theory0.jpg| input image}" );samples::addSamplesDataSearchSubDirectory("doc/tutorials/imgproc/histograms/back_projection/images");Mat src = imread(samples::findFile(parser.get<String>( "@input" )) );if( src.empty() ){cout << "Could not open or find the image!\n" << endl;cout << "Usage: " << argv[0] << " <Input image>" << endl;return -1;}

将其转换为 HSV 格式:

 Mat hsv;cvtColor( src, hsv, COLOR_BGR2HSV );

在本教程中,我们将仅将 Hue 值用于我们的一维直方图(如果您想使用更标准的 H-S 直方图,请查看上面链接中的更高级代码,这会产生更好的结果):

 hue.create(hsv.size(), hsv.depth());int ch[] = { 0, 0 };mixChannels( &hsv, 1, &hue, 1, ch, 1 );
  • 如您所见,我们使用函数 cv::mixChannels 仅从 hsv 图像中获取通道 0(色相)。它获取以下参数:
    • &HSV:将从中复制通道的源数组
    • 1:源数组的数量
    • 色相(&C):复制通道的目标数组
    • 1:目标数组的数量
    • ch[] = {0,0}:指示如何复制通道的索引对数组。在本例中,将 &hsv 的 Hue(0) 通道复制到 &hue 的 0 通道(1 通道)
    • 1:索引对数
  • 为用户创建用于输入图格值的跟踪栏。对 Trackbar 的任何更改都意味着对 Hist_and_Backproj回调函数的调用。

 const char* window_image = "Source image";namedWindow( window_image );createTrackbar("* Hue bins: ", window_image, &bins, 180, Hist_and_Backproj );Hist_and_Backproj(0, 0);

显示图像并等待用户退出程序:

 imshow( window_image, src );// Wait until user exits the programwaitKey();

Hist_and_Backproj功能:初始化 cv::calcHist 所需的参数。条柱数量来自 Trackbar:

 int histSize = MAX( bins, 2 );float hue_range[] = { 0, 180 };const float* ranges[] = { hue_range };

计算直方图并将其归一化为范围 [0,255]

 Mat hist;calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, ranges, true, false );normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );

 通过调用函数 cv::calcBackProject 获取同一图像的反向投影

 Mat backproj;calcBackProject( &hue, 1, 0, hist, backproj, ranges, 1, true );
  • 所有参数都是已知的(与用于计算直方图的参数相同),只是我们添加了 BackProj 矩阵,它将存储源图像 (&hue) 的反向投影
  • 显示 backproj:

 imshow( "BackProj", backproj );

绘制图像的一维色相直方图:

 int w = 400, h = 400;int bin_w = cvRound( (double) w / histSize );Mat histImg = Mat::zeros( h, w, CV_8UC3 );for (int i = 0; i < bins; i++){rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ),Scalar( 0, 0, 255 ), FILLED );}imshow( "Histogram", histImg );

结果

以下是使用示例图像的输出(你猜怎么着?另一只手)。您可以使用 bin 值,您将观察它如何影响结果:

参考文献:

1、《Back Projection》-----Ana Huamán

相关文章:

OpenCV如何实现背投(58)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV直方图比较(57) 下一篇&#xff1a;OpenCV如何模板匹配(59) 目标 在本教程中&#xff0c;您将学习&#xff1a; 什么是背投以及它为什么有用如何使用 OpenCV 函数 cv::calcBackP…...

5-在Linux上部署各类软件

1. MySQL 数据库安装部署 1.1 MySQL 5.7 版本在 CentOS 系统安装 注意&#xff1a;安装操作需要 root 权限 MySQL 的安装我们可以通过前面学习的 yum 命令进行。 1.1.1 安装 配置 yum 仓库 # 更新密钥 rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022# 安装Mysql…...

【Jenkins】持续集成与交付 (八):Jenkins凭证管理(实现使用 SSH 、HTTP克隆Gitlab代码)

🟣【Jenkins】持续集成与交付 (八):Jenkins凭证管理(实现使用 SSH 、HTTP克隆Gitlab代码) 1、安装Credentials Binding、git插件2、凭证类型及用途3、(用户名和密码类型)凭证的添加和使用3.1 用户密码类型3.2 测试凭证是否可用3.3 开始构建项目3.3 查看结果(进入Jenk…...

开源模型应用落地-CodeQwen模型小试-SQL专家测试(二)

一、前言 代码专家模型是基于人工智能的先进技术&#xff0c;它能够自动分析和理解大量的代码库&#xff0c;并从中学习常见的编码模式和最佳实践。这种模型可以提供准确而高效的代码建议&#xff0c;帮助开发人员在编写代码时避免常见的错误和陷阱。 通过学习代码专家模型&…...

Arch Linux安装macOS

安装需要的包 sudo pacman -S qemu-full libvirt virt-manager p7zip yay -S dmg2img安装步骤 cd ~ git clone --depth 1 --recursive https://github.com/kholia/OSX-KVM.git cd OSX-KVM # 选择iOS版本 ./fetch-macOS.py #将上一步下载的BaseSystem.dmg转换格式 dmg2img -…...

接口自动化框架篇:Pytest + Allure报告企业定制化实现!

接口自动化框架是现代软件开发中的重要组成部分&#xff0c;能够帮助开发团队提高测试效率和质量。本文将介绍如何使用Pytest作为测试框架&#xff0c;并结合Allure报告进行企业定制化实现。 目标规划 在开始编写接口自动化测试框架之前&#xff0c;我们需要先进行目标规划。…...

保持 Hiti 证卡打印机清洁的重要性和推荐的清洁用品

在证卡印刷业务中&#xff0c;保持印刷设备的清洁至关重要。特别是对于 Hiti 证卡打印机来说&#xff0c;它们是生产高质量证卡的关键工具。保持设备清洁不仅可以保证打印质量和效率&#xff0c;还可以延长其使用寿命。本文将探讨保持 Hiti 证卡打印机清洁卡的重要性&#xff0…...

Unity C#的底层原理概述

文章目录 前言IL与IL2CPP总结 前言 看到底层二字&#xff0c;会感到很高深&#xff0c;好似下一秒就要踏入深渊。实际上&#xff0c;对于C#底层的理解非常简单&#xff0c;比冒泡排序这种基础算法还要简单。 底层的两种机制&#xff1a;Mono和IL2CPP。 IL2CPP其中的"2&qu…...

国产数据库的发展势不可挡

前言 新的一天又开始了&#xff0c;光头强强总不紧不慢地来到办公室&#xff0c;准备为今天一天的工作&#xff0c;做一个初上安排。突然&#xff0c;熊二直接进入办公室&#xff0c;说&#xff1a;“强总老大&#xff0c;昨天有一个数据库群炸了锅了&#xff0c;有一位姓虎的…...

权益商城系统源码 现支持多种支付方式

简介&#xff1a; 权益商城系统源码&#xff0c;支持多种支付方式&#xff0c;后台商品管理&#xff0c;订单管理&#xff0c;串货管理&#xff0c;分站管理&#xff0c;会员列表&#xff0c;分销日志&#xff0c;应用配置。 上传到服务器&#xff0c;修改数据库信息&#xff…...

python安装问题及解决办法(pip不是内部或外部命令也不是可运行)

pip是python的包管理工具&#xff0c;使python可在cmd&#xff08;命令行窗口&#xff0c;WinR后输入cmd&#xff09;中执行 针对 “pip不是内部或外部命令也不是可运行” 问题&#xff0c;需要在安装的时候将python添加到环境变量中 上图第三个选项必须勾选才能在cmd中使用pi…...

Json高效处理方法

一、参考我之前的博客,Delphi可以很方便的把类和结构体转换成JSON数据,但是数据量大了,就会非常之慢,1万条数据需要20秒左右。如果引用Serializers单元,那么100万数据只需要4秒左右,每秒处理20万+,速度还是很快的。 二、写一个简单的类  TPeople = class private …...

若依分离版-前端使用echarts组件

1 npm list:显示已安装的模块 该命令用于列出当前项目的所有依赖关系&#xff0c;包括直接依赖和间接依赖。执行 npm list 时&#xff0c;npm 将从当前目录开始&#xff0c;递归地列出所有已安装的模块及其版本信息 npm list 2 npm outdated:用于检查当前项目中的npm包是否有…...

android native开发

framwork 一些重要的流程都是要放到native中做的 原因也很简单&#xff0c;效率&#xff0c;尤其是针对性能优化方面的&#xff0c;更离不开native开发 目前针对native开发也回顾下&#xff0c;总结下经验 1 jni开发有两种&#xff0c;app端一般是静态模式&#xff0c;要有jav…...

Partisia Blockchain 生态zk跨链DEX上线,加密资产将无缝转移

在 5 月 1 日&#xff0c;由 Partisia Blockchain 与 zkCross 创建合作推出的 Partisia zkCrossDEX 在 Partisia Blockchain 生态正式上线。Partisia zkCrossDEX 是 Partisia Blockchain 上重要的互操作枢纽&#xff0c;其融合了 zkCross 的 zk 技术跨链互操作方案&#xff0c;…...

Vue3组合式API + TS项目中手写国际化插件

文章目录 1. 在项目中创建一个国际化插件的文件i18n.ts2. 创建语言模块json3. 注册插件4. 语言切换组件5. 使用插件(ts中使用全局需注意点) 1. 在项目中创建一个国际化插件的文件i18n.ts <!-- plugins/i18n.ts --> export const i18nPlugin {install(app: any, option:…...

深入解析Jackson的ObjectMapper:核心功能与方法指南

com.fasterxml.jackson.databind.ObjectMapper 是Jackson库的核心类&#xff0c;负责JSON序列化与反序列化的重任。本文旨在详细介绍其成员属性和方法&#xff0c;帮助开发者更好地利用Jackson进行Java对象与JSON数据之间的转换操作。 初始化与配置 构造与复制 默认构造函数…...

计算机是如何执行指令的

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…...

Jetson Orin NX L4T35.5.0平台相机stop导致系统死机问题调试

1. 环境 硬件:国产OrinNX套件 系统版本: L4T35.5.0 相机: SDI 相机,1080P50fps 2. 问题描述 移植驱动已经开始正常采集相机图像,但是会出现以下问题: 采集流程如下: (1)start SDI camera (2)gst-launch-1.0采集图像 gst-launch-1.0 v4l2src device=/dev/vide…...

【个人博客搭建】(18)使用Quartz.NET 定时备份数据库

Quartz.NET在系统主要承担的一些关键功能&#xff1a; 任务调度&#xff1a;Quartz.NET 允许开发人员创建、调度和管理定时任务&#xff0c;支持简单触发器和Cron表达式等多样化的触发策略。灵活性&#xff1a;Quartz.NET 提供了灵活的任务安排机制&#xff0c;不仅支持基于时间…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...