我是一名计算机视觉工程师,并且使用OpenCV库。我经常使用unsigned short
类型的原始数据,并且必须将其分配给OpenCV的cv::Mat
对象。
此cv::Mat
对象有一个名为data的字段,无论数据类型如何,此字段的类型都为unsigned char*
。
那么,我将unsigned short*
数据分配给unsigned char*
Mat.data的做法如下:
// Obtain raw data from the hardware
const unsigned short* rawData = engine->getRawData();
// Create Mat with right dimensions and of type 16 Bit unsigned and 1 channel (unsigned short)
cv::Mat Test = cv::Mat::zeros(480, 640, CV_16UC1);
// Assign data by casting rawData to unsigned char* type
Test.data = (unsigned char*) rawData;
// Convert Test to 8Bit unsigned so I can visualize it
Test.convertTo(irIm, CV_8UC1);
我在很多情况下使用这种方法并且工作正常,但我从未真正理解为什么它有效。我有一个unsigned short类型的数据块,然后我把它转换为unsigned char*
并且程序没有崩溃并且没有数据丢失。
任何人都可以帮我理解这个吗?
编辑:
关于我得到的答案。 我知道数据仍然有效但解释不同,但它仍然没有意义。
想象一下,我有以下简短:0010000100001000。现在,我用一个计算器来实现这个短路代表8456的十进制数。如果那时我将其解释为unsigned char,我将其读作两个字节,然后我有00100001字节,然后是00001000,这绝不代表以前的短值。
所以我的问题仍然存在。在我看来唯一有意义的是,OpenCV在某种程度上期待这些演员阵容,并将内部转换数据,因此它不会失去意义。
答案 0 :(得分:1)
人们通常将原始字节缓冲区定义为unsigned char
,因为uint8_t
在语义上是一个字节。稍微好一点的可能是使用标准化的整数类型,例如void*
,但两者都可以看到。
从一种指针类型转换为另一种指针类型只会更改它指向的数据的解释。它不会触及数据本身。
类似的情况是void*
,有时人们会使用此类型来传递未指定内容的缓冲区。但是,对于{{1}},您不能使用指针算术的标准语法,在内部这样的指针通常被强制转换为适当的类型(或被视为单独的字节)。
答案 1 :(得分:0)
data
字段是指向矩阵数据的指针。
预计在(unsigned char*)
。您可以将不同类型的指针强制转换为(unsigned char*)
。它们仍然指向存储rawData
的内存地址。
但重要的是,当您创建矩阵时,您将数据类型指定为CV_16UC1
。 (一个元素是16位且无符号。请参阅Documentation)。
因此,如果您的计算机short
为2个字节,则(unsigned short*)
可以转换为(unsigned char*)
,但矩阵仍然有效。
答案 2 :(得分:0)
C ++有一个内存模型,它将计算机内存视为字节可寻址:
C ++程序可用的内存由一个或多个连续字节序列组成。每个字节都有一个唯一的地址。
- C ++标准, [intro.memory] / 1
由于历史原因,C ++使用字符类型 byte
,char
而不是使用unsigned char
类型来按字节方式访问内存字节。 signed char
:
T
类型对象的对象表示是由N
unsigned char
个对象占用的序列T
类型的对象,其中N
等于sizeof(T)
。
- 同上, [basic.types] / 4
这意味着通过将数据指针转换为unsigned char *
来访问程序内存始终是合法的。