首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么用cv::Mat (opencv)更改指向数据的指针在cv::filter2D上会有问题?

为什么用cv::Mat (opencv)更改指向数据的指针在cv::filter2D上会有问题?
EN

Stack Overflow用户
提问于 2019-02-08 22:15:09
回答 1查看 486关注 0票数 2

我想迁移到使用opencv进行自定义成像探测器数据。数据集可能非常大(有时是上千帧的上百帧),我用boost内存映射加载它们。在测试行为时,我创建了一个适当大小的cv::mat (对于单个帧),并将指针更改为我正在查看的帧的数据。这对于显示数据(cv::imshow)或应用色彩映射表很有效,但当我使用cv::filter2D之类的东西时就会失败。如果我克隆数据或使用一些拷贝,它可以工作,但我不想开始拷贝/克隆,因为我认为这会降低性能(可能我错了)。

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

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

代码语言:javascript
运行
复制
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行替换为:

代码语言:javascript
运行
复制
  std::cout<<"Is it continuous: " << img.isContinuous() << std::endl;

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

代码语言:javascript
运行
复制
#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建议的工作代码:

代码语言:javascript
运行
复制
#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();
}
EN

回答 1

Stack Overflow用户

发布于 2019-02-09 06:44:34

因此,看起来您正在修改data字段,而没有更新任何其他字段。(请参阅Public Attributes。)具体而言,dataenddatalimitdatastart属性标识为

locateROI和adjustROI中使用的

帮助器字段

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

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

接受数据和步骤参数的

矩阵构造函数不分配矩阵数据。相反,它们只是初始化指向指定数据的矩阵头,这意味着不复制任何数据。此操作非常有效,可用于通过OpenCV函数处理外部数据。

这确保了所有的标题数据都被正确地创建,而没有不必要的复制。

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

外部数据不会自动释放,因此您应该小心处理它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54594288

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档