访问cv::Mat中的数据时遇到的指针类型问题
在用Opencv的时候由于下图原本的图像尺寸是1111*1111,要进行resize,代码如下:
cv::Mat img = cv::imread("//Users//apple//td3//vase//19201.png",CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat img2;
cv::resize(img, img2, cv::Size(400,400),0,0, cv::INTER_AREA);
因为我根本不知道img的数据是什么类型(不知道数据类型根本无法通过指针计算来访问每个像素的值,而且我想操作逐个像素来做blur),然后我就用int指针去访问,结果自然是很容易错误的。我将访问的值写入文本之后发现都是些奇怪的数值,例如-1,4294967296(2^32),还以其他奇葩数值。结果如果我利用其opencv自己重载的函数输出:
std::cout << img2.at<int>(0,0); //输出(0,0)的像素值为-1
std::cout << img2; //输出矩阵的所有像素的像素值,结果很正常属于[0,255]
结果我以为矛盾,然后直接访问img2.data成员,写了一些很没道理的代码:
for(int row = 0; row <img2.rows; row++){
uchar *ptr = (img2.data + row*img2.step);
for(int col = 0; col < img2.cols; col++){
int *intTmp = (int*)(ptr+col); //结果输出自然是错的,因为img2的数据类型是uchar,一个像素用8位表示
std::cout << *intTmp << ' '; //而强制转换成int*后访问的时候就直接取出32位
}
std::cout << std::endl;
}
然后设置断点查看了下img2.data里面的数据是'\xff',然后用cout打印出来是'\377',原来是字符串的十六进制和八进制表示,仔细分析为什么'\377'的值是-1,结果得出:
在C中有两种特殊的字符,八进制转义字符和十六进制转义字符,八进制字符的一般形式是'\ddd',d是0-9的数字。十六进制字符的一般形式是'\xhh',h是0-9或A-F内的一个。八进制字符和十六进制字符表示的是字符的ASCII码对应的数值。比如
'\063'表示的是字符'3',因为'3'的ASCII码是30(十六进制),48(十进制),63(八进制)。
'\x41'表示的是字符'A',因为'A'的ASCII码是41(十六进制),65(十进制),101(八进制)。
负数在计算机内部是用补码表示的 例如 -1 1 的原码是 0000 0001 则 -1 的反码是 1111 1110 补码是 1111 1111
因为我强制转换为int指针,所以是指针指向的数是有符号的,并且一次性取得32位,将这4个'\xff'表示为二进制:1111 1111 1111 1111 1111 1111 1111 1111(32个1)所以在有符号整数中的值就是-1,而在无符号中的值又是4294967295。但是均不是我想要的255,然后查了各种资料,结果看到这个网站:
http://stackoverflow.com/questions/23819445/why-is-xff-not-being-recognized
中有一句话剪切过来:
'\xff' is a character constant, not a string literal. String literals have no signedness; they represent arrays. Type char may be either signed or unsigned, depending on the implementation. If plain char is unsigned, then '\xff' has the value 255 of type int. If plain char is signed, the wording of the standard is unclear (at least to me).
结果我试了几组代码:
char *sign_t = new char('\377');
int j = *sign_t; //值是-1
uint *intTest = new uint('\xff\xff\xff\xff'); //值是4294967295
uchar *t = new uchar('\xff');
int *pp = (int*)t; //值是255
结果我明白了很多,错误始终是在一开始我根本不清楚cv::Mat中的数据的深度和通道信息,然后我搜索了到了一个解答:
http://stackoverflow.com/questions/10167534/how-to-find-out-what-type-of-a-mat-object-is-with-mattype-in-opencv
http://answers.opencv.org/question/742/matrix-depth-equals-0/
将其解答剪切出来,我们可以用img2::type(), img2::channels(), img2::depth()来确定mat的类型。但是img2::type与img2::depth()需要区别如下:

So,至此所有问题都明朗了,最后贴上一个正确访问CV_8UC1类型Mat.data数据的代码:
for(int row = 40; row <img2.rows-200; row++){
uchar *ptr = (img2.data + row*img2.step);
for(int col = 20; col < img2.cols-200; col++){
uchar *ptrTmp = ptr+col;
*ptrTmp = 0;
}
std::cout << std::endl;
}
结果图如下:


还有留下的问题需要解决,继续看opencv,就是如果我要逐个操作每个像素值,我是否应该将CV_8UC1类型转为浮点型计算完成之后再转回来。还有另外一个问题就是负数的二进制表示还需要再看看资料。
访问cv::Mat中的数据时遇到的指针类型问题的更多相关文章
- 从Excel中导入数据时,提示“未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序”的解决办法
注意,64位系统,用64位的补丁文件; https://www.cnblogs.com/A2008A/articles/2438962.html 操作系统:使用的是64位的Windows Server ...
- 读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots
读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots 以下为异常详细信息: Exception in thread &q ...
- 触发器修改后保存之前的数据 表中插入数据时ID自动增长
create or replace trigger t before update on test5 for each rowbegin insert into test55 values (:old ...
- 在Oracle中更新数据时,抛出:ORA-01008: not all variables bound
在Oracle中更新数据时,抛出了一个 :ORA-01008 not all variables bound, 我的理解是不是所有的变量/参数都有边界,不懂: 后来知道了,原来是“不是所有变量/参数都 ...
- OpenCV几种访问cv::Mat数据的方法
一般来说,如果是遍历数据的话用指针ptr比用at要快.特别是在debug版本下.因为debug中,OpenCV会对at中的坐标检查是否有溢出,这是非常耗时的. 代码如下 #include <op ...
- [MySQL]load data local infile向MySQL数据库中导入数据时,无法导入和字段不分离问题。
利用load data将文件中的数据导入数据库表中的时候,遇到了两个问题. 首先是load data命令无法执行的问题: 命令行下输入load data local infile "path ...
- C#读取Excel表中的数据时,为何有些行的字段内容读取不到
转载:http://bbs.csdn.net/topics/360220285 1.当某列数据中含有混合类型时,在.NET中使用Microsoft.Jet.OLEDB.4.0来读取Excel文件造成数 ...
- 在往oracle中插数据时,如何处理excel读取的时间空值
//若从excel中读取的时间值为空值时,做如下转换 string YDKGSJ = string.Empty; if (dbdata.Rows[i]["约定开工时间"].ToSt ...
- 在向"带有自增字段的数据库表"中插入数据时,自定义"该自增字段"的数据
在设计数据库表的时候,经常会使用自增主键或其他自增字段.比如: DB_UserGroups表中GroupID为该表主键,并为自增字段. 但在将某字段设置自增后,想在插入数据时,人为指定自增字段的数据内 ...
随机推荐
- UTF-8 's format
几篇比较好的博客 古腾龙的博客:编码规则(UTF-8 GBK) GBK 千千秀字 shell set man ascii可以查看ascii码表,man utf-8看以查看utf-8的帮助 Unicod ...
- 查询和修改(Queries and Mutations)
On this page, you'll learn in detail about how to query a GraphQL server. 在这个页面,你将会学习更多的关于如何查询GraphQ ...
- 在stream流和byte[]中查找(搜索)指定字符串
在 stream流 和 byte[] 中查找(搜索)指定字符串 这里注重看的是两个 Search 的扩展方法,一个是 stream 类型的扩展,另一个是 byte[] 类型的扩展, 如果大家有更好的“ ...
- Android Studio 优秀插件汇总
第一部分 插件的介绍 Google 在2013年5月的I/O开发者大会推出了基于IntelliJ IDEA java ide上的Android Studio.AndroidStudio是一个功能齐全的 ...
- spring 集成shiro 之 自定义过滤器
在web.xml中加入 <!-- 过期时间配置 --> <session-config><session-timeout>3</session-timeout ...
- git 删除和重命名文件
1. 删除文件 git rm a.txt git rm--cached filename 会删除索引中的文件并把它保留在工作目录中 而 git rm 则会将文件从索引和工作目录中都删除 文件删除后的恢 ...
- 引入AOP 报错 error at ::0 formal unbound in pointcut
使用了AOP 后启动报错 九月 27, 2016 2:29:46 下午 org.springframework.context.support.AbstractApplicationContext r ...
- css-@keyframes动画
详细w3c这里 http://www.cnblogs.com/happyPawpaw/archive/2012/09/12/2681348.html Internet Explorer 10.Fire ...
- git初体验(一)基础
一.window下的git安装 1.安装教程 网上教程一堆,我参考的是这个:Git_Windows 系统下Git安装图解 还有这个也不错 2.环境搭建: 在配置完成后,自动加载到系统环境变量中,如我的 ...
- 控件 UI: StateTrigger
VisualState 之 StateTrigger 示例1.自定义 StateTriggerControls/UI/VisualState/MyDeviceFamilyStateTrigger.cs ...