OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()

OpenCV学习(二十二) :反向投影:calcHist(),minMaxLoc(),compareHist()

参考博客:
反向投影backproject的直观理解
opencv 反向投影
颜色直方图的计算、显示、处理、对比及反向投影

一、概述

1、官方解释:反向投影是一种记录给定图像中的像素点如何适应直方图模型像素分布的方式。简单的讲,
1)就是首先计算某一特征的直方图模型;(特征可以为色调+饱和度、灰度值等等)
2)然后使用模型去寻找图像中存在的该特征。例如,你有一个肤色直方图(Hue-Saturation直方图),你可以用它(色调和饱和度)来寻找图像中的肤色区域:

2、反向投影图就是图像对应位置像素的数量统计,也可以看做是密度统计。 反向投影图在某一位置(点)的值是原图对应位置(点)的像素值所在原图区间(bins)的总数目。(所以,一个区间点越多,在反向投影矩阵中就越亮。)

3、反向投影中的“反向”指的是从直方图值到反向投影矩阵映射的过程。

4、通过反向投影,原始的图像被简化了,而这个简化的过程实际上就是提取出图像的某个特征。所以我们就可以用这个特征来对比两幅图,如果两幅图的反向投影矩阵相似或相同,那么我们就可以判定这两幅图这个特征是相同的。

5、反向投影的作用:
反向投影用于在输入图像(通常较大)中查找**特定图像(通常较小或者仅1个像素,以下将其称为模板图像)**最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。如图:
在这里插入图片描述

第一个图为源图像,中间的那个小图像是产生用于反向投影的直方图的图像,最后的用直方图均衡化后的结果图像,可以看到,苹果的像素位置几被找到了。

二、calcBackProject()函数

calcBackProject 的基本过程是:
1)拿到 特征图像 (或模板图像)
2)得到 特征图像的直方图
3)拿到测试图像,依据测试图像的每个像素的值,在特征图像的直方图中找到对应的值,然后将直方图的值赋给新的图像,backproject算法就完成了。

void cv::calcBackProject(   
const Mat* images		// 输入图像,图像深度必须位CV_8U,CV_16U或CV_32F中的一种,尺寸相同,每一幅图像都可以有任意的通道数 
int nimages				// 输入图像的数量 
const int* channels 	// 用于计算反向投影的通道列表,通道数必须与直方图维度相匹配,第一个数组的通道是从0到image[0].channels()-1, 
InputArray hist 		// 输入的直方图,直方图的bin可以是密集(dense)或稀疏(sparse) 
OutputArray backProject	// 目标反向投影输出图像,是一个单通道图像,与原图像有相同的尺寸和深度 
const float ranges**	// 直方图中每个维度bin的取值范围 
double scale=1:			// 可选输出反向投影的比例因子 
bool uniform=true:		// 直方图是否均匀分布(uniform)的标识符,有默认值true
)

三、CalcBackProjectPatch()函数

对于calcBackProjectPatch,整个是基于块的形式,利用直方图做匹配,类似于模板匹配,只不过这些模板转换为直方图,而原图中以某点为基准,抠出来作对比的部分也转换为直方图,两个直方图作匹配,匹配的结果作为此点的值。

结果会是一张概率图,概率越大的地方,代表此区域与模板的相似度越高。而且,当模板小于检测的目标时,得到的结果图也能反映出检测区域的形状。这个结果与模板匹配的结果很相似,但利用直方图的方式,就能去除光照变化、边缘遮挡,旋转等因素的影响。另外
基于块的反向投影。这种方法速度很慢,模版图像别弄的太大了。
例如:
1)当模板图像小与目标的时候,作为区域检测器,测试如下:可以找到手区域
在这里插入图片描述
2)当模板等于目标的时候,测试如下:输出图像,较亮的部分就是人的头部大致位置
在这里插入图片描述

详情参考:
opencv 直方图反向投影

函数原型:

void cvCalcBackProjectPatch( 
IplImage** image,   // 输入图像:是一个单通道图像数组,而非实际图像
CvArr* dst,         // 输出结果:是一个单通道32位浮点图像,它的宽度为W-w+1,高度为H-h+1,这里的W和H是输入图像的宽度和高度,w和h是模板图像的宽度和高度
CvSize patch_size,  // 模板图像的大小:宽度和高度
CvHistogram* hist,  // 模板图像的直方图:直方图的维数和输入图像的个数相同,并且次序要一致;例如:输入图像包含色调和饱和度,那么直方图的第0维是色调,第1维是饱和度
int method,         // 对比方式:跟直方图对比中的方式类似,可以是:CORREL(相关)、CHISQR(卡方)、INTERSECT(相交)、BHATTACHARYYA
float factor        // 归一化因子,一般都设置成1,否则很可能会出错;中文、英文以及各路转载的文档都错了,这个参数的实际类型是double,而非float,我看了源代码才搞定这个地方
)

四、mixChannels()函数

mixChannels()函数用于将输入数组的指定通道复制到输出数组的指定通道。
其实我们接触到的,split()和merge(),以及cvtColor的某些形式,都只是mixChannels()的一部分。
参考:
opencv3/C++ mixChannels()详解:4通道图像分割、HSV通道获取

void mixChannels(
const Mat* src, 		//输入数组或向量矩阵,所有矩阵的大小和深度必须相同。
size_t nsrcs, 			//第一个参数src矩阵的数量
Mat* dst, 				//输出数组或矩阵向量,大小和深度必须与src[0]相同
size_t ndsts,			//第三个参数ndsts矩阵的数量
const int* fromTo,		//指定被复制通道与要复制到的位置组成的索引对
size_t npairs 			//fromTo中索引对的数目
);

示例:

#include<opencv2/opencv.hpp>
using namespace cv;int main()
{Mat bgra( 500, 500, CV_8UC4, Scalar(255,255,0,255) );Mat bgr( bgra.rows, bgra.cols, CV_8UC3 );Mat alpha( bgra.rows, bgra.cols, CV_8UC1 );Mat out[] = { rgb, alpha };int from_to[] = { 0, 2, 1, 1, 2, 0, 3, 3 };// 输入1一个矩阵,输出2个举证,4个索引对mixChannels( &bgra, 1, out, 2, from_to, 4 );imshow("bgra", bgra); 	// 青色imshow("bgr", bgr);		// 黄色(通道值改变,色彩空间不变)waitKey(0);return 0;
}

在这里插入图片描述

五、示例:

使用模型直方图(代表手掌的皮肤色调)来检测测试图像中 的皮肤区域。
1)对测试图像中的每个像素(p(i,j),获取色调数据并找到该色调(h(i,j),s(i,j))在直方图中的bin的位置;
2)查询模型直方图中对应的bin-(hi,j,si,j)并读取该bin的数值;
3)将此数值存储在新的图像中(BackProjection)。你也可以先归一化模型直方图,这样测试图像的输出就可以在屏幕显示了;
4)通过对测试图像中的每个像素采用以上步骤,我们得到了下面的BackProjection结果图:
5)使用统计学的语言,BackProjection中存储的数值代表了测试图像中该像素属于皮肤区域的概率。比如上图为例,亮起的区域是皮肤区域的概率更大,而更暗的区域则表示更低的概率(注意手掌内部和边缘的阴影影响了检测的精度)。

#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;Mat g_srcImage,g_hsvImage,g_hueImage;
int g_bins = 30;//直方图组距int main()
{// 1、载入源图,转化为HSV颜色模型g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/shou.jpg", 1);if(!g_srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); return false; }cvtColor( g_srcImage, g_hsvImage, CV_BGR2HSV ); // 转换颜色空间// 2、分离 Hue 色调通道g_hueImage.create( g_hsvImage.size(), g_hsvImage.depth() );  // 创建同尺寸、深度的单通道图int ch[ ] = { 0, 0 };mixChannels( &g_hsvImage, 1, &g_hueImage, 1, ch, 1 );imshow("g_hueImage", g_hueImage);// 3、创建 Trackbar 来输入bin的数目namedWindow( "反向投影图" , CV_WINDOW_AUTOSIZE );createTrackbar("色调组距 ", "反向投影图" , &g_bins, 180, on_BinChange );on_BinChange(0, 0);//进行一次初始化// 4、显示效果图imshow( "【原始图】" , g_srcImage );waitKey(0);return 0;
}

直方图计算 bins(特征空间子区段的数目)回调函数:

void on_BinChange(int, void* )
{// 1、参数准备MatND hist;int histSize = MAX( g_bins, 2 );    // 组距 最小为2float hue_range[] = { 0, 180 };const float* ranges = { hue_range };// 2、计算直方图并归一化// 将handhue取值替换为g_hueImage图像的中心部分,作为特征图像Mat handhue_feature= g_hueImage(Rect(g_hueImage.rows/2-25, g_hueImage.cols/2-25, 50, 50)).clone();// g_hueImageimshow("handhue_feature", handhue_feature); // 显示特征// 将handhue_feature的取值 替换为g_hueImage图像的中心部分,作为特征图像calcHist( &handhue_feature, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false );normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );     // 归一化直方图数值范围为0~255之间// 3、计算 获取反向投影MatND backproj;calcBackProject( &g_hueImage, 1, 0, hist, backproj, &ranges, 1, true );// 4、显示反向投影imshow( "反向投影图", backproj );// 5、绘制直方图的参数准备int w = 400; int h = 400;int bin_w = cvRound( (double) w / histSize );Mat histImg = Mat::zeros( w, h, CV_8UC3 );// 6、绘制直方图for( int i = 0; i < g_bins; i ++ ){ rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ), Scalar( 100, 123, 255 ), -1 ); }// 7、显示直方图窗口imshow( "直方图", histImg );
}

源图+色调图
在这里插入图片描述
特征图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

美国正式宣告将在月球建立永久存在基地

来源&#xff1a;凤凰新闻央视网消息&#xff1a;7月20号是人类首次载人登陆月球50周年纪念日&#xff0c;美国公布了“阿尔忒弥斯计划”的官方标志图案&#xff0c;正式宣告将在月球建立永久存在基地。美国媒体直呼&#xff0c;美国要“占领”月球了。1969年&#xff0c;美国的…

一文看懂5G芯片背后的明争暗斗

来源&#xff1a;鲜枣课堂6月6日工信部正式发放5G商用牌照之后&#xff0c;国内5G网络建设的步伐大幅加快了。越来越多的城市出现了5G基站和5G信号&#xff0c;5G离我们的距离更近了。面对激动人心的5G&#xff0c;我们普通用户最关心的问题&#xff0c;当然是什么时候才能用上…

OpenCV学习(二十三) :模板匹配:matchTemplate(),minMaxLoc()

OpenCV学习(二十三) &#xff1a;模板匹配:matchTemplate() 1、概述 模板匹配是一种最原始、最基本的模式识别方法&#xff0c;研究某一特定对象物的图案位于图像的什么地方&#xff0c;进而识别对象物&#xff0c;这就是一个匹配问题。 它是图像处理中最基本、最常用的匹配方…

CSS3实现图形曲线阴形和翘边阴影

首先&#xff0c;来看看完成之后的效果图&#xff1a; 实现原理 ①曲线阴影实现&#xff1a; 多个阴影重叠&#xff0c;就是正常阴影曲线阴影 正常情况下&#xff0c;有个矩形有正常的阴影&#xff0c;作为主投影&#xff0c;这时候再定义一个有一定弧度圆角的圆角矩形&#xf…

腾飞资本任溶 :互联网大脑,新的天方夜谭?—评《崛起的超级智能》

作者&#xff1a;任 溶 腾飞资本董事长&#xff0c;城市大脑创新合伙人基金管理合伙人因为我做科技产业投资工作&#xff0c;投资领域涉及互联网等新经济、新模式和新技术等&#xff0c;所以这几年总是听到一些言论&#xff0c;诸如“互联网已死”&#xff0c;或者“互联网红利…

OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()

OpenCV学习(二十四 &#xff09;&#xff1a;角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack() 参考博客&#xff1a; Harris角点检测原理详解 Harris角点检测原理及C实现 OpenCV亚像素角点cornerSubPixel()源代码分析 Taylor公式&#xff08;泰勒公式&#x…

无人驾驶技术的7大典型应用场景

来源 | 数据观综合无人驾驶风口来临&#xff0c;引得各方资本竞相追逐。据业内预测&#xff0c;2019年到2020年无人驾驶L3&#xff08;条件自动&#xff09;级别的汽车将实现量产化&#xff0c;2022年后部分企业将实现L4&#xff08;高度自动&#xff09;量产&#xff0c;若要实…

数字图像处理学习笔记(一):特征检测和匹配概述

数字图像处理学习笔记&#xff08;一&#xff09;&#xff1a;特征检测和匹配概述 参考博客&#xff1a; 特征点的匹配SIFT特征详解数字图像处理学习笔记&#xff08;二&#xff09;&#xff1a;SIFT&#xff08;尺度不变特征变换&#xff09;算法 1、特征点概述 如何高效且…

数字图像处理学习笔记(二):SIFT(尺度不变特征变换)算法

数字图像处理学习笔记&#xff08;二&#xff09;&#xff1a;SIFT&#xff08;尺度不变特征变换&#xff09;算法 一、概述&#xff1a; 提到特征点算法&#xff0c;首先就是大名鼎鼎的SIFT算法了。SIFT的全称是Scale Invariant Feature Transform&#xff0c;尺度不变特征变…

微软向马斯克的人工智能公司OpenAI投资10亿美元

来源: 新浪财经新浪美股讯微软(Microsoft)周一宣布&#xff0c;将向埃隆-马斯克(Elon Musk)的OpenAI投资10亿美元&#xff0c;打造能够处理更复杂任务的人工智能。根据声明&#xff0c;通过合作&#xff0c;两家公司将建立新的Azure AI超级计算技术&#xff0c;微软将成为OpenA…

数字图像处理学习笔记(三):ORB算法(尺度不变特征变换)Oriented FAST and Rotated BRIEF

数字图像处理学习笔记&#xff08;三&#xff09;&#xff1a;ORB算法&#xff08;尺度不变特征变换&#xff09;Oriented FAST and Rotated BRIEF 一、概述 参考&#xff1a;特征点匹配特征检测方法汇总 ORB的全称是Oriented FAST and Rotated BRIEF&#xff0c;是目前来说…

华为:对部分顶尖学生实行年薪制 最高200万元

来源&#xff1a;EETOP7月23日上午消息&#xff0c;据华为总裁办签发的电子邮件&#xff0c;华为对部分2019届顶尖学生实行年薪制管理。华为以电邮通知【2019】068号文发布了8名天才少年的年薪方案&#xff0c;这8名人员全部为2019届应届顶尖学生&#xff0c;其年薪的最低限为8…

matplotlib使用GridSpec自定义子图位置 (非对称的子图)

上图的结构可以用一下两种方式画&#xff1a; import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpecfig plt.figure(1) gs GridSpec(3, 3)ax1 plt.subplot(gs[0, :]) ax2 plt.subplot(gs[1, :2]) ax3 plt.subplot(gs[1:, 2]) ax4 plt.subplot(gs[…

大脑简史(1)-历史上的大事件

来源&#xff1a;人机与认知实验室能够上天入地&#xff0c;却不知道自己的大脑&#xff0c;笔者认为这是很多人的疑惑。随着科技的发展&#xff0c;我们能够延伸到的地方越来越多&#xff0c;无论是伸手不见五指的海底&#xff0c;还是扶摇直上九万里的浩渺星空&#xff0c;都…

作业3词频统计

(1). 实现一个控制台程序&#xff0c;给定一段英文字符串&#xff0c;统计其中各个英文单词&#xff08;4字符以上含4字符&#xff09;的出现频率。 答&#xff1a; 从文件读取遍历字符串大写转小写将句子分隔成一个个单词判断是否为单词计算单词出现的频率预估时间10minutes10…

MATLAB报错Invalid ADAPTORNAME specified. Type 'imaqhwinfo' for a list of available ADAPTORNAMEs. Image

MATLAB报错Invalid ADAPTORNAME specified. Type imaqhwinfo for a list of available ADAPTORNAMEs. Image acquisition adaptors may be available as downloadable support packages. Open Support Package Installer to install additional vendors. 这时需要安装两个安装…

陈天奇:十年机器学习科研之路(附链接)

来源&#xff1a;深度学习自然语言处理链接&#xff1a;https://zhuanlan.zhihu.com/p/74249758导读十年前&#xff0c;MSRA的夏天&#xff0c;刚开始尝试机器学习研究的我面对科研巨大的不确定性&#xff0c;感到最多的是困惑和迷茫。十年之后&#xff0c;即将跨出下一步的时候…

QT示例:基于TCP 点对多Socket通讯(server,clients)

QT示例&#xff1a;基于TCP 点对多通讯&#xff08;server,clients&#xff09;一、服务器server二、客户端Client下载&#xff1a;基于TCP 点对多Socket通讯 一、服务器server 因为对于客户端来说&#xff0c;只能连接一个服务器。而对于服务器来说&#xff0c;它是面向多连…

MATLAB GUI的CreateFcn如何创建

看MATLAB关于GUI代码的时候发现有一些function _CreateFcn(hObject, eventdata, handles)函数&#xff0c;那么这类函数是如何创建出出来的呢&#xff1f; 首先在MATLAB中输入guide&#xff0c;打开其中一个GUI文件&#xff0c;现在随便打开一个我之前创建好的GUI&#xff1a;…

文小刚:量子革命是最不可思议的物理革命

来源&#xff1a;科学网人类生活在一个怎样的世界里&#xff1f;凝聚态理论物理学家、美国麻省理工学院终身教授、美国科学院院士文小刚的答案是&#xff1a;“我们生活在量子计算机里面。量子信息是真实的&#xff0c;而所看到的各种物质、人&#xff0c;都是量子信息的虚拟反…