前言

  红胖子,来也 !
  做了部分人脸识别后,又回到直方图相关的研究-直方图方向投影。

 

Demo

  
  
  
  
  

 

直方图

 

直方图反向投影

概述

  反向投影是计算像素和直方图模型中像素吻合度的一种方法。
  通俗来说,就是用已知一个对象的直方图模型去目标图像中寻找是否有相似的对象。例如,如果有肤色的直方图,可以使用反向投影来在图像中寻找肤色区域。
  有一点需要注意,反向投影中一般使用HSV色彩空间,使用HS两个通道直方图模型去进行匹配计算。

关于HSV颜色空间

  HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。HSV即色相(Hue)、饱和度(Saturation)、明度(Value),又称HSB(B即Brightness)。色相是色彩的基本属性,就是平常说的颜色的名称,如红色、黄色等。饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。明度(V),取0-max(计算机中HSV取值范围和存储的长度有关)。HSV颜色空间可以用一个圆锥空间模型来描述。

  • 圆锥的顶点处,V=0,H和S无定义,代表黑色;
  • 圆锥的顶面中心处V=max,S=0,H无定义,代表白色;

反向投影原理

  • 步骤一:先将已知的图片进行颜色空间转换为HSV颜色空间;
  • 步骤二:对H通道进行单元划分起二维空间上计算对应直方图;
  • 步骤三:计算直方图空间上的最大值,并进行归一化绘制响应的直方图信息;
  • 步骤四:计算反向投影图像;

计算反向投影函数原型

/** @overload */
void calcBackProject( const Mat* images,
int nimages,
const int* channels,
const SparseMat& hist,
OutputArray backProject,
const float** ranges,
double scale = 1,
bool uniform = true );
/** @overload */
void calcBackProject( InputArrayOfArrays images,
const std::vector<int>& channels,
InputArray hist,
OutputArray dst,
const std::vector<float>& ranges,
double scale );
void calcBackProject( const Mat* images,
int nimages,
const int* channels,
InputArray hist,
OutputArray backProject,
const float** ranges,
double scale = 1,
bool uniform = true );
  • 参数一:const Mat*类型的images,输入的数组(或数组集),它们须为相同的深度(CV_8U或CV_32F)和相同的尺寸,而通道数则可以任意;
  • 参数二:int类型的nimages,输入数组的个数,也就是第一个参数中存放了多少张image;
  • 参数三:const int*类型的channels,需要统计的通道(dim)索引。第一个数组通道从0到images[0].channels()-1,而第二个数组通道从images[0].channels()到images[0].channels()+images[1].channels()–1;
  • 参数四:InputArray类型的hist,输入的直方图;
  • 参数五:OutputArray类型的backProject,目标反向投影阵列,其须为单通道,并且和image[0]有相同的大小和深度;
  • 参数六:const float**类型的ranges,表示每一个维度数组(第六个参数dims)的每一维的边界阵列,可以理解为每一维数值的取值范围;
  • 参数七:double类型的scale,有默认值1,输出的方向投影可选的缩放因子;
  • 参数八:bool类型的uniform,指示直方图是否均匀的标识符,有默认值true;
 

Demo源码

void OpenCVManager::testCalcBackProject()
{
QString fileName1 =
"E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/19.jpg";
cv::Mat srcMat = cv::imread(fileName1.toStdString());
cv::Mat dstMat;
int width = 400;
int height = 300; cv::resize(srcMat, srcMat, cv::Size(width, height)); cv::String windowName = _windowTitle.toStdString();
cvui::init(windowName); cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2,
srcMat.rows * 2),
srcMat.type()); cv::Mat allMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());
allMat = cv::Scalar(0, 0, 0); int bins = 255;
while(true)
{
// 刷新全图黑色
windowMat = cv::Scalar(0, 0, 0); // 原图复制
cv::Mat mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat); {
// 步骤一:先将已知的图片进行颜色空间转换为HSV颜色空间;
cv::Mat hsvMat;
cv::cvtColor(srcMat, hsvMat, cv::COLOR_BGR2HSV);
// 步骤二:对H和S通道进行分离,计算H上的直方图;
cv::Mat hueMat;
hueMat.create(hsvMat.size(), hsvMat.depth());
int channel[] = {0, 0};
cv::mixChannels(&hsvMat, 1, &hueMat, 1, channel, 1);
// 步骤三:计算直方图空间上的最大值,并进行归一化绘制响应的直方图信息;
// 调整bins值2~255
cvui::printf(windowMat, 75 + width * 1, 20 + height * 0, "thresh");
cvui::trackbar(windowMat, 75 + width * 1, 40 + height * 0, 165, &bins, 2, 255);
cv::MatND hueHistMat;
int histSize = MAX(bins, 2);
float hueRange[] = {0, 180};
const float *ranges = {hueRange};
cv::calcHist(&hueMat, 1, 0, cv::Mat(), hueHistMat, 1, &histSize, &ranges, true, false);
cv::normalize(hueHistMat, hueHistMat, 0, 255, cv::NORM_MINMAX, -1, cv::Mat());
// 步骤四:计算反向投影图像
cv::MatND backprojectMat;
cv::calcBackProject(&hueMat, 1, 0, hueHistMat, backprojectMat, &ranges, 1, true); // copy显示
mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
cv::Range(srcMat.cols * 0, srcMat.cols * 1));
cv::cvtColor(backprojectMat, dstMat, cv::COLOR_GRAY2BGR);
cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat); // 对直方图进行均衡化
mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
cv::Range(srcMat.cols * 1, srcMat.cols * 2));
cv::equalizeHist(backprojectMat, dstMat);
cv::cvtColor(dstMat, dstMat, cv::COLOR_GRAY2BGR);
cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
} // 更新
cvui::update();
// 显示
cv::imshow(windowName, windowMat);
// esc键退出
if(cv::waitKey(25) == 27)
{
break;
}
}
}
 

工程模板:对应版本号v1.51.0

  对应版本号v1.51.0

 
 

OpenCV开发笔记(五十七):红胖子8分钟带你深入了解直方图反向投影(图文并茂+浅显易懂+程序源码)的更多相关文章

  1. OpenCV开发笔记(五十六):红胖子8分钟带你深入了解多种图形拟合逼近轮廓(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  2. OpenCV开发笔记(五十五):红胖子8分钟带你深入了解Haar、LBP特征以及级联分类器识别过程(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  3. OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  4. OpenCV开发笔记(六十九):红胖子8分钟带你使用传统方法识别已知物体(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  5. OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  6. OpenCV开发笔记(七十一):红胖子8分钟带你深入级联分类器训练

    前言   红胖子,来也!  做图像处理,经常头痛的是明明分离出来了(非颜色的),分为几块区域,那怎么知道这几块区域到底哪一块是我们需要的,那么这部分就涉及到需要识别了.  识别可以自己写模板匹配.特征 ...

  7. OpenCV开发笔记(七十二):红胖子8分钟带你使用opencv+dnn+tensorFlow识别物体

    前言   级联分类器的效果并不是很好,准确度相对深度学习较低,本章使用opencv通过tensorflow深度学习,检测已有模型的分类.   Demo       可以猜测,1其实是人,18序号类是狗 ...

  8. OpenCV开发笔记(七十三):红胖子8分钟带你使用opencv+dnn+yolov3识别物体

      前言   级联分类器的效果并不是很好,准确度相对深度学习较低,上一章节使用了dnn中的tensorflow,本章使用yolov3模型,识别出具体的分类.   Demo   320x320,置信度0 ...

  9. OpenCV开发笔记(七十四):OpenCV3.4.1+ffmpeg3.4.8交叉编译移植到海思平台Hi35xx平台

    前言   移植opencv到海思平台,opencv支持对视频进行解码,需要对应的ffmpeg支持.   Ffmpeg的移植   Ffmpeg的移植请参考之前的文章:<FFmpeg开发笔记(十): ...

  10. Django开发笔记五

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.页面继承 定义base.html: <!DOC ...

随机推荐

  1. [转帖]ORACLE USERENV函数

    https://www.cnblogs.com/youngerger/p/8862210.html ORACLE USERENV函数 USERENV返回关于当前会话的信息.此信息可以用于编写一个应用程 ...

  2. [转帖]fio工具中的iodepth参数与numjobs参数-对测试结果的影响

    测试环境 3台服务器:ceph配置内外网分离,外网使用万兆线,内网使用千兆线,osd共21个. 1台客户端:安装fio工具.内核客户端,使用万兆线. 测试目的 针对fio工具中的iodepth(队列深 ...

  3. [转帖]什么是拒绝服务(DoS)攻击?

    https://www.cloudflare.com/zh-cn/learning/ddos/glossary/denial-of-service/ 什么是拒绝服务攻击? 拒绝服务(DoS)攻击是一种 ...

  4. 查找linux下面某目录下重名出现的文件以及次数

    find . -name '*.data' -exec basename {} \;| sort | uniq -w32 --all-repeated=separate | uniq -c | sor ...

  5. Redis labs 的安装

    Install and setup This guide shows how to install Redis Enterprise Software, which includes several ...

  6. 神通奥斯卡数据库是否兼容Oracle, 以及参数修改的办法

    1. 最近公司要适配神通数据库, 但是因为一些功能异常.参数可能存在风险. 为了减少问题, 想着简单描述一下这些的处理. 开发和客户给的默认参数建议 1. 不选择 兼容oracle模式 2. 字符集选 ...

  7. 一台不容错过的Java单元测试代码“永动机”

    作者:京东零售 陈志良 作为一名京东的软件匠人,我们开发的软件支撑着数亿的用户,责任是重大的,因此我们深深地敬畏每一行代码,那如何将我们的失误降到最低呢?那就是单元测试,它会让我们树立对代码的自信心. ...

  8. Istio安装和部署

    Istio的版本对k8s的版本是有要求的,不兼容的版本会引发一些隐蔽的错误,安装前先参考下图 版本 目前支持 发行日期 停止维护 支持的 Kubernetes 版本 未测试,可能支持的 Kuberne ...

  9. 人工智能自然语言处理:N-gram和TF-IDF模型详解

    人工智能自然语言处理:N-gram和TF-IDF模型详解 1.N-gram 模型 N-Gram 是一种基于统计语言模型的算法.它的基本思想是将文本里面的内容按照字节进行大小为 N 的滑动窗口操作,形成 ...

  10. 21.14 Python 实现Web指纹识别

    在当今的Web安全行业中,识别目标网站的指纹是渗透测试的常见第一步.指纹识别的目的是了解目标网站所使用的技术栈和框架,从而进一步根据目标框架进行针对性的安全测试,指纹识别的原理其实很简单,目前主流的识 ...