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

时间:2014-09-03 11:07:02

标签: c++ opencv exc-bad-access kalman-filter

我有这个问题,请参阅。

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

问题出现了,当我试图从std :: vector中删除一个元素时,我在那里存放我的手。擦除的原因是由于某些问题,面部被误解为一只手,所以我检测面部,如果手部区域与面部区域相交,我删除那只手。我知道,非常天真,但我目前处于起步阶段。 代码如下所示:

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)行在指向我的EXC_BAD_ACCESS结构时获得了KalmanFilterTracker,以及mat.hpp中带有EXC_i386_GPFLT的这一行:

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

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

2 个答案:

答案 0 :(得分:1)

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

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;
    }
}

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

答案 1 :(得分:0)

好的,通过一些调试,我发现,我的矢量手在某个时刻变空,并且在尝试从空矢量中删除时出现错误。 唯一剩下的就是找出它为什么变空而且在哪一点上。 谢谢大家。