gpt4 book ai didi

c++ - 为什么使用 cv::Mat (opencv) 更改指向数据的指针对 cv::filter2D 有问题?

转载 作者:太空狗 更新时间:2023-10-29 22:54:40 25 4
gpt4 key购买 nike

我想迁移到使用 opencv 来获取自定义成像检测器数据。数据集可能非常大(有时是数千帧的数百帧),我使用增强内存映射加载它们。在测试行为时,我创建了一个适当大小的 cv::mat(对于单个帧)并将指针更改为我正在查看的帧的数据。这适用于显示数据 (cv::imshow) 或应用颜色图,但当我使用类似 cv::filter2D 的东西时失败。如果我克隆数据或使用一些拷贝,它会起作用,但我不想开始复制/克隆,因为我认为这会降低性能(也许我错了)。

那么 - 我做错了什么?为什么 cv::filter2D 在这里不起作用,还有更好的方法吗?

在运行时(现在使用 Windows 10)我在终端中得到以下信息:

OpenCV(4.0.1) Error: Assertion failed (data == datastart + ofs.y*step[0] + ofs.x*esz) in cv::Mat::locateROI, file c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\matrix.cpp, line 767
OpenCV: terminate handler is called! The last OpenCV error is:
OpenCV(4.0.1) Error: Assertion failed (data == datastart + ofs.y*step[0] + ofs.x*esz) in cv::Mat::locateROI, file c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\matrix.cpp, line 767

只有当 filter2D 与从内存映射数组构造的矩阵一起使用时才会发生这种情况。

我在克隆版本未注释的情况下运行程序,并将循环中的 std::cout 行替换为:

  std::cout<<"Is it continuous: " << img.isContinuous() << std::endl;

而且 cv::Mat 确实是连续的。

#include <QCoreApplication>
#include<opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>


#include<iostream>
#include <boost/iostreams/device/mapped_file.hpp>


int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
boost::iostreams::mapped_file_source mem_ifile;

mem_ifile.open(std::string("someimage.raw"));
std::cout<<"file size: "<<mem_ifile.size()/(396*266*sizeof (float))<<std::endl;
cv::Mat adjMap;
cv::Mat img(266,396,CV_32FC1);
cv::Mat falseColorsMap;
cv::Mat b_hist;
cv::Mat kernel;
cv::Mat filsMap;
kernel = cv::Mat::ones( 2, 2,CV_32FC1)/double(4.0);
cv::namedWindow("image", cv::WINDOW_NORMAL);
cv::namedWindow("false color", cv::WINDOW_NORMAL);
cv::namedWindow("filtered", cv::WINDOW_NORMAL);

for(unsigned long long i = 0;i< mem_ifile.size()/(396*266*sizeof (float)); i++)
{
img.data = (reinterpret_cast<uchar *>(const_cast<char *>(mem_ifile.data()))+(i*396*266*sizeof (float)));
cv::convertScaleAbs(img, adjMap, 255 / 500.0);
applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_JET);

// PROBLEM HERE - FIRST TWO WORK, LAST ONE DOESN'T
//cv::filter2D(adjMap,filsMap,-1,kernel); // works
//cv::filter2D(img.clone(),filsMap,-1,kernel); // works
cv::filter2D(img,filsMap,-1,kernel); // doesn't work


std::cout<<"mean of adjmap: " << cv::mean(adjMap) << std::endl;
cv::imshow("image", adjMap);
cv::imshow("false color",falseColorsMap);
cv::imshow("filtered", filsMap);
cv::waitKey(20);
}
mem_ifile.close();
return a.exec();
}

基于 Beaker 建议的工作代码:


#include <QCoreApplication>
#include<opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>

#include<iostream>
#include <boost/iostreams/device/mapped_file.hpp>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
boost::iostreams::mapped_file_source mem_ifile;

mem_ifile.open(std::string("/home/hugh/Documents/APS2017April/Ti7_nr2_e_x36000.raw"));
std::cout<<"file size: "<<mem_ifile.size()/(396*266*sizeof (float))<<std::endl;
cv::Mat adjMap;
cv::Mat *img;
cv::Mat falseColorsMap;
cv::Mat b_hist;
cv::Mat kernel;
cv::Mat filsMap;
kernel = cv::Mat::ones( 2, 2,CV_32FC1)/double(4.0);
cv::namedWindow("image", cv::WINDOW_NORMAL);
cv::namedWindow("false color", cv::WINDOW_NORMAL);
cv::namedWindow("filtered", cv::WINDOW_NORMAL);

for(unsigned long long i = 0;i< mem_ifile.size()/(396*266*sizeof (float)); i++)
{
//img.data = (reinterpret_cast<uchar *>(const_cast<char *>(mem_ifile.data()))+(i*396*266*sizeof (float)));
img = new cv::Mat(266,396,CV_32FC1,(reinterpret_cast<uchar *>(const_cast<char *>(mem_ifile.data()))+(i*396*266*sizeof (float))));

cv::convertScaleAbs(*img, adjMap, 255 / 500.0);
applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_JET);

//cv::filter2D(adjMap,filsMap,-1,kernel); // works
//cv::filter2D(img->clone(),filsMap,-1,kernel); // works
cv::filter2D(*img,filsMap,-1,kernel); // works

std::cout<<"Is it continuous: " << img->isContinuous() << std::endl;
cv::imshow("image", adjMap);
cv::imshow("false color",falseColorsMap);
cv::imshow("filtered", filsMap);
cv::waitKey(20);
delete img;
}
mem_ifile.close();
return a.exec();
}

最佳答案

所以看起来您正在修改 data 字段而不更新任何其他字段。 (参见 Public Attributes。)具体来说,dataend , datalimitdatastart 属性标识为

helper fields used in locateROI and adjustROI

locateROI 是错误消息中给出的方法。

正确的方法是使用cv::Mat data* contructor .如文档中所述,

Matrix constructors that take data and step parameters do not allocate matrix data. Instead, they just initialize the matrix header that points to the specified data, which means that no data is copied. This operation is very efficient and can be used to process external data using OpenCV functions.

这可确保正确创建所有 header 数据,而无需进行不必要的复制。

另请注意,在使用这些构造函数时,您应该清理自己的数据:

The external data is not automatically deallocated, so you should take care of it.

关于c++ - 为什么使用 cv::Mat (opencv) 更改指向数据的指针对 cv::filter2D 有问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54594288/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com