Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 循环浏览捕获的图像向量<;cv::Mat>;_C++_Qt_Opencv_Vector_Mat - Fatal编程技术网

C++ 循环浏览捕获的图像向量<;cv::Mat>;

C++ 循环浏览捕获的图像向量<;cv::Mat>;,c++,qt,opencv,vector,mat,C++,Qt,Opencv,Vector,Mat,我有个奇怪的问题。 我正在通过网络摄像头和OpenCV拍摄一组连续事件的照片。将它们存储在向量变量中。在捕获函数结束时,我得到的只是最后一次捕获 我想我有一个关于向量的基本问题。功能如下 void eventCapture() { vector<cv::Mat> capturedAll; getCaptures(capturedAll, 10, 500); int csize = capturedAll.size(); // Here gives a

我有个奇怪的问题。 我正在通过网络摄像头和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();
    }
}
void eventCapture()
{
矢量捕获器;
获取捕获(capturedAll,10500);
int csize=capturedAll.size();
//这里总是最后一次捕捉
//这与imshow无关
//imwrite还将最后一次捕获保存为错误
对于(int i=0;i<10;i++){
简历:imshow(“图像”,capturedAll[i]);
字符串imgname=“imgcaps”+到字符串(i)+“.jpg”;
简历:imwrite(imgname,capturedAll[i]);
cv::waitKey(100);
}
}
void getCaptures(向量和capStore、整数计数、整数tdif)
{
qedtimer-capTimer;
capTimer.start();
for(int i=0;iprocessEvents();
}
}

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

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

    cv::Mat capMat = webCam.get_capture();
    capStore.push_back(capMat.clone());
如果您正在使用Qt(正如标签所示),避免这种情况的最佳方法是将图像深度复制到
QImage
,以避免创建
cv::Mat
的副本。这是从
cv::Mat
创建
QImage
的安全方法,在删除最后一个
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
格式转换为正确格式,例如:

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

void DeleteImageData(void*数据){
自动缓冲=静态转换(数据);
删除缓冲区;
}

显示get_capture()的代码。我所能做的只是猜测,但我认为您应该在while循环中否定hasExpired,因为当前距离您获取图像的时间只有10微秒。难怪它们看起来一样…get_capture是一个伪代码。我有一个不同的相机类,但该函数的输出是正确的。正如我在getCaptures函数中所指出的,如果我直接保存捕获的图像,我会得到正确的结果。但如果我把它分配给一个向量,并试图从那里得到它,我就得到了最后一次捕获。它们实际上并不在几微秒之外。我可以以毫秒为单位设置捕获之间的时间差。所以500毫秒是很长的时间差,我敢肯定镜头前的场景在不同的拍摄之间发生了变化。对不起,我复制错了。这只是两次捕获之间的延迟。查看
Mat(Mat&)
的双文档:制作浅拷贝您需要使用克隆来制作深拷贝。可能在网络摄像头中,数据内存被重新用于新图像。除非您深度复制或创建新的Mat内存,否则capMat仅是提供的图像数据周围的标题。
QImage::Format ImageFilterPrivate::getOpenCVType(int openCvFormat) {
    switch(openCvFormat) {
        case CV_8UC4: return QImage::Format_ARGB32;
        case CV_8UC3: return QImage::Format_RGB888;
        // ... etc.
    }
}
void DeleteImageData(void* data) {
  auto buffer = static_cast<unsigned char*>(data);
  delete buffer;
}