使用Map初衷
笔者在做红外视频多运动目标检测及跟踪,不论是考虑跟踪算法,还是精确检测目标位置,倘或能给每个目标建立一个固定特征,在后续的检测或者跟踪中,只要做好匹配就ok了。
那么我们需要这样一个容器,能同时保存目标序号和特征。
然后Map就被召唤出来。
我不去翻看C++给的标准样板了,没有底层基础,看不懂,大概就是存放ID和value。
比较让人欣慰的特征是:ID和value的数据类型根据需求设置。
基本的用法如下:
- 新建一个map:
笔者希望存储每个目标所在位置作为特征,map定义如下:
map<int,Rect>MyFeatures
<>中为建立map的ID和value的类型,笔者将目标简单设置为数字序号,Rect为opencv的矩形类型,保存目标的位置。
- 增加数据操作:
笔者用的是insert的方式,如下:
MyFeatures.insert(map<int, Rect>::value_type(count, inRect[i]))
count是笔者用来记录目标序号的标记,inRect为当前索引满足匹配的一个Rect。
基本这样的操作ok。
- 迭代器操作和替换:
迭代器是为了访问 并操作Map中元素的一种索引,跟指针有点儿像吧。
在之前,笔者一直采用下标方式。最近尝试迭代器:iterator。
使用方式如下:
map<int, Rect>::iterator itr_myfeatures
- 位置查找
遍历的时候简单叠加就可以,在查找状态下,使用如下:
itr_myfeatures=MyFeatures.find(_to_find_key)
- 迭代器访问ID和value:
key= itr_myfeatures->first
value= itr_myfeatures->second
基本意思就是,第一个位置保存ID,第二个位置保存value。就假象是excel的两列数据吧。
- value的更新:
一般情况下,key值是不允许改变的,我们更新的是value,笔者采用这样的方式:
itr_myfeatures->second=new_value
直接替换就可以了,是不是很简单呢?
- 接下来分享一个坑:
在做遍历的过程中,经常遇到这样的操作:符合条件的对当前删除,否则进入下一组元素判断和操作。
map<int, Rect>::iterator iter;
for (iter = MyFeatures.begin(); iter != MyFeatures.end(); iter++)
{
if (condition_1)
{
MyFeatures.erase(iter);
}
if (condition_2)
{
iter++;
}
}
注意啦,直接这样的操作是会死循环的,为什么呢?
在MyFeatures.erase(iter);据后,迭代器会在清除空间后指向任意位置,即野指针。
所以呢,清除空间后请及时给迭代器以正确方向:
MyFeatures.erase(iter++);
这句话什么意思呢?在清除满足条件的数据空间后,让迭代器指向map的下一组元素。
ok,洋洋洒洒一点文字,就是这周对map的一点使用经验。