简体   繁体   English

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

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

I have a OpenCV Mat of type CV_32S with contains integer values of >= -1. 我有一个CV_32S类型的OpenCV Mat,其中包含> = -1的整数值。 I am trying to access the underlying data pointer which is a flat 1D array of type uchar . 我试图访问底层数据指针 ,这是一个类型为uchar的平面1D数组。

I suppose that since int is 4 byte [32 bits] and uchar is 1 byte [8 bits] I need to unpack the data into int type which is initially provided in a OpenCV Mat structure. 我想因为int是4字节[32位]而uchar是1字节[8位]我需要将数据解包为int类型,这最初是在OpenCV Mat结构中提供的。

cv::Mat opencv_data;  //! data of type CV_32 with both negative and positive values.

I pass the uchar *data pointer of opencv_data to cuda kernel. 我将opencv_datauchar *data指针opencv_data给cuda内核。 To unpack the four uchars into single int I doing the following. 要将四个uchars解压缩为单个int我会执行以下操作。

int value =   (uchar)opencv_data[index] |
            (((uchar)opencv_data[index + 1]) << 8) |
            (((uchar)opencv_data[index + 2]) << 16);

When the opencv_data has only positive values I get the correct unpack value in value . 当opencv_data只有正值时,我得到正确的解包value However if I put a single negative number in opencv_data the above unpacking produces value = -1 . 但是,如果我在opencv_data放入一个负数,则上面的解包会产生value = -1

I fail to understand the reason behind this problem and I need help with this. 我无法理解这个问题背后的原因,我需要帮助。

EDIT: based on suggestion to use reinterpret_cast . 编辑:基于使用reinterpret_cast建议。 The update code is below but for negative numbers the result is still not correct. 更新代码如下,但对于负数,结果仍然不正确。

//! 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";
}

The edited code produces correct result for positive number but not for negative numbers in test . 编辑后的代码生成正数的正确结果,但不会生成test负数。

Eg: for -2 the result is 16777215 例如:对于-2,结果为16777215

It would appear that there are a few concepts you have misunderstood here. 看来你在这里误解了一些概念。

The openCV mat stores the address of the memory allocation which holds the matrix data in a uchar * . openCV mat存储内存分配的地址,该地址分配将矩阵数据保存在uchar * This doesn't mean that the data is in any way transformed. 这并不意味着数据以任何方式进行转换。 If you want to access the data associated with the matrix directly, you simply cast the pointer to the correct type and use that cast pointer. 如果要直接访问与矩阵关联的数据,只需将指针强制转换为正确的类型并使用该转换指针即可。 Like this: 像这样:

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

You mistyped the last shift, it should be: 你错误输入了最后一个班次,它应该是:

(reinterpret_cast<uchar>(data[i + 3]) << 24);

Note that this method invokes undefined behavior if the last shift overflows, but for most current implementations, it should not cause a problem. 请注意,如果最后一次移位溢出,此方法将调用未定义的行为,但对于大多数当前实现,它不应导致问题。 Btw, you do not need the reinterpret_cast<uchar> since data is an array of uchar . 顺便说一下,你不需要reinterpret_cast<uchar>因为data是一个uchar数组。 Here is a safer method: 这是一个更安全的方法:

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

Note still that this method makes assumptions about the byte ordering of integer types. 还要注意,此方法假设整数类型的字节顺序。 A much simpler approach is to consider test.data as pointing to a simple array of int with int *p = reinterpret_cast<int*>(test.data); 一种更简单的方法是将test.data视为使用int *p = reinterpret_cast<int*>(test.data);指向一个简单的int数组int *p = reinterpret_cast<int*>(test.data); as posted in talomies ' answer. 发表于talomies的回答。

Finally, all these methods assume that the 2D array is packed, ie: test.step == test.cols * sizeof(int) , which may not be guaranteed. 最后,所有这些方法都假设打包了2D数组,即: test.step == test.cols * sizeof(int) ,这可能无法保证。

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

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