python分析视频文件_一起学opencv-python三十六(视频分析:目标跟踪)

e73a5196094181335e4ce8f4f448b6ddbb362c42.png

上一讲里直接用opencv的stitcher类拼接的话,会损失一部分分辨率,出来的图片是506*1207的,但是这个图像还需要裁剪,也就是列数会小于506。c51b86610a8c73f6cc525b98d5edb67617d29a09.png

这个是可以对不同大小的图片进行拼接的。336f5b6fffee51b09b1f8cb0b1db5a85760844dd.png

不过似乎不稳定。有的时候就会报错。4cbfaefdce233e97d9234bf37b5832ef5b6ab6f8.png

有的时候出来的图片大小不一样:c54fc636df798b71f40014abac95719653acdecd.png

这个应该是和特征匹配有关系,首先如果用的是二进制描述符,那么它本身是基于概率的,然后在match的时候,又有很多随机的方法,比如随机k-d树,那么就可能出现最后符合条件匹配的点对太少,认为两幅图片拼接不了,也可能是足够拼接的,但是匹配的点对有细微的差别,所以出现图片大小不一样,不过这都是我的猜测了,因为我没看过这个类的源码,我只是猜测它是这么做的。

视频分析之目标追踪

如何追踪视频里的目标呢?如果是单一颜色,并且周围背景没有这种颜色,我们而可以把BGR转到HSV,然后用inRange去追踪,但是前面的一般都不太可能实现的。有一种思路是利用特征匹配,并且用SIFT等方法还有旋转和尺度不变性,但是这种是有问题的,因为前一帧和后一帧的特征匹配结果,我们想要的目标的特征点不一定会匹配得很好,有可能效果很差,完全下一帧匹配得是另一个物体,而且特征点检测匹配整个过程花费时间比较长。不过这是一个思路,还有一个思路就是用直方图去匹配。

参考了:https://blog.csdn.net/chen825919148/article/details/7570246bc44d6ec35ca027b667ed3e8bc5ffe01c1e35b51.png

得到ROI得直方图以后,我们对下一帧图像的每个小区域直方图计算和ROI直方图之间的相似度:aa24ebdd1de78e581b6b0e2574f3755807226843.png

本质上来说,视频目标跟踪就是寻找到上面的相似度值最大的位置,即最佳匹配位置。

这个过程用直方图反向投影可以办到,其实前面我们还学习了模板匹配,模板匹配考虑了空间位置,但是它的旋转不变性和尺度不变性就会很差,视频中的目标一般来说都会有旋转或者尺度的变化,一般摄像头是不动的,即便摄像头运动,也很难保证目标不旋转,大小不变化。就像下面的车。而直方图反向投影反而因为舍弃了位置信息而对旋转和尺度变化都有一定的适应性。c9bcc19f8ff4708098a9622632a932f7d52a1450.png

但是其实直方图匹配的结果一般不会像上面的结果那么好,即使阈值化之后,还是会有很多分散的区域。比如下面文章里面:da970c5087f5e5cd9bea3118620e468b7d93fc01.png

69c1dda9295039ea3c4473f6aa30d959db8ddfdc.png

得到的结果都是比较分散的,如何从这些分散的区域找到抑恶个最佳匹配区域呢?这就是我们下面要解决的问题,我觉得最终的目标就是最后选择区域里面包含点的值(这个值是直方图反向投影的结果)的和最大。第一种方法是Meanshift,参考了https://blog.csdn.net/jameshater/article/details/50992155

和https://blog.csdn.net/jinshengtao/article/details/302588335c78efc0b5c721d8e758facf44e0f56fc886e1cb.png

如果这些点是均匀的分布在圆里面,合成向量就是0,也就是不移动,最后的合成向量向哪个方向,说明这个方向的点比较多,为了得到比较好的结果(包含较多的直方图反向投影的较大的值),圆就应该朝这个方向靠近,但是其实这里应该是向质心方向而不是合成向量方向偏移,质心方向和合成向量一般不会在一个方向。da5f029581cf760ec62debfd9f42a1e76f0b53d3.png

上面点的密度我们可以看做是直方图反向投影结果的密度,也就是点多的地方直方图反向投影的结果比较大。49bd2b92284ad21230167a4b80d7f7ff0c43212b.png

e4754a35697e00b187ab6fabbde93a1a0c9092cc.png

我补充几点,其实从上面的描述中我们不难看出来,这个算法毕竟是数值算法,它是有缺点的,因为如果恰好在某个密度不是很大的地方,点均匀分布了(比如全是黑色的区域),那么岂不是圆就不会移动了,所以说能不能收敛到全局最优解,这个和初值的关系很大。下面的gif

是一个例子。1db07aeae66697bc953932a28815da64026443c6.gif

下面来看看Meanshift的数学描述和数学原理:6bdcbfdeea5b511c5d444621873bd0b86ed63ed7.png

7de17ccbb42f1dc62743e15b4af0d1b345566f40.png

4dd27a9583c5b53e00b96076a893363473e058d8.png

下面这段话叙述了引入核函数和权重系数的原因:947569bcf80b236d0f0ecdde228c06af5b3f7747.png

57fb2567930267b02f2a92a52931efe2afa46a27.png

这个核函数别看说的挺麻烦,其实就和卷积核是一个道理,只是给每个位置加了一个权重而已,它遵守的原则就是越接近圆心,权重越大,反之越小。73c67062c298df70cd42ef4739bac0ba1b04f5b6.png

这个不一定收敛到全局最优解。28d5561f992951fc3c1490199250f971f1b9ada1.png

8a8861128a5cffc8ec067c43bd82896dfbfc2d62.png

18b98b165d093e31d60909227393d9ec7887db4b.png

893499934a0f59ef45e45f84d04d1d9a7bb9df4b.png

计算目标新位置就是在计算质心位置。1bd6267e42345540f60e214de01262f4fbc6c18f.png

当然opencv里用meanshift只需要从直方图反向投影的结果开始,这个就比较方便了。

opencv代码:

下面的代码是在HSV的Hue(色调)空间做的直方图匹配。为了防止一些亮度比较低的无效的值干扰,这里计算直方图的时候用了inRange的结果做掩码。这里要过滤掉了s和v通道都比较小的点,我觉得这里更可能是因为它们比较没有特色?4f0a4a20fd24edfca578ba49118b0122a7df4e20.png

530a79c031339f6baea0f85899759777eae0047d.png

先来看一看里面用到的没见过的函数:af3fb266b967f9873141897403bd55ec794cb176.png

初始搜索窗口的格式应该是左上角坐标和宽高。上面用的是视频,我只用两张图来测试。5b4317c752dd573017dd443560181ddddb634c6e.jpgq1.jpg

de99abec3334399ffea53c396dea7da173d35044.jpgq2.jpg

我就来跟踪这个眼镜清洗液。62cb5583392607b2b64e5851da0b6104b6a37269.png

首先定位眼镜清洗液。02ff789c1e131dffd7771e81fcd416a004dca5ba.png

上面的初始窗口是我随便选的位置。结果:157089d841a0bc0f610fb180efb2f3b9f17668b3.png

完全不对。我们看一看这个dst:ac1f1e633518ae33c4b8afcaddef3931d9c6ee0c.png

这下就是因为初始位置选的不好,结果直接给搞到黑色区域了,并且最后的结果和我们的初始窗口大小都不一样。那么我们就再选一个:63c9d96ee043a9984437c8d95f5367dd8c0f1d1d.png

结果:2bf622c4b47f2b2468d83ce5c6f4dae92986d19f.png

好了很多。不过输出的窗口大小还是和初始的不一样呢,有点搞不懂它是怎么变换窗口大小的。我去掉过滤低亮度和饱和度那一步其实结果也还是挺好的:3fbc6eafff105fecbea5f14e90c367460ea474e3.png

还有一种算法叫做CAMSHIFT,它是基于meanshift算法的。

参考https://blog.csdn.net/qq_15947787/article/details/53161768

camshift就是让这个窗口的大小是变化的,来适应尺度和旋转变化,它在1988年被提出。它先用meanshift直到收敛,然后更新窗口大小,它还计算最佳拟合椭圆,然后在更新一次大小?官方里没说,不知道它拟合椭圆是要干嘛?我觉得可以根据拟合的椭圆更新这个窗口的大小和方向。然后再利用新的窗口继续用meanshift直到收敛或者满足停止条件。aa104f87708a3ea37b0a5a5bf1d7b9163fe17e34.png

关于调整的s大小,我查了其它地方说的不太一样。7d90eb6ea60bd7d17bf8bae55d6057af9b493bee.png

这个更新的大小怎么推到出来的我还真的是不知道,如果收敛到全是255的里面的话,如果一开始的窗口大小是a×a,后来就变成了(255/256)**0.5*a×1.2*s,不知道是怎么来的,不过里面用了M00,也就是用了统计信息,虽然还是不知道这个形式怎么来的。下面gif显示了这个过程。df9254c1b6d006ba2093306ce3f4605a6ff59a20.gif

代码:65115955a6c92645cfe8ebe4d0cda6a87c37d6f5.png

a708cfbf759f3f21e1d045a5c16d7865712384ef.png

其实meanshift已经用了camshift的方法来放大了,看官方文档的解释,所以上面用meanshift才会出现结果和初始窗口大小不一样。288ae0ee4a0a9e9a578b88a056a36068c5ee12b8.png

试一下camshift:593c5c7866ea08b1598288497dff3875333c2f52.png

结果还是和meanshift有所不同的。这个ret里面应该是存放着的是旋转过后的信息,参考3555f6e3684719fd6a48823b6c90836aa9769939.png

6b79ac2037e763f086b89d67cee6ef3a18970f8a.png

cbdfde0c3a1ad3c99ab5f65716debb629dabf629.png

ef789342eb0e4d2d453b96f7fe4880b12fbab9a6.png

根据ret的信息我们也可以画一个矩形框,这个矩形应该是根据拟合椭圆的最小面积外接矩形来的。所以可以出现斜的:da2ae24f55673c1b37c350b926eb87d1488f883d.png

05d626849c96995f6caf1fc7f3d095a9023a7875.png

结果:df0e0a8f7e56b1969c6b914ff695890cc6149581.png

这断断续续的感觉是因为取整,原来的小数在一条直线上,取整之后,这些点就可能不再一条直线上了,因为取整的舍入量不一样。

用meanshift试一下:dc240c61962b89aab9090a0a6b2ebdea6bfa1107.png

0a0203028b63504f57996fcbe45814892b915a3f.png

它的ret返回的是迭代次数,所以meanshift的结果不能是斜的。

4d84d81f806927465dfa0784f911813c78ccd59c.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值