循环通过捕获的图像矢量

问题描述 投票:-1回答:2

我有奇怪的问题。我正在通过网络摄像头和OpenCV拍摄一系列连续事件的照片。将它们存储在矢量变量中。在捕获功能结束时,我得到的只是最后一次捕获。

我认为我的向量存在根本问题。功能如下

void eventCapture()
{
    vector<cv::Mat> capturedAll;
    getCaptures(capturedAll, 10, 500);

    int csize = capturedAll.size();
    // Here gives always the last capture
    // It is not related with imshow
    // imwrite also saves the last capture as wrong
    for (int i = 0; i < 10; i++) {
        cv::imshow("Images", capturedAll[i]);
        string imgname = "imgcaps" + to_string(i) + ".jpg";
        cv::imwrite(imgname, capturedAll[i]);
        cv::waitKey(100);
    }
}

void getCaptures(vector<cv::Mat>& capStore, int count, int tdif)
{
    QElapsedTimer capTimer;
    capTimer.start();

    for (int i = 0; i < count; i++) {
        capTimer.restart();

        // get_capture takes a photo from webcam
        cv::Mat capMat = webCam.get_capture();
        capStore.push_back(capMat);

        string imgname = "localsave" + to_string(i) + ".jpg";
        // Saved image here is giving correct result
        cv::imwrite(imgname, capMat);

        while (!capTimer.hasExpired(tdif))
            qApp->processEvents();
    }
}

我也尝试使用迭代器,但它给出了同样错误的结果。

c++ qt opencv vector mat
2个回答
1
投票

我认为问题是关于cv :: Mat的指针。改变下面部分解决了问题。但我完全不明白。每次在循环中我都会再次初始化capMat。

    cv::Mat capMat = webCam.get_capture();
    capStore.push_back(capMat.clone());

0
投票

如果你在Qt工作(正如你的标签所示)最好的方法是完全避免这种情况是将图像深度复制到QImage以避免创建cv::Mat的副本。这是从QImage创建cv::Mat的安全方法,它还可以在删除最后一个QImage引用时释放内存:

cv::Mat* capture;
size_t bufferSize = capture->cols * capture->rows * capture->channels();
auto pixelFormat = toPixelFormat(capture->format);

auto outputBuffer = new uchar[bufferSize];

// This will not work for sparse mats - you have to copy row-by-row
memcpy(outputBuffer, capture->data, bufferSize);

// Have to pass stride since QImage is padding the rows for non power-of-two sizes
QImage image(outputBuffer, capture->cols, capture->rows, capture->cols * capture->channels(), pixelFormat, DeleteImageData, outputBuffer);

你需要将cv::Mat格式转换为正确的QImage::Format,例如:

QImage::Format ImageFilterPrivate::getOpenCVType(int openCvFormat) {
    switch(openCvFormat) {
        case CV_8UC4: return QImage::Format_ARGB32;
        case CV_8UC3: return QImage::Format_RGB888;
        // ... etc.
    }
}

一些OpenCV格式(例如16位灰度级在Qt中没有匹配类型)。在QImage的最后一次引用丢失后,您还需要提供一个删除已分配数据的函数,以避免内存泄漏(可以作为lambda传递):

void DeleteImageData(void* data) {
  auto buffer = static_cast<unsigned char*>(data);
  delete buffer;
}
© www.soinside.com 2019 - 2024. All rights reserved.