Serializing cv::Mat with nlohmann/json lib

738 Views Asked by At

I would like to serialize my own Camera class with the nlohmann/json library:

class Camera
{
  private:
    std::string name_;
    std::string camera_calibration_filename_;
    cv::Mat intrinsics_;
    cv::Mat distortion_;

  public:
    Camera() = default;
    Camera(const std::string& name, const std::string& camera_calibration_filename);

    NLOHMANN_DEFINE_TYPE_INTRUSIVE(Camera, name_, camera_calibration_filename_, intrinsics_, distortion_)
}

As you can see i use the NLOHMANN_DEFINE_TYPE_INTRUSIVE macro to create a simple json with the same names. The intrinsics_ and distortion_ members have the third_party type cv::Mat. Therefore i have to specialize the adl_serializer in the nlohmann namespace:

namespace nlohmann {
    template<>
    struct adl_serializer<cv::Mat> {
        static void to_json(json &j, const cv::Mat &opt) {
            j = opt;
        }

        static void from_json(const json &j, cv::Mat &opt) {
            opt = j.get<cv::Mat>();
        }
    };
} // end namespace nlohmann

Since the cv::Mat type has members of type cv::MatSize, cv::MatStep i have to specialize adl_serializer for them. Since both data types are not copy-constructable but move-constructable i use the special from_json overload described in the documentation:

namespace nlohmann {
    template<>
    struct adl_serializer<cv::MatSize> {
        static void to_json(json &j, const cv::MatSize &opt) {
            j = opt;
        }

        static cv::MatSize from_json(const json &j) {
            return {j.get<cv::MatSize>()};
        }
    };

    template<>
    struct adl_serializer<cv::MatStep> {
        static void to_json(json &j, const cv::MatStep &opt) {
            j = opt;
        }

        static cv::MatStep from_json(const json &j) {
            return {j.get<cv::MatStep>()};
        }
    };
} // namespace nlohmann

But unfortunately the serialization/deserialization is not working correctely (Segmentation fault during serialization:

Camera camera{};
std::cout << "Camera initialized" << std::endl;

nlohmann::json j = camera;
std::cout << "Camera serialized" << std::endl;

auto camera2 = j.get<Camera>();
std::cout << "Camera deserialized" << std::endl;

Can anybody please give me a hint how to proceed?

1

There are 1 best solutions below

1
On

this line makes a recursive call :

static void to_json(json &j, const cv::Mat &opt) {
     j = opt;
}