Pixy原理及Opencv实现
2017-02-01 16:54
204 查看
Pixy原理
Pixy的基本思想其实是简单的:利用颜色空间来除去所有用户不感兴趣的背景,提取出前景。但是在实际的环境下却并不好做,特别是摄像头看到的颜色会受到光线的影响,导致颜色的变化(对于这一点,笔者觉得确实是没有办法的,比如红色在黑暗的条件下确实看起来是红色,那么依靠任何颜色空间看到的其实都是黑色,无法区别),因此,对于Pixy这样神奇的产品来讲,他的识别也需要颜色尽量鲜艳,饱和度尽量好的物体,对于背景来讲,也尽量是光线较好、不突变的环境。否则Pixy是“学习”不来的。在笔者看到的Pixy的对于颜色处理的源码中,其核心思想有2个部分,这也是笔者借鉴最多的地方:
1、对像素点的处理
Pixy接收到摄像头的信息格式应该是YUV格式的,在源码的colorlut.cpp的nextHelper函数中,Pixy做了两件事:1、将YUV转为RGB的;2、处理该像素值得到U和V的值,这里的U和V并不是YUV中的UV通道,而是经过了处理,具体处理的代码如下:其中CL_LUT_ENTRY_SCALE变量为15
if (uv) { c = r+g1+b; if (c<miny) { m_x += 2; continue; } u = ((r-g1)<<CL_LUT_ENTRY_SCALE)/c; c = r+g2+b; if (c<miny) { m_x += 2; continue; } v = ((b-g2)<<CL_LUT_ENTRY_SCALE)/c; uv->m_u = u; uv->m_v = v; }
这样做的好处是在U和V的值中,加入亮度的影响,这样得到的U和V值就考虑到了光线亮度对于物体颜色的影响。
2、对感兴趣域的比较统计
对于得到的U和V,Pixy将其作为“学习”的依据,即下面的学习算法均是依靠此处的U和V来进行的,在colorlut.cpp的calcRatios函数中,Pixy对于得到的U和V值进行了如下处理:其中sig是个结构体,其中的元素代表该感兴趣前景的U和V的上下阈值
while(ip->next(&uv)) { if (uv.m_u>sig->m_uMin) counts[0]++; if (uv.m_u<sig->m_uMax) counts[1]++; if (uv.m_v>sig->m_vMin) counts[2]++; if (uv.m_v<sig->m_vMax) counts[3]++; n++; } // calc ratios ratios[0] = (float)counts[0]/n; ratios[1] = (float)counts[1]/n; ratios[2] = (float)counts[2]/n; ratios[3] = (float)counts[3]/n; // calc mean (because it's cheap to do it here) sig->m_uMean = (sig->m_uMin + sig->m_uMax)/2; sig->m_vMean = (sig->m_vMin + sig->m_vMax)/2;
在上段代码中,Pixy对用户给出区域的像素点与上下阈值进行比较统计,得到的统计值决定了“学习”的方向。
3、根据统计进行“学习”
由上部分得到的ratios数组表征了用户给定区域的像素在该阈值左右的分布,假定给定一个该分布情况的界限,则阈值就可以根据当前分布与给定分布之间的大小进行自动调整(Pixy默认的界限是80%,即该阈值可以提取出图像区域80%的像素值):以U值为例,当图像在该阈值作用下,大于U阈
baf1
值最小值的像素点有90%,则说明U阈值的最小值过小,此时应该向下调整,使该阈值增大,反之则反之。具体的代码见下: 其中m_ratio为0.8
for (scale=1<<30, sig->m_uMin=sig->m_uMax=sig->m_vMin=sig->m_vMax=0; scale!=0; scale>>=1) { calcRatios(ip, sig, ratios); if (ratios[0]>m_ratio) sig->m_uMin += scale; else sig->m_uMin -= scale; if (ratios[1]>m_ratio) sig->m_uMax -= scale; else sig->m_uMax += scale; if (ratios[2]>m_ratio) sig->m_vMin += scale; else sig->m_vMin -= scale; if (ratios[3]>m_ratio) sig->m_vMax -= scale; else sig->m_vMax += scale; }
根据上述代码可以看到,Pixy在学习的过程中对一幅图像(用户感兴趣)学习了30次,最终根据反馈得到了较好的阈值。
Opencv实现
其实知道了原理之后,想用Opencv对一幅图像进行处理并得到较好的阈值是比较容易的,笔者也对该算法进行了尝(chao)试(xi),但是效果十分不好,1、不能进行较好的前景提取;2、处理速度十分慢。对于以上两个问题,个人认为还是对于YUV的格式没有把握好,导致中间运算出现问题(悼念三分钟尝试失败)。但是笔者并没有放弃,把该算法移植到了HSV空间上,说是移植,其实中间去掉了一些处理,比如移植的算法没有考虑亮度对颜色的影响(> <),但是确实可以给定一个区域进行自“学习”了,收获还是不小,想要进行参考的同学可以到该地址进行下载http://download.csdn.net/detail/wubaobao1993/9745837
最后上两个图,是该算法的实际效果
相关文章推荐
- 简单线性迭代聚类SLIC的原理及opencv实现
- 图像平滑技术之核算子、均值滤波、中值滤波、高斯滤波、双边滤滤、导向滤波的原理概要及OpenCV代码实现
- 【算法+OpenCV】基于三次Bezier原理的曲线拟合算法C++与OpenCV实现
- 二维最大熵阈值分割原理与opencv实现
- Sobel算子原理及OpenCv实现
- 基于OpenCV的跳一跳外挂实现原理
- Camshift算法原理及其Opencv实现
- 伽马(Gamma)校正的原理及opencv实现
- RANSAC(随机采样一致算法)原理及openCV代码实现
- Camshift算法原理及其Opencv实现
- Camshift算法原理及其Opencv实现
- 基于opencv人脸检测原理及实现
- 【opencv2】Sobel算子原理与实现
- Camshift算法原理及其Opencv实现
- 直方图均衡原理及opencv实现
- 图像特征检测描述(一):SIFT、SURF、ORB、HOG、LBP特征的原理概述及OpenCV代码实现
- Harris角点检测原理及openCV实现
- Hu不变矩原理及opencv实现
- opencv中的GMM(混合高斯分布)算法原理及C++实现(BackgroundSubtractorMOG)
- 双目相机标定以及立体测距原理及OpenCV实现