繁体   English   中英

从uchar到int的C ++数据打包(正数和负数)

[英]C++ data packing from uchar to int (both positive and negative numbers)

我有一个CV_32S类型的OpenCV Mat,其中包含> = -1的整数值。 我试图访问底层数据指针 ,这是一个类型为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.

我将opencv_datauchar *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

看来你在这里误解了一些概念。

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;
}

你错误输入了最后一个班次,它应该是:

(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 *p = reinterpret_cast<int*>(test.data);指向一个简单的int数组int *p = reinterpret_cast<int*>(test.data); 发表于talomies的回答。

最后,所有这些方法都假设打包了2D数组,即: test.step == test.cols * sizeof(int) ,这可能无法保证。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM