OPENCV新建一个CV::MAT对象

本文介绍了如何使用OPENCV中的CV::MAT对象创建图像,并重点讨论了当数据连续时如何使用memcpy进行数据拷贝。同时,详细解释了CV::MAT的type参数,包括比特深度、数据类型和通道数,提供了几个创建不同类型图像的示例。

 

2018.10.8更新

不过最新的学习发现,如果CV::MAT中的数据是连续的,也可以把数据用memcpy拷贝到对应的data指针指向的内存中。不过需要注意的是如果不连续,这样做是不可以的。


我之前项目中需要做的是把CV::MAT中的数据按字节取出,通过tcp发送出去,对方收到后重新根据接收到的字节流组装起来显示就需要用到以下构造函数:

inline Mat::Mat(int _rows, int _cols, int _type)

需要输入的是创建的图像大小的行列和type,行列自然不必说,那么就说一下type吧,这边参考了https://blog.youkuaiyun.com/u013270326/article/details/72954232,由于这篇博文排版有点问题,所以我就把最核心的内容摘录下来,以备以后查阅

举个例子:

cv::Mat testImg(1080,1920,CV_8UC4);

可以看到这里的type都是 CV_<bit_depth>(S|U|F)C<number_of_channels>这种格式的。其解释为:

1--bit_depth---比特数---代表8bite,16bites,32bites,64bites
2--S|U|F--
        S--代表---signed int---有符号整形
        U--代表--unsigned int--无符号整形
        F--代表--float---------单精度浮点型
3--

<think>好的,我现在需要解决用户的问题,将QSharedPointer<cv::Mat>转换为cv::Mat,并避免在使用cv::cvtColor时出现错误。用户还提供了之前的回答和相关引用,我需要参考这些信息。 首先,用户提到QSharedPointer的转换。根据引用[3],Qt与OpenCV结合时,cv::Mat的赋值是软拷贝,可能导致数据共享的问题。用户可能在使用QSharedPointer管理cv::Mat时,导致多个对象共享同一数据,这可能引发问题,比如在转换时数据被修改或释放。 接下来是cv::cvtColor报错的问题。之前的回答已经分析过可能的原因,比如空图像、通道数不对或版本问题。用户现在可能在转换指针后,仍然遇到这些错误,需要确保转换后的cv::Mat有效且符合要求。 步骤一:转换QSharedPointer到cv::Mat。由于QSharedPointer是智能指针,获取其内部的cv::Mat需要使用data()方法。但需要注意深拷贝还是浅拷贝。如果直接使用浅拷贝,原指针释放后可能出现问题。所以可能需要克隆数据,确保新Mat独立存在。 步骤二:检查转换后的Mat是否有效。确保指针不为空,Mat的data不为空,且尺寸正确。根据引用[1]和[2],使用vector初始化Mat时,如果所有元素共享数据,可能引发问题,类似地,这里需要确保转换后的Mat数据独立或正确引用。 步骤三:处理cv::cvtColor的报错。检查图像是否为空、通道数是否为3、是否正确使用颜色转换代码(如COLOR_BGR2RGB而非旧版)。根据引用[3],Qt显示时可能出现红蓝通道对调,所以转换颜色空间是否正确也很重要。 可能遇到的问题:用户可能在转换指针后,Mat被释放,导致cvtColor处理空数据。或者转换后的Mat通道数不符合要求,例如不是3通道的BGR图像。需要确保在转换后,Mat的数据完整且符合cvtColor的要求。 解决方案:使用深拷贝(clone())来确保Mat数据独立,避免共享问题。转换后验证Mat的有效性,再进行颜色空间转换。同时,处理Qt与OpenCV的通道顺序差异,可能需要显式转换颜色空间,确保显示正确。 最后,结合用户提供的引用,特别是关于vector<Mat>初始化和数据共享的问题,需要提醒用户在转换智能指针时注意数据所有权和生命周期,避免悬空指针或数据覆盖。</think>### QSharedPointer与cv::Mat的转换及`cv::cvtColor`报错解决方案 --- #### **一、QSharedPointer<cv::Mat> 转 cv::Mat 的正确方法** ##### 1. **浅拷贝与深拷贝的选择** - **浅拷贝**:直接通过`data()`获取指针,但需注意共享数据的风险(若原指针释放,新Mat可能失效)[^1][^3] ```cpp QSharedPointer<cv::Mat> sharedMat = ...; cv::Mat mat = *sharedMat.data(); // 浅拷贝 ``` - **深拷贝**:使用`clone()`确保数据独立,避免共享问题 ```cpp cv::Mat mat = sharedMat->clone(); // 完全独立的内存 ``` ##### 2. **验证数据有效性** 转换后需检查Mat是否为空或数据异常: ```cpp if (mat.empty() || mat.data == nullptr) { qWarning() << "转换失败:Mat数据为空或指针无效"; return; } ``` --- #### **二、`cv::cvtColor`报错的深层原因与修复** ##### 1. **输入图像有效性检查** - **空图像**:确保转换后的Mat不为空(`!mat.empty()`) - **通道数验证**:BGR到RGB转换要求输入为3通道 ```cpp if (mat.channels() != 3) { qDebug() << "通道数不符,当前通道数:" << mat.channels(); cv::cvtColor(mat, mat, cv::COLOR_GRAY2BGR); // 单通道转3通道示例 } ``` ##### 2. **Qt与OpenCV的通道兼容性** Qt的`QImage::Format_RGB888`默认按RGB顺序存储,而OpenCV的`cv::Mat`默认按BGR顺序存储[^3]。需显式转换: ```cpp cv::Mat rgbMat; cv::cvtColor(mat, rgbMat, cv::COLOR_BGR2RGB); // 关键步骤 QImage img(rgbMat.data, rgbMat.cols, rgbMat.rows, rgbMat.step, QImage::Format_RGB888); ``` ##### 3. **数据生命周期管理** 若使用浅拷贝,需确保`QSharedPointer`生命周期覆盖后续操作: ```cpp // 正确做法:保持sharedMat存活直到不再使用mat QSharedPointer<cv::Mat> sharedMat = ...; { cv::Mat mat = *sharedMat.data(); // 浅拷贝 cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); // 操作期间sharedMat必须有效 } ``` --- #### **三、完整代码示例** ```cpp QSharedPointer<cv::Mat> sharedMat = QSharedPointer<cv::Mat>::create(cv::imread("test.jpg")); if (sharedMat.isNull() || sharedMat->empty()) { qFatal("图像加载失败"); } // 深拷贝避免共享问题 cv::Mat targetMat = sharedMat->clone(); // 通道数验证与转换 if (targetMat.channels() != 3) { cv::cvtColor(targetMat, targetMat, cv::COLOR_GRAY2BGR); } // BGR转RGB cv::Mat rgbMat; cv::cvtColor(targetMat, rgbMat, cv::COLOR_BGR2RGB); // 注意目标Mat新建 // 转换为QImage QImage img(rgbMat.data, rgbMat.cols, rgbMat.rows, rgbMat.step, QImage::Format_RGB888); ``` --- #### **四、扩展问题与调试技巧** 1. **智能指针悬挂引用**:若浅拷贝后`QSharedPointer`被提前释放,Mat数据将失效,建议优先使用深拷贝。 2. **OpenCV版本兼容性**:验证`cv::cvtColor`标识符是否与OpenCV版本匹配(如4.x+要求`COLOR_`前缀)[^1][^3]。 3. **内存对齐问题**:若Qt显示时出现图像扭曲,检查`QImage`构造时传入的`bytesPerLine`参数(对应Mat的`step`字段)[^3]。 --- ### 相关问题 1. 如何检测`QSharedPointer<cv::Mat>`是否已释放内存? 2. OpenCV中`cv::Mat::clone()`与`cv::Mat::copyTo()`的性能差异? 3. Qt多线程环境下如何安全传递`cv::Mat`数据?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值