У меня есть эта проблема, видите.
Я использую 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
...
}
ни hands
ни faces
пусты
Если я полностью удаляю фильтр Калмана из своего проекта и любое упоминание или использование его, ошибка исчезает.
vector :: erase (iterator) делает недействительным стираемый итератор. Но он возвращает новый итератор к следующему действительному элементу в векторе. Таким образом строка должна быть:
it = hands.erase(it);
Изменить после комментария Берака:
Ах, я пропустил внутренний цикл. Так как вы лишаете законной силы 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;
}
}
Можно сложить некоторые из манипуляций итератора во внутренний цикл, но если оставить его снаружи, код станет немного понятнее и легче рассуждать.
Хорошо, после некоторой отладки я обнаружил, что мой вектор рук в какой-то момент становится пустым, и появляется ошибка при попытке стереть из пустого вектора.
Осталось только выяснить, почему он становится пустым и в какой момент.
Всем спасибо.