OpenCV卡尔曼滤波器,从std::vector中删除

OpenCV Kalman Filter, erasing from std::vector

本文关键字:std vector 删除 滤波器 OpenCV      更新时间:2023-10-16

我有这个问题,请参阅。

我正在使用OpenCV来跟踪视频中的一只手。用级联检测器定位手,然后使用CamSHIFT进行跟踪。如果CamShift算法在某些帧失败,我也会使用卡尔曼滤波器来校正手的位置。

当我试图从存储Hands的std::向量中删除一个元素时,问题就出现了。擦除的原因是,由于一些问题,人脸被误解为手,所以我检测人脸,如果手的区域与人脸区域相交,我会删除那只手。我知道,非常天真,但我目前正处于起步阶段。代码如下:

class Hand {
...
public:
    struct 
    {
        ...
        struct {
            cv::Mat_<float> measurement;
            cv::KalmanFilter KF;
            cv::Mat state;
            cv::Mat processNoise;
        } KalmanTracker;
    } Tracker;
};
...
std::vector<Hand> hands;
...
std::vector<cv::Rect> faces;
faceCascade.detectMultiScale(frame, faces, 1.1, 2, CV_HAAR_FIND_BIGGEST_OBJECT);
// iterate through hands
for (std::vector<Hand>::iterator it = hands.begin(); it != hands.end(); ++it) {
    // iterate through faces:
    for (std::vector<cv::Rect>::iterator fc = faces.begin(); fc != faces.end(); ++fc) {
        cv::Rect intersection = (*it).handBox.boundingRect() & (*fc);
        // check if they have at leasy 75% intersection
        if (intersection.area() >= ((*it).handBox.boundingRect().area() * 0.75)) {
            // delete that hand from list
            hands.erase(it);    // this gets me a a EXC_BAD_ACCESS
        }
    }
}

hands.erase(it)行在指向我的KalmanFilterTracker结构时获得EXC_BAD_ACCESS,以及mat.hpp中具有EXC_i386_GPFLT:的这一行

inline void Mat::release()
{
    if( refcount && CV_XADD(refcount, -1) == 1 ) // EXC_BAD_ACCESS, code=EXC_i386_GPFLT
    ...
}

handsfaces都不为空。如果我从我的项目中完全删除卡尔曼滤波器,并提及或使用它,错误就会消失。

vector::erase(迭代器)使正在擦除的迭代器无效。但它确实向向量中的下一个有效项返回了一个新的迭代器。因此,这条线应该是:

it = hands.erase(it);

在berak的评论后编辑:

啊,我错过了内环。由于您在内部循环中使it无效,所以事情会变得有点复杂。你需要克服重重困难才能把它做好。

for (std::vector<Hand>::iterator it = hands.begin(); it != hands.end(); ) {
    bool found = false;
    // iterate through faces:
    for (std::vector<cv::Rect>::iterator fc = faces.begin(); fc != faces.end() && !found; ++fc) {
        cv::Rect intersection = (*it).handBox.boundingRect() & (*fc);
        // check if they have at leasy 75% intersection
        if (intersection.area() >= ((*it).handBox.boundingRect().area() * 0.75)) {
            found = true;
        }
    }
    if (found) {
        it = hands.erase(it);
    }
    else {
        ++it;
    }
}

可以将一些迭代器操作折叠到内部循环中,但将其保留在外部会使代码更清晰、更容易推理。

好的,通过一些调试,我发现我的手向量在某个时刻变空,并且在试图从空向量中擦除时出现错误。唯一剩下的就是找出它为什么会变成空的,以及在什么时候变成空的。谢谢大家。