opencv编程中错误提示:不存在从mat到cvmat适当的转换函数。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv编程中错误提示:不存在从mat到cvmat适当的转换函数。相关的知识,希望对你有一定的参考价值。

是在cvMat*到Mat形式转换过程中出现的,希望大侠能提出建设性的意见,cvMat*到Mat形式数据转换中不能直接转换,具体应该怎么转换才可以,用什么函数。急!!

参考技术A Mat x;
&(cvMat)x就可以得到cvMat的指针了
参考技术B opencv中常见的与图像操作有关的数据容器有Mat,cvMat和IplImage,这三种类型都可以代表和显示图像,但是,Mat类型侧重于计算,数学性较高,openCV对Mat类型的计算也进行了优化。而CvMat和IplImage类型更侧重于“图像”,opencv对其中的图像操作(缩放、单通道提取、图像阈值操作等)进行了优化。在opencv2.0之前,opencv是完全用C实现的,但是,IplImage类型与CvMat类型的关系类似于面向对象中的继承关系。实际上,CvMat之上还有一个更抽象的基类----CvArr,这在源代码中会常见。
1. IplImage
opencv中的图像信息头,该结构体定义:
View Code

typedef struct _IplImage

int nSize;
int ID;
int nChannels;
int alphaChannel;
int depth;

char colorModel[4];
char channelSeq[4];
int dataOrder;
int origin;
int align;

int width;
int height;

struct _IplROI *roi;
struct _IplImage *maskROI;
void *imageId;
struct _IplTileInfo *tileInfo;

int imageSize;
char *imageData;
int widthStep;
int BorderMode[4];
int BorderConst[4];

char *imageDataOrigin;
IplImage;

dataOrder中的两个取值:交叉存取颜色通道是颜色数据排列将会是BGRBGR...的交错排列。分开的颜色通道是有几个颜色通道就分几个颜色平面存储。roi是IplROI结构体,该结构体包含了xOffset,yOffset,height,width,coi成员变量,其中xOffset,yOffset是x,y坐标,coi代表channel of interest(感兴趣的通道),非0的时候才有效。访问图像中的数据元素,分间接存储和直接存储,当图像元素为浮点型时,(uchar *) 改为 (float *):
View Code
参考技术C CvMat
首先,我们需要知道,第一,在OpenCV中没有向量(vector)结构。任何时候需要向量,都只需要一个列矩阵(如果需要一个转置或者共轭向量,则需要一个行矩阵)。第二,OpenCV矩阵的概念与我们在线性代数课上学习的概念相比,更抽象,尤其是矩阵的元素,并非只能取简单的数值类型,可以是多通道的值。
Mat
Mat是opencv2.0推出的处理图像的新的数据结构,现在越来越有趋势取代之前的cvMat和lplImage,相比之下Mat最大的好处就是能够更加方便的进行内存管理,不再需要程序员手动管理内存的释放。opencv2.3中提到Mat是一个多维的密集数据数组,可以用来处理向量和矩阵、图像、直方图等等常见的多维数据。 之前的图像一般都是用IplImage*表示

///////////////////////////////背景知识结束///////////////////////////////////////

这里是CvMat和Mat的互相转换公式,基本上是复制数据块。

CvMat -> Mat
Mat::Mat(const CvMat* m, bool copyData=false); /*类似IplImage -> Mat,可选择是否复制数据*/

Mat -> CvMat
例子(假设Mat类型的imgMat图像数据存在):
CvMat cvMat = imgMat;/*Mat -> CvMat, 类似转换到IplImage,不复制数据只创建矩阵头本回答被提问者和网友采纳

opencv 将数据从 *Mat 复制到 Mat

【中文标题】opencv 将数据从 *Mat 复制到 Mat【英文标题】:opencv copy data from a *Mat to a Mat 【发布时间】:2016-02-09 12:53:14 【问题描述】:

我有两个cv::Mat 对象:

cv::Mat *frameLeftRemap;
cv::Mat frameLeft2;

数据从相机流入 *frameLeftRemap。我需要将数据复制到 frameLeft2,然后删除 frameLeftRemap,以避免我看到的帧伪影。 (这是相机制造商支持台建议的。)

功能是:

  void ProcessImageLeft(AVT::VmbAPI::FramePtr pFrame)
    
        VmbUchar_t *pBuffer;
        VmbUint32_t FrameWidth;
        VmbUint32_t FrameHeight;


        //prepare frame information:
        pFrame->GetWidth(FrameWidth);
        pFrame->GetHeight(FrameHeight);
        pFrame->GetImage(pBuffer);
        //edited
        Mat1b imageL(FrameHeight, FrameWidth, (uchar*)pBuffer);

        cv::remap(imageL, *frameLeftRemap, mx1, my1, cv::INTER_LINEAR);

        frameLeft2 = frameLeftRemap->clone(); 

        //frameLeftRemap->copyTo(frameLeft2);


        cv::imshow("right", frameLeft2);
        cv::waitKey(1);
        delete frameLeftRemap;


    

copyTo 和 clone 都报错:

this is nullPtr. read access violation

我在这里做错了什么?

【问题讨论】:

请发帖minimal reproducible example。正如已经指出的那样,如果您的图像仍然有效,这应该可以正常工作。此外,使用Mat* 通常是个坏主意,因为您可能会破坏内部引用计数(就像您在这里所做的那样) 你为什么还要使用IplImage?请避免使用过时的 C api。请重构此代码以仅使用 Mat。错误可能已经解决了 该部分是来自相机制造商的代码。我将如何将 *pBuffer 直接变成 Mat?谢谢。 Mat1b m(rows, cols, (uchar*)buffer, step) 另外,你应该交换FrameWidthFrameHeightMat1b copyimageL(FrameHeight, FrameWidth, (uchar*)pBuffer); 【参考方案1】:

frameL= frameLeftRemap->clone(); 应该可以正常工作。看来你在frameL 有问题。尝试使用cv::imshowcv::imwrite 显示它,以确保它在克隆之前已损坏。然后解决原来的问题。如果您发布代码,我们会为您提供更多帮助。

【讨论】:

以上是关于opencv编程中错误提示:不存在从mat到cvmat适当的转换函数。的主要内容,如果未能解决你的问题,请参考以下文章

opencv编程中cvMat到Mat如何进行数据转换?

OpenCV - Mat::convertTo() 断言错误。

opencv 报错:Error: Assertion failed (data) in cv::Mat::at, file ... mat.inl.hpp, line 897(访问了不存在矩阵的像素)

opencv 将数据从 *Mat 复制到 Mat

使用QT5绘制OpenCV3的Mat图像

使用QT5绘制OpenCV3的Mat图像