3

私は C++ が初めてで、cv::Mat のリストを作成しようとしています。

これは非常に多くのメモリを割り当てる可能性がありますが、リストにロードする小さなマットは約 10 個しかありません。

このコードを作成しましたが、なぜ機能しないのかわかりません。

void Utils::getFramesFromVideo(std::string file,std::list<cv::Mat>& listMatOutput) {

    cv::VideoCapture* videoCapture = new cv::VideoCapture(file);

    bool hasImage = false;

    cvNamedWindow("WhileReading", 1);

    do {
        cv::Mat frame;
        hasImage = videoCapture->read(frame);
        if (hasImage) {
            listMatOutput.push_back(frame);
            imshow("WhileReading", frame);
            waitKey(0);//give some time to see the frame (debug)
        }
    } while (hasImage);

    cvNamedWindow("AfterReading", 2);

    for (std::list<Mat>::const_iterator iterator = listMatOutput.begin();
            iterator != listMatOutput.end(); iterator++) {
        imshow("AfterReading", *iterator);
        waitKey(0);//give some time to see the frame (debug)
    }
    videoCapture->release();
}

最初の読み込みではフレームが正しく表示されますが、2 番目のウィンドウ (AfterReading) では画像が黒く赤い縞模様になっています。誰かアドバイスをお願いできますか?

4

2 に答える 2

1

The list format is an STL container, meaning that you've got some things to keep in mind to work with it. push_back() is the preferred method of adding instances to the container, much like using an iterator is the preferred method of accessing the elements of the list. If you try to directly set an element of the list to a cv::Mat() you're working on, then a) you need to know exactly what sort of wrapping the list is doing to each instance, so you can do it properly yourself, and b) you're defeating the purpose of using an STL container in the first place, which is to abstract away the details of the list.

You don't necessarily need to use the frame.clone() call in your code, as this creates a deep copy of the image and takes up precious resources. I know that I've used std::vector<cv::Mat> in the past without having to make deep copies for each element in the vector, so I assume that you should be able to pass the Mat itself to a list. Consult the C++ documentation on STL lists.

Another thing you might consider, if low memory usage and speed of access through the list is a concern, and your number of images is low, is a list of image pointers. Keep your images stored as individual cv::Mat instances, and make your list of type std::list<cv::Mat*>, passing the handle of the image to the push_back() call. Of course, with this method, your images will not be 'thread safe' because they will be stored in one place, but called and worked on from another. I hope this shed a little light on your inquiry.

于 2012-07-15T18:55:46.973 に答える
0

ポインターやベクターに変更したり、GCC でのコードの最適化を確認したりするなど、あらゆることを試しました。次に、 cv::Mat のクローンを作成しようとした後、それは機能しました:

listMatOutput.push_back(frame.clone());

誰かが理由を教えてくれ、より良い方法を提案してくれると嬉しいです。そうすれば、自分の答えよりも良い答えを選ぶことができます.

于 2012-07-13T23:55:52.483 に答える