简体   繁体   中英

Sending a Mat object over socket from Java to Java

I understand Sockets over Java and sending Int,String,bytes etc over it.

What i just want to know is that is there a way to decode a Mat object to byte array and then send it over java socket and then retrieve back the Mat object from the byte received?

Till Now this is What I have done

For Sending Mat over socket

//Sending Mat over Socket

Mat socketmat;      
long  nbytes = socketmat.total() * socketmat.elemSize();
byte[] bytes = new byte[ (int) nbytes ];
socketmat.get(0, 0,bytes);
mybytearray = bytes;

dos = new DataOutputStream(os);
dos.writeLong(nbytes);
dos.write(mybytearray, 0, mybytearray.length);  

dos.flush(); 

For Receiving Mat over Socket

//Receiving Mat over Socket

long len = clientData.readLong();  
byte[] data = new byte[ (int) len];
if (len > 0) {
    clientData.readFully(data);
}            
byte[] bytes_ = data;
result_mat.get(0, 0, bytes_ );

What I think is to Save Mat using FileStorage class using JNI.

The following code can be used to save Mat as File Storage

FileStorage storage("image.xml", FileStorage::WRITE);
storage << "img" << mat;
storage.release();

Then send the file using Socket and then retrive Mat back from File.

FileStorage fs("image.xml", FileStorage::READ);
Mat img;
fs >> img;

As other pointed out, you can solve your problem using Serialization . You should let your Mat class implement the Serializable interface.

Next, instead of converting your object to bytes manually, you can just write your object directly, by wrapping your stream in an ObjectOutputStream

ObjectOutputStream oos = new ObjectOutputStream(outputStream);
oos.writeObject(mat);

On receival you can extract the object in the same way.

ObjectInputStream ois = new ObjectInputStream(inputStream);
Mat mat = (Mat)(ois.readObject());

Instead of using byte 's to communicate, you could replace the above by a more flexible XML-based communication. You can let java create the XML for you using JAXB (Java Architecture for Xml Binding), which is pretty easy and in a way also very similar to serialization.

// for sender
JAXBContext jc = JAXBContext.newInstance(Mat.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(mat, outputStream);

// for receiver
JAXBContext jc = JAXBContext.newInstance(Mat.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Mat mat = unmarshaller.unmarshal(inputStream);

In your case your object has native references . But for this problem there is a simple solution. Just break the native bounds by creating a wrapper class

import java.io.Serializable;

public class MatWrapper implements Serializable {
    int rows;
    int cols;
    int type;
    byte[] data;

    public MatWrapper() {
    }

    public MatWrapper(Mat mat)
    {
        if (mat.isContinuous()) {

            int elemSize = (int) mat.elemSize();
            rows = mat.rows();
            cols = mat.cols();
            type = mat.type();

            data = new byte[cols * rows * elemSize];
            mat.get(0, 0, data);
        }
    }

    public Mat toMat()
    {
        Mat mat = new Mat(rows, cols, type);
        mat.put(0, 0, data);
        return mat;
    }
}

Usage:

// convert Mat object to a wrapper object
MatWrapper wrapper = new MatWrapper(mat);

// this wrapper object is serializable

// next on receiver-side
MatWrapper wrapper = (MatWrapper)(ois.readObject);
Mat mat = wrapper.toMat();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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