0

I've tried to serialize a map of pairs and obtained an exception as below:

 java.io.NotSerializableException: org.opencv.core.Mat

Is there some kind of way to serialize this?

Araneo
  • 477
  • 2
  • 9
  • 25
  • The following SO answer has information concerning getting a `Mat` into Java primitives, which of course are serializable: https://stackoverflow.com/a/44089416/897007 – Dale May 23 '17 at 14:41

4 Answers4

3

no, not so easy.

the actual data is held inside the c++ native so, so your serialize() won't reach into that.

what you can do:

Mat mat = ...
byte[] bytes = new byte[mat.total()*mat.elemSize()];
mat.get(0,0,bytes);
// now somehow save mat.type(), mat.rows(), mat.cols() and the bytes, later restore it:
Mat m2 = new Mat(rows,cols,type);
m2.put(0,0, bytes);
berak
  • 39,159
  • 9
  • 91
  • 89
  • Is any other easy way to make something like database and store there all Mat objects I have? – Araneo Nov 21 '14 at 17:13
3

I made some improvments from here. Tested and working SerializationUtils class here

public static String matToJson(Mat mat){
    JsonObject obj = new JsonObject();

    if(mat.isContinuous()){
        int cols = mat.cols();
        int rows = mat.rows();
        int elemSize = (int) mat.elemSize();
        int type = mat.type();

        obj.addProperty("rows", rows);
        obj.addProperty("cols", cols);
        obj.addProperty("type", type);

        // We cannot set binary data to a json object, so:
        // Encoding data byte array to Base64.
        String dataString;

        if( type == CvType.CV_32S || type == CvType.CV_32SC2 || type == CvType.CV_32SC3 || type == CvType.CV_16S) {
            int[] data = new int[cols * rows * elemSize];
            mat.get(0, 0, data);
            dataString = new String(Base64.encodeBase64(SerializationUtils.toByteArray(data)));
        }
        else if( type == CvType.CV_32F || type == CvType.CV_32FC2) {
            float[] data = new float[cols * rows * elemSize];
            mat.get(0, 0, data);
            dataString = new String(Base64.encodeBase64(SerializationUtils.toByteArray(data)));
        }
        else if( type == CvType.CV_64F || type == CvType.CV_64FC2) {
            double[] data = new double[cols * rows * elemSize];
            mat.get(0, 0, data);
            dataString = new String(Base64.encodeBase64(SerializationUtils.toByteArray(data)));
        }
        else if( type == CvType.CV_8U ) {
            byte[] data = new byte[cols * rows * elemSize];
            mat.get(0, 0, data);
            dataString = new String(Base64.encodeBase64(data));
        }
        else {

            throw new UnsupportedOperationException("unknown type");
        }
        obj.addProperty("data", dataString);

        Gson gson = new Gson();
        String json = gson.toJson(obj);

        return json;
    } else {
        System.out.println("Mat not continuous.");
    }
    return "{}";
}

public static Mat matFromJson(String json){


    JsonParser parser = new JsonParser();
    JsonObject JsonObject = parser.parse(json).getAsJsonObject();

    int rows = JsonObject.get("rows").getAsInt();
    int cols = JsonObject.get("cols").getAsInt();
    int type = JsonObject.get("type").getAsInt();

    Mat mat = new Mat(rows, cols, type);

    String dataString = JsonObject.get("data").getAsString();
    if( type == CvType.CV_32S || type == CvType.CV_32SC2 || type == CvType.CV_32SC3 || type == CvType.CV_16S) {
        int[] data = SerializationUtils.toIntArray(Base64.decodeBase64(dataString.getBytes()));
        mat.put(0, 0, data);
    }
    else if( type == CvType.CV_32F || type == CvType.CV_32FC2) {
        float[] data = SerializationUtils.toFloatArray(Base64.decodeBase64(dataString.getBytes()));
        mat.put(0, 0, data);
    }
    else if( type == CvType.CV_64F || type == CvType.CV_64FC2) {
        double[] data = SerializationUtils.toDoubleArray(Base64.decodeBase64(dataString.getBytes()));
        mat.put(0, 0, data);
    }
    else if( type == CvType.CV_8U ) {
        byte[] data = Base64.decodeBase64(dataString.getBytes());
        mat.put(0, 0, data);
    }
    else {

        throw new UnsupportedOperationException("unknown type");
    }
    return mat;
}
Joker
  • 96
  • 6
0

I changed others code ,and it seems work. Hope it can help.

 public static byte[] serializeMat(Mat mat) {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                float[] data = new float[(int) mat.total() * mat.channels()];
                mat.get(0, 0, data);
                ObjectOutput out = new ObjectOutputStream(bos);
                out.writeObject(data);
                out.close();
                // Get the bytes of the serialized object
                byte[] buf = bos.toByteArray();
                return buf;
            } catch (IOException ioe) {
                ioe.printStackTrace();
                return null;
            }
        }
Fang
  • 136
  • 5
0

You can dump the contents to a String a serialize that, like so:

Mat mat = new Mat();
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(mat.dump());
Willeman
  • 720
  • 10
  • 24