| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> Opencv meanStdDev mean函数详解 -> 正文阅读 |
|
[人工智能]Opencv meanStdDev mean函数详解 |
阅读了一下Opencv求均值和标准差的源码,总结下来,愿渡有缘人。 meanStdDev 函数在mean.dispatch.cpp中实现,计算均值和方差的公式如下: ? meanStdDev这个函数的输入是src和mask,mask矩阵里为0位置的元素不被求和if( mask[i] ){才求和}; 这个函数的输出也是两个矩阵,这个输出矩阵的维数应该是channels * 1,每个通道存储相应的和(sum)或平方和(sqsum),如果空间太大,后面的空间会被设置为0. ?下面先说一下要理解这个函数的一些先决条件: (1)NAryMatIterator类:这是一个N元矩阵迭代器,这个迭代器可同步处理多个矩阵,常用在处理src和mask的情况。每个NAryMatIterator::pannels是一个连续的地址空间,pannels是整体矩阵的切片。不连续的地址空间出现在如Mat(src, Rect(1, 1, 3, 3))的情况。就是用Rect截取了src矩阵的一部分,这个部分矩阵的地址空间不连续。 也有很多人写了关于这个类的详解,但是最终还是看源码上的注释才懂了的。 (2)这个函数调用了一个求和、求平方和的函数
是通过getSumSqrFunc()获取一个函数数组得到的。 这个函数的输入是src,mask 输出是:没有被mask的元素的和(保存在sum所指的变量内)、元素的平方和(保存在sqsum) 返回值:处理元素的长度len 如果src是多个通道,sum[0],sum[1]分别存储相应通道的和 (3)AutoBuffer:这个类简单,就相当于new (4)这个函数里OCL/OVX/IPP:和图形加速、GPU相关,Opencv编译的时候应该没有使能这些选项,我也没有细究这些,高人可以补充一下。 (5)CV_INSTRUMENT_REGION():这个宏Opencv里随处可见,我也没有细究,应该是标识下面的代码在链接过程应该放在哪个段内。(放在.code的指令区段内) 正题,解释一下这个函数内使用的变量的含义和难懂的语句: (1)total:每个pannels的尺寸大小,这个是Pannels的总大小。 (2)blockSize:每次处理的元素个数,被初始化为total (3)_buf(cn*4):如果有3个通道,则对于通道一,使用_buf[0,3,6,9],通道二使用_buf[1,4,7,10] 其中_buf[0]保存最终的sum,_buf[3]保存最终的sqsum。_buf[6]和_buf[9]保存临时的sum和sqsum。 (4)intSumBlockSize:求和的时候,处理的元素个数超过intSumBlockSize的大小,就将求和的结果加到_buf[0],intSumBlockSize被初始化为1<<15。这个值不能太大,否则求得的sum会超过int类型表示的范围。 (5)?bool?blockSum = depth <= CV_16S: ? ? ? ? ??bool?blockSqSum = depth <= CV_8S: 这两条语句主要是因为求均值,那么元素大小不能超过2个字节,否则图像加起来会超过double(8字节)所能表示的范围;要计算方差,元素不能超过1字节,否则不计算方差。 正常情况这两个变量的值都应该为true (6)?int nz = func( ptrs[0], ptrs[1], (uchar*)sbuf, (uchar*)sqbuf, bsz, cn ); sbuf存储cn个通道的sum,sqbuf存储cn个通道的sqsum,返回处理元素的个数: nz = bsz (7)if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) ){} count为已经处理了的元素个数:已经处理的元素个数不能超过intSumBlockSize,因为sqsum8u返回的和是int类型的。(func就是static int sqsum8u( const uchar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )) 这里count + blockSize的意思是,如果马上要满了,下次循环处理的元素个数就超了intSumBlockSize,就把求得的和保存一下,保存到_buf[0]里面,这个变量是double类型的,所以足够存储一副图像的sum。 (8)nz0:count的值在处理的元素个数马上超过intSumBlockSize的时候就会清零,而nz0不会,nz0保存所有的处理过的元素个数。 (9)ptrs[0] += bsz*esz; 最初ptrs[0]指向第一个Pannels数据的首地址,ptrs[0] += bsz*esz就是指针在本Pannel内向后移动bsz*esz个字节。(因为ptrs[0]的类型是char *型) ptrs[1] += bsz;不乘esz是因为如果要计算方差,元素必须是占1个字节 (10)后面的代码就简单了,就是先求均值和方差,然后通过一个2遍的for循环将计算值保存到输出参数内,for循环第一遍保存均值;第二遍保存标准差。 附上源码:
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 19:51:32- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |