我创建了一个函数来过滤掉std :: vector中我不喜欢的元素,在本例中为opencv轮廓的向量。下面的代码看起来像是可以工作,但是不能,我怀疑是因为每当我删除索引时都会更改索引,但是我继续进行下一个i值迭代。
void FilterContours( std::vector<std::vector<cv::Point>> contours )
{
for ( int i = 0; i < contours.size(); i++ ) {
//Remove contours smaller than 5 from vector - example
if ( contours[i].size() < 5 ) {
contours.erase(contours.begin() + i);
continue;
}
//Other filtering...
}
return;
}
因此,问题是,此功能是否可以按预期工作(我不认为可以),如果不能,则如何使它按预期工作?擦除后是否应该添加ai-= 1以保持正确的索引位置?
每次您erase()
从容器中size()
删除元素时,其元素的递减量以及其余元素的索引也会递减。但是您无条件地增加了循环计数器,因此,每次擦除一个元素时,都将跳过紧随其后的下一个元素!
此外,你是通过你vector
的价值,所以你在工作拷贝的vector
,调用者不会看到在原来的任何变化vector
。
正确的方法是:
仅当不删除元素时,才在循环体内增加索引变量。当您确实要擦除元素时,请保持变量不变:
void FilterContours( std::vector<std::vector<cv::Point>> &contours )
{
int i = 0;
while ( i < contours.size() ) {
if ( contours[i].size() < 5 ) {
contours.erase(contours.begin() + i);
continue;
}
//Other filtering...
++i;
}
}
使用迭代器代替索引:
void FilterContours( std::vector<std::vector<cv::Point>> &contours )
{
auto it = contours.begin();
while ( it != contours.end() ) {
if ( it->size() < 5 ) {
it = contours.erase(it);
continue;
}
//Other filtering...
++it;
}
}
使用删除删除习惯用法:
void FilterContours( std::vector<std::vector<cv::Point>> &contours )
{
contours.erase(
std:::remove_if(
contours.begin(),
contours.end(),
[](const std::vector<cv::Point> &v)
{
if (v.size() < 5) return true;
//Other filtering...
return false;
}
),
contours.end()
);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句