Serializing OpenCV Mat_

前端 未结 7 1173
刺人心
刺人心 2020-11-30 05:29

I\'m working on a robotics research project where I need to serialize 2D matrices of 3D points: basically each pixel is a 3-vector of floats. These pixels are saved in an Op

相关标签:
7条回答
  • 2020-11-30 05:56

    You can use msgpack also Create an adaptor https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor Here is example code. It might be useful:

    namespace clmdep_msgpack {
    MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
        namespace adaptor {
    
            //I am sending as bin (int)(int)(int)(char*)
            //Mat values:         rows,cols,type,data
            template<>
            struct convert<cv::Mat> {
                clmdep_msgpack::object const &operator()(clmdep_msgpack::object const &o, cv::Mat &v) const
                {
                    if(o.type != clmdep_msgpack::type::BIN) throw clmdep_msgpack::type_error();
                    char *buffer = (char *) o.via.bin.ptr;
                    int buffer_size = o.via.bin.size;
                    int rows, cols, type;
                    rows = *reinterpret_cast<int *>(buffer);
                    cols = *reinterpret_cast<int *>(buffer + 1 * sizeof(int));
                    type = *reinterpret_cast<int *>(buffer + 2 * sizeof(int));
                    cv::Mat(rows, cols, type, (void *) (buffer + 3 * sizeof(int))).copyTo(v);
    
                    return o;
                }
            };
    
            template<>
            struct pack<cv::Mat> {
                template<typename Stream>
                clmdep_msgpack::packer<Stream> &operator()(clmdep_msgpack::packer<Stream> &o, cv::Mat const &v) const
                {
                    // packing member variables as bin.
                    size_t mat_size;
                    if(v.isContinuous()) {
                        mat_size = v.total() * v.elemSize();
                    } else {
                        mat_size = v.step[v.dims - 1];
                        for(int t = 0; t < v.dims; t++) {
                            // calculate total size of multi dimensional matrix by multiplying dimensions
                            mat_size *= v.size[t];
                        }
                    }
                    int extra_ints = 3;
                    int buffer_size = extra_ints * sizeof(int) + mat_size;
                    // Allocate destination image buffer
                    char *imagebuffer = new char[buffer_size];
                    int type = v.type();
                    std::memcpy(imagebuffer, &(v.rows), sizeof(int));
                    std::memcpy(imagebuffer + 1 * sizeof(int), &(v.cols), sizeof(int));
                    std::memcpy(imagebuffer + 2 * sizeof(int), &type, sizeof(int));
    
                    if(v.isContinuous()) {
                        std::memcpy((imagebuffer + 3 * sizeof(int)), (char *) v.data, mat_size);
                    } else {
                        const size_t rowsize = v.step[v.dims - 1] * v.size[v.dims - 1];
                        size_t coordinates[v.dims - 1] = {0};
                        size_t srcptr = 0, dptr = extra_ints * sizeof(int);
                        while(dptr < buffer_size) {
                            // we copy entire rows at once, so lowest iterator is always [dims-2]
                            // this is legal since OpenCV does not use 1 dimensional matrices internally (a 1D matrix is a 2d matrix with only 1 row)
                            std::memcpy(&imagebuffer[dptr], &(((char *) v.data)[srcptr]), rowsize);
                            // destination matrix has no gaps so rows follow each other directly
                            dptr += rowsize;
                            // src matrix can have gaps so we need to calculate the address of the start of the next row the hard way
                            // see *brief* text in opencv2/core/mat.hpp for address calculation
                            coordinates[v.dims - 2]++;
                            srcptr = 0;
                            for(int t = v.dims - 2; t >= 0; t--) {
                                if(coordinates[t] >= v.size[t]) {
                                    if(t == 0) break;
                                    coordinates[t] = 0;
                                    coordinates[t - 1]++;
                                }
                                srcptr += v.step[t] * coordinates[t];
                            }
                        }
                    }
                    o.pack_bin(buffer_size);
                    o.pack_bin_body(imagebuffer, buffer_size);
                    return o;
                }
            };
    
            template<>
            struct object_with_zone<cv::Mat> {
                void operator()(clmdep_msgpack::object::with_zone &o, cv::Mat const &v) const
                {
                    size_t mat_size;
                    if(v.isContinuous()) {
                        mat_size = v.total() * v.elemSize();
                    } else {
                        mat_size = v.step[v.dims - 1];
                        for(int t = 0; t < v.dims; t++) {
                            // calculate total size of multi dimensional matrix by multiplying dimensions
                            mat_size *= v.size[t];
                        }
                    }
                    int extra_ints = 3;
                    int buffer_size = extra_ints * sizeof(int) + mat_size;
                    // Allocate destination image buffer
                    char *imagebuffer = new char[buffer_size];
                    int type = v.type();
                    std::memcpy(imagebuffer, &(v.rows), sizeof(int));
                    std::memcpy(imagebuffer + 1 * sizeof(int), &(v.cols), sizeof(int));
                    std::memcpy(imagebuffer + 2 * sizeof(int), &type, sizeof(int));
    
                    if(v.isContinuous()) {
                        std::memcpy((imagebuffer + 3 * sizeof(int)), (char *) v.data, mat_size);
                    } else {
                        const size_t rowsize = v.step[v.dims - 1] * v.size[v.dims - 1];
                        size_t coordinates[v.dims - 1] = {0};
                        size_t srcptr = 0, dptr = extra_ints * sizeof(int);
                        while(dptr < buffer_size) {
                            // we copy entire rows at once, so lowest iterator is always [dims-2]
                            // this is legal since OpenCV does not use 1 dimensional matrices internally (a 1D matrix is a 2d matrix with only 1 row)
                            std::memcpy(&imagebuffer[dptr], &(((char *) v.data)[srcptr]), rowsize);
                            // destination matrix has no gaps so rows follow each other directly
                            dptr += rowsize;
                            // src matrix can have gaps so we need to calculate the address of the start of the next row the hard way
                            // see *brief* text in opencv2/core/mat.hpp for address calculation
                            coordinates[v.dims - 2]++;
                            srcptr = 0;
                            for(int t = v.dims - 2; t >= 0; t--) {
                                if(coordinates[t] >= v.size[t]) {
                                    if(t == 0) break;
                                    coordinates[t] = 0;
                                    coordinates[t - 1]++;
                                }
                                srcptr += v.step[t] * coordinates[t];
                            }
                        }
                    }
                    o.type = type::BIN;
                    o.via.bin.size = buffer_size;
                    o.via.bin.ptr = imagebuffer;
                }
            };
    
    
        } // namespace adaptor
    } // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
    } // names
    
    0 讨论(0)
提交回复
热议问题