循环捕获图像矢量<cv :: mat>

时间:2017-12-30 16:05:49

标签: c++ qt opencv vector mat

我有奇怪的问题。 我正在通过网络摄像头和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();
    }
}

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分: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;
}