【问题标题】:std::vector is filled up with the same data every time it's usedstd::vector 每次使用时都填充相同的数据
【发布时间】:2014-08-09 12:40:17
【问题描述】:

好的,所以下面的程序应该获取一个视频文件并将其分割成单独的帧并将每一帧保存在它自己的文件中,但是不是所有的帧都应该被保存,而只有那些里面有人的帧,包括大约有人进入画面前 20 帧。

我的代码:

#include <opencv2/opencv.hpp>
#include <vector>

void checkForPerson(const cv::Mat &frame, bool &personInside, bool &personInsideLastFrame);
void saveFrame(const cv::Mat &frame, std::vector<const cv::Mat> &frameBuffer, const bool personInsideLastFrame, int &savedFramesCount);

int main(){
    cv::VideoCapture vc;
    cv::Mat currFrame, currFrameBackup, filtered, bg;
    std::vector<const cv::Mat> frameBuffer;
    const cv::String org = "Original";
    const cv::String filt = "Filtered";
    bool personInside = false;
    bool personInsideLastFrame;
    int savedFramesCount = 0;

    vc.open("res/video1.avi");
    if(!vc.isOpened()){
        std::cerr << "cant load video file!\n";
        system("pause");
        return EXIT_FAILURE;
    }

    vc >> bg; // use first frame as background asuming no people are inside
    if(!bg.data){
        std::cerr << "no frames found\n";
        system("pause");
        return EXIT_FAILURE;
    }
    cv:cvtColor(bg, bg, cv::COLOR_BGR2GRAY);

    int c;
    while(vc.read(currFrame) && ((c = cv::waitKey(5)) != 27)){
        cv::cvtColor(currFrame, currFrameBackup, cv::COLOR_BGR2GRAY);
        filtered = bg - currFrameBackup;
        cv::threshold(filtered, filtered, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
        cv::Mat erode = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3,3));   //just to clean up the mess a bit
        cv::Mat dilate = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3,3));
        cv::erode(filtered, filtered, erode);
        cv::dilate(filtered, filtered, dilate);
        checkForPerson(filtered, personInside, personInsideLastFrame);
        if(personInside || personInsideLastFrame){
            saveFrame(currFrame, frameBuffer, personInsideLastFrame, savedFramesCount);
        }else{
            if(frameBuffer.size() == 20){
                frameBuffer.erase(frameBuffer.begin());
            }
            frameBuffer.push_back(currFrame);
        }

        cv::imshow(org, currFrame);
        cv::imshow(filt, filtered);
    }

    return EXIT_SUCCESS;
}

void checkForPerson(const cv::Mat &frame, bool &personInside, bool &personInsideLastFrame){
    if(personInside){
        personInsideLastFrame = true;
    }else{
        personInsideLastFrame = false;
    }
    cv::MatConstIterator_<uchar> it = frame.begin<uchar>();
    cv::MatConstIterator_<uchar> it_end = frame.end<uchar>();
    for(; it != it_end; ++it){
        if((*it) == 255){
            personInside = true;
            return;
        }
    }
    personInside = false;
}

void saveFrame(const cv::Mat &frame, std::vector<const cv::Mat> &frameBuffer, const bool personInsideLastFrame, int &savedFramesCount){
    if(personInsideLastFrame){
        std::stringstream ss;
        ss << "result/" << ++savedFramesCount << ".jpg";
        cv::imwrite(ss.str(), frame);
    }else{
        for(int i = 0; i<frameBuffer.size(); ++i){
            std::stringstream ss;
            ss << "result/" << ++savedFramesCount << ".jpg";
            cv::imwrite(ss.str(), frameBuffer[i]);
            //cv::imshow("tmp", frameBuffer[i]);
            //cv::waitKey(0);
        }
        frameBuffer.clear();
        std::stringstream ss;
        ss << "result/" << ++savedFramesCount << ".jpg";
        cv::imwrite(ss.str(), frame);
    }
}

代码中的frameBuffer 用于 20 个(如果没有 20 个则应使用最大可用)预输入帧,以及补偿一些“丢失的帧”与里面的人。但是,当我保存它们时,似乎帧被正确插入到frameBuffer 时,当检测到内部人员时,第一帧被保存了 20 次。 我在currentFrame 中未检测到任何内容时向frameBuffer 插入一个帧,并在最后一帧中未检测到任何内容时使用这些帧。 这真的把我的大脑炸了,我似乎看不到问题(实际上什么也看不到), 所以有人请告诉我我犯了一个愚蠢的错误,我们也会非常感谢一些建议。

很抱歉,如果我的描述有些混乱,我找不到更好的解释方式。

【问题讨论】:

    标签: c++ opencv vector logic


    【解决方案1】:

    除非需要,否则 OpenCV 不会重新分配 Mat。 Mat 本质上是一个指向缓冲区的智能指针。如果你 push_back 一个 Mat 到一个向量中,这就像复制指向同一个缓冲区的指针。然后你重用缓冲区,向量中的指针指向新的内容!

    当你将 Mat 推到向量上时,你需要克隆它:

    frameBuffer.push_back(currFrame.clone());
    

    【讨论】:

    • 天哪,我怎么这么笨!非常感谢!我知道我在做一些愚蠢的事情!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 2020-01-10
    • 2016-03-15
    • 1970-01-01
    相关资源
    最近更新 更多