OpenCV data of two mats are the same but values when retrieved with Mat::at are corrupted

可紊 提交于 2021-02-11 15:14:51

问题


I serialize and then deserialize a Mat using custom functions. When you compare the uchar* Mat.data of two functions they are the same but when I try to check values directly using Mat.at<> after third element, element values are stuck at some corrupted float values. I tried changing elements to every other value, nothing changed. The problem also doesn't happen when I serialize-deserialize image Mats and histogram Mats. Below is the code and below that is the output.

cv::Mat kernelx = (cv::Mat_<float>(3, 3) << 1, 0, -1, 1, 0, -1, 1, 0, -1);
std::string stroper = dbop::serializeMat(kernelx);
cv::Mat matoper = dbop::deserializeMat(stroper);
for (int i = 0; i < matoper.rows; i++) {
    for (int j = 0; j < matoper.cols; j++) {
        float f1 = (float)kernelx.data[i + j];
        float f2 = (float)matoper.data[i + j];
        std::cout << kernelx.at<float>(i, j) << " " << matoper.at<float>(i, j) << " " << f1 << " " << f2 << " " << std::endl;
    }
}

Here is the output. First values are elements of the original Mat, second values are elements of serialized-deserialized Mat, third values are the original Mat's data values casted to float, fourth values are s-d Mat's data values.

1       1               0       0
0       0               0       0
-1      -4.31596e+08    128     128
1       -4.31602e+08    0       0
0       -4.31602e+08    128     128
-1      -4.31602e+08    63      63
1       -4.31602e+08    128     128
0       -4.31602e+08    63      63
-1      -4.31602e+08    0       0

I guess serializeMat and deserializeMat functions are relevant here so here is both.

std::string dbop::serializeMat(cv::Mat operand) {
    std::ostringstream srlzstrstream;
    uchar* pixelPtr = (uchar*)operand.data;
    int cn = operand.channels();
    cv::Scalar_<uchar> cnPixel;

    srlzstrstream << operand.dims << " ";
    for (int i = 0; i < operand.dims; i++) {
        srlzstrstream << operand.size[i] << " ";
    }
    srlzstrstream << operand.type() << " ";

    for (int i = 0; i < operand.total(); i++) {
            for (int k = 0; k < cn; k++) {
                srlzstrstream << (float)pixelPtr[i * cn + k] << " ";
            }
    }
    std::string srlzdstr = srlzstrstream.str();
    return srlzdstr;
}
cv::Mat dbop::deserializeMat(std::string operand){
    std::istringstream desrlzstrstream(operand);
    int mdims, mtype;

    desrlzstrstream >> mdims;
    int* msize = new int[mdims];
    for (int i = 0; i < mdims; i++)
        desrlzstrstream >> msize[i];
    desrlzstrstream >> mtype;

    cv::Mat matoper(mdims, msize, mtype);
    delete [] msize;

    uchar* pixelPtr = (uchar*)matoper.data;
    float cnpixoper;

    for (int i = 0; i < matoper.total(); i++) {
        for (int k = 0; k < matoper.channels(); k++) {
            desrlzstrstream >> cnpixoper;
            pixelPtr[i * matoper.channels() + k] = cnpixoper;
        }
    }
    return matoper;
}

回答1:


+ Edit
Since you want to save byte for generic types, you can just iterate each byte like this.

In serializeMat

for (int i = 0; i < operand.total() * operand.elemSize(); i++) {
    srlzstrstream << pixelPtr[i] << " ";
}

In deserializeMat

for (int i = 0; i < matoper.total() * matoper.elemSize(); i++) {
    desrlzstrstream >> cnpixoper;
    pixelPtr[i] = cnpixoper;
}

operand.total() * operand.elemSize() will give you the byte size of operand

In both case, the output is

   1    1    0    0 
   0    0    0    0 
  -1   -1  128  128 
   1    1    0    0 
   0    0  128  128 
  -1   -1   63   63 
   1    1  128  128 
   0    0   63   63 
  -1   -1    0    0 


来源:https://stackoverflow.com/questions/62325615/opencv-data-of-two-mats-are-the-same-but-values-when-retrieved-with-matat-are

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!