opencv中Mat的断言问题

本文深入解析OpenCV中Mat类的CV_DbAssert断言机制,阐述其在调试阶段的作用及如何防止矩阵操作中的越界错误。详细解释了五种断言条件,包括维度检查、数据有效性验证、索引边界校验等,帮助读者理解并正确使用OpenCV进行图像处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OpenCV中经常会碰见CV_DbAssert,来谈一谈opencv中Mat类的CV_DbAssert

_Tp& Mat::at(int i0, int i1)
{
//1.如果维度越界
CV_DbgAssert(dims <= 2);
//2.如果数据为空
CV_DbgAssert(data);
//3.如果i0越界
CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
//4.如果i1越界
CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
//5.elemSize1为Mat中一个通道中一个元素的所占内存大小的值
CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1());
//6.返回该点对应的值
return ((_Tp*)(data + step.p[0] * i0))[i1];
}
首先,这个断言官方的解释是只在调试阶段运行,在发布版本不运行,但是很有可能会引起程序的崩溃。
主要的目的就是防止越界。
这里共有5个断言,只要断言的表达式为false就会终止程序。逐条来解释一下:
1.CV_DbgAssert(dims <= 2);很显然这是一个二维矩阵,如果矩阵的维度大于2就会断言。
2.CV_DbgAssert(data); 如果数据为空,传过来的矩阵数据为空
3. CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);行参数i0越界,P【0】为Mat中的梯级,P【0】代表着
第一级,在这个二维矩阵中,P【0】就为矩阵中一行数据在内存中占的大小。size嘛大概意思也就是一行的
大小。
4.CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));同理,这个是判
段i1参数是否越界。具体嘛,没搞明白,反正C++那么多坑,就没必要深挖了。功能明白了就好。
5.CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1());这个嘛,估计是和我一样碰 到 最多的一个了。这句话的意思是判断类型是否合适。
比如H.at(2, 2) = Z这么一个语句来说就是,判断double这个类型和H矩阵存储类型是否相同。
经常会发生你的矩阵类型是CV_64F,你却写了H.at(2, 2) = Z他也会报错。忘了:elemSize1是矩阵中一个像素一个通道的一个元素在内存中占的大小。elemSize是多个通道叠加大小。
附上:
opencv中调用type函数返回值对应的含义。
在这里插入图片描述
opencv中调用depth()的返回值代表的含义如下:
#define CV_8U 0
#define CV_8S 1
#define CV_16U 2
#define CV_16S 3
#define CV_32S 4
#define CV_32F 5
#define CV_64F 6
#define CV_USRTYPE1 7

在opencv中数据类型的对应。
Mat_对应的是CV_8U
Mat_对应的是CV_8S
Mat_对应的是CV_32S
Mat_对应的是CV_32F
Mat_对应的是CV_64F
这里我们就能明白H.at(2,2)==z;如果h的类型是cv——64f,因为在opencv中float对应的是32F。
参考:https://blog.youkuaiyun.com/github_30605157/article/details/79872549
https://blog.youkuaiyun.com/pekingFloater/article/details/82688327

### 关于OpenCV和FRRTTI的技术信息 #### OpenCV中的FRRTTI支持 在C++编程环境中,`type_info` 和 RTTI(Run-Time Type Information)机制允许程序动态获取对象的类型信息。然而,在某些情况下,编译器可能禁用了RTTI功能或者链接库未正确配置,这可能导致运行时错误或不兼容的情况。 如果遇到与OpenCV相关的RTTI问题,通常是因为以下原因之一: 1. 编译选项中显式关闭了RTTI支持。 2. 使用第三方库时,这些库并未启用RTTI支持[^4]。 3. 链接阶段缺少必要的标准库文件。 解决方法如下: - **重新编译OpenCV**:确保在构建过程中启用了RTTI支持。可以通过设置 `CMAKE_CXX_FLAGS` 参数来实现这一点。例如: ```bash cmake -D CMAKE_CXX_FLAGS="-frtti" .. ``` - **检查依赖项**:确认所有使用的外部库均支持并启用了RTTI功能[^5]。 --- #### 解决方案示例代码 以下是针对OpenCV项目的一个简单示例,展示如何验证RTTI是否正常工作: ```cpp #include <opencv2/core.hpp> #include <iostream> #include <typeinfo> int main() { try { cv::Mat mat(3, 3, CV_8UC1); std::cout << "Type name: " << typeid(mat).name() << std::endl; } catch (const std::bad_cast& e) { std::cerr << "Error during type casting: " << e.what() << std::endl; } return 0; } ``` 此代码片段尝试打印 `cv::Mat` 对象的类型名称,并捕获任何潜在异常。如果输出为空字符串或其他意外结果,则表明当前环境可能存在RTTI相关问题[^6]。 --- #### 常见错误及其处理方式 当涉及OpenCV和RTTI时,可能会出现一些特定类型的错误消息。下面列举了几种常见情况以及对应的修复建议: | 错误描述 | 可能原因 | 处理措施 | |----------|-----------|------------| | `std::bad_cast` 抛出 | 动态强制转换失败 | 检查源数据结构定义是否一致;确保继承关系清晰无歧义 | | 类型名无法解析 | 缺少必要头文件加载 | 添加 `<typeinfo>` 到包含路径下 | | 性能下降明显 | 过度依赖RTTI检测逻辑 | 替换为静态断言或其他更高效手段 | 以上表格总结了一些典型场景下的应对策略[^7]。 --- ### 提高效率的小贴士 为了减少因频繁调用 `dynamic_cast` 或其他基于RTTI的操作带来的开销,可以考虑采用模板元编程技术替代传统的方法设计思路。比如利用CRTP模式提前绑定子类行为从而规避运行期额外代价。 另外值得注意的是,尽管现代硬件架构对于这类操作优化程度较高但仍需谨慎对待大规模部署场合下的影响评估过程[^8]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值