使用OpenCV找出图像中的不同点
问题:
提供三组图像:{0-0.jpg,0-1.jpg,0-2.jpg},{1-0.jpg,1-1.jpg},{2-0.jpg,2-1.jpg};每一组中的不同图像拍摄的是同一个场景,但是场景中部分区域发生了变化。以#-0.jpg为参考图,找出#-1.jpg, #-2.jpg中的变化区域。
下面展示的是0-0.jpg,0-1.jpg,可以看出两者之间的变化。
思路:
1. 获取SIFT特征和特征点
使用上节课使用的特征匹配的knnMatch
获取好的匹配点:
由于有的图像设置good
阈值以后似乎会导致没有好的匹配,所以此处选择不断改变阈值thresh
,直到能够找到至少对点。对应代码SIFTMatch
函数最开始部分
接着把这些”好的特征点从所有特征点里删去”。[noMatch函数]
得到未匹配特征后大概是这样的:[绿色表示图片2有的图片1没有,红色表示图片1有的图片2没有]
2. 去除多余特征点
发现很多特征点都是多余的,比如键盘上很多点,
发现这些多余的特征点都有一个共性: 周围红色绿色特征点混杂(也就是内点),所以我的办法是对每一个红色的特征点(本图有而另一张图没有的特征点),在绿色特征点[本图没有而另一张图有的特征点]里找距离最近的一个特征点,如果这个距离小于某个阈值,则认为是内点,直接去除。[对应代码findNoMatch
函数】
去除完多余特征点大概就是这样:
看得出来,只剩下花的特征点了。
3. 聚类: 对应代码Clustering
函数
给这些特征点聚类。
嗯,这是最麻烦的一步,如果聚类的聚类半径设置的太大:
[当然,这里只取占比总特征点数比较大的一些类别,不然会有很多误检测]
会把两个弄到一起。
如果设置的很小,加上只取占比比较大的类别,则会造成漏检测[电脑屏幕被漏检测了]:
我的想法是,由于应该处于一个大类的特征点本身分布就不均匀[电脑上的两堆特征点本身分布就比较分开],所以我们要允许两堆比较大[防止一些外点进入导致误检]且比较靠近的一些类有融合的操作。
所以在我的Clustering
函数中就利用上述条件把一些靠近的类融合在一起。
这样的效果就好了很多。
4. 画矩形: 对应代码中的drawRecs
函数
由于聚类完毕后得到的是一堆点集合,所以还要对点集合找一个合适的矩形,就找点集里最小的坐标,最大的坐标即可。
不过发现有的时候还会有多重矩形(相交矩形):
类似于这种,所以应该把它们合成一个大矩形,
最后就大功告成了。
后记
花了很多时间调参,也花了很多时间思考到底该怎么把这朵花在往下多框一些[只框住了有特征点的部分]
试图使用遍历像素,找像素值近的点扩张一下范围,不过似乎效果不是很好?
另外调参也每调到让每一幅图像都满意的程度,哎。