访问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为该表主键,并为自增字段. 但在将某字段设置自增后,想在插入数据时,人为指定自增字段的数据内 ...
随机推荐
- 自然数从1到n之间,有多少个数字含有1
问题明确而简单.for循环肯定是不好的. 用递推方法: 定义h(n)=从1到9999.....9999 ( n 个 9)之间含有1的数字的个数.定义f(n)为n位数中 ...
- 开发错误记录11:git报错 fatal:open /dev/null or dup failed: No such file or directory
今天在自己的的电脑上装了git,没成想运行报错: 重装了几次git ,都不行,电脑上没有装github桌面版; 后来在网上查到了方法,反映这是系统的问题: null是比较特殊的系统文件,它实际上是为操 ...
- ETL利器Kettle实战应用解析系列一【Kettle使用介绍】
本系列文章主要索引如下: 一.ETL利器Kettle实战应用解析系列一[Kettle使用介绍] 二.ETL利器Kettle实战应用解析系列二 [应用场景和实战DEMO下载] 三.ETL利器Kettle ...
- JPA Hibernate应用实例
1.配置文件:persistence.xml <?xml version="1.0" encoding="UTF-8"?> <persiste ...
- git 格式化输出版本信息
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&l ...
- CentOS 6.5升级Python和安装IPython(亲测可用)
python的升级(2.6------>2.7.x) 如下地址:http://note.youdao.com/share/?id=2928aeda020123bfdf2a2c76bc75e4a7 ...
- HoG
实现步骤 先计算每一个像素点位置上x和y方向上的梯度. 这样在每一个像素点位置上得到一个二维向量, 计算它的方向和模长 将图片分为一个个的cell, 如\(8\times 8\). 计算它的HOG: ...
- 强连通 HDU3072
n个点m条边 m条边 权值 简单点说就是求把所有强连通分量连在一起所需的最小花费 不用双向 图是联通的 cost[] 维护到这里的最小花费求和 #include<stdio.h> #in ...
- CentOS6.5下搭建NFS文件服务器
本文参考这里 CentOS下搭建NFS服务器总结 环境介绍: 1. 服务器: 192.168.0.100 2. 客户机: 192.168.0.101 安装软件包: 服务器和客户机都要安装nfs 和 r ...
- git使用相关文章的链接
http://search.fishc.com/cse/search?s=14988791857133860392&q=git&partner=discuz http://bbs.fi ...