我有一个CV_32S类型的OpenCV Mat,包含整数值> = -1。
我正在尝试访问基础data pointer,它是uchar
类型的平面1D数组。
我认为,因为int
是4字节[32位]而uchar
是1字节[8位],我需要将数据解包为int类型,最初在OpenCV Mat结构中提供。
cv::Mat opencv_data; //! data of type CV_32 with both negative and positive values.
我将uchar *data
opencv_data
指针传递给cuda内核。
要将四个uchars
解压缩为单int
,我会执行以下操作。
int value = (uchar)opencv_data[index] |
(((uchar)opencv_data[index + 1]) << 8) |
(((uchar)opencv_data[index + 2]) << 16);
当opencv_data只有正值时,我在value
中得到正确的解包值。但是,如果我在opencv_data
中添加一个负数,则上述解包会产生value = -1
。
我无法理解这个问题背后的原因,我需要帮助。
根据建议使用reinterpret_cast
编辑。更新代码如下,但对于负数,结果仍然不正确。
//! for test only
cv::Mat test = cv::Mat(40, 60, CV_32S);
for (int j = 0; j < test.rows; j++) {
for (int i = 0; i < test.cols; i++) {
test.at<int>(j, i) = -2;
}
}
int INDICES_BYTE = test.step * test.rows;
uchar *data = reinterpret_cast<uchar*>(test.data);
for (int i = 0; i < INDICES_BYTE; i += 4) {
int index = reinterpret_cast<uchar>(data[i]) |
(reinterpret_cast<uchar>(data[i + 1]) << 8) |
(reinterpret_cast<uchar>(data[i + 2]) << 16) |
(reinterpret_cast<uchar>(data[i + 3]) << 32);
std::cout << index << "\n";
}
编辑后的代码会为正数生成正确的结果,但不会生成test
中的负数。
例如:对于-2,结果是 16777215
答案 0 :(得分:2)
看来你在这里误解了一些概念。
openCV mat
存储内存分配的地址,该地址分配将矩阵数据保存在uchar *
中。这并不意味着数据以任何方式进行转换。如果要直接访问与矩阵关联的数据,只需将指针强制转换为正确的类型并使用该转换指针即可。像这样:
#include <opencv2/core/core.hpp>
#include <iostream>
int main()
{
cv::Mat test = cv::Mat(4, 6, CV_32S);
for (int j = 0; j < test.rows; j++) {
for (int i = 0; i < test.cols; i++) {
test.at<int>(j, i) = -2*i;
}
}
int *p = reinterpret_cast<int*>(test.data);
for(int j=0; j<test.rows; ++j) {
for(int i=0; i<test.cols; ++i) {
std::cout << j << "," << i << " = " << p[i] << std::endl;
}
p += test.cols;
}
return 0;
}
答案 1 :(得分:1)
您错误输入了最后一班,应该是:
(reinterpret_cast<uchar>(data[i + 3]) << 24);
请注意,如果最后一次移位溢出,此方法将调用未定义的行为,但对于大多数当前实现,它不应导致问题。顺便说一句,您不需要reinterpret_cast<uchar>
,因为data
是uchar
的数组。这是一种更安全的方法:
for (int i = 0; i < INDICES_BYTE; i += 4) {
unsigned u32 = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) |
((unsigned)data[i + 3] << 24);
int index = (u32 <= INT_MAX) ? u32 : ~(int)~u32;
std::cout << index << "\n";
}
请注意,此方法会假设整数类型的字节顺序。一种更简单的方法是将test.data
视为指向一个简单的int
int *p = reinterpret_cast<int*>(test.data);
数组,其中test.step == test.cols * sizeof(int)
已发布在 talomies &#39;答案。
最后,所有这些方法都假设2D数组是打包的,即:<p>
,这可能无法保证。