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

时间:2016-08-28 10:51:32

标签: c++ opencv int

我有一个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

2 个答案:

答案 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>,因为datauchar的数组。这是一种更安全的方法:

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>,这可能无法保证。