package resa.evaluation.topology.tomVLD;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoSerializable;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.opencv_core;
import java.io.*;
/**
* This class provides kryo serialization for the JavaCV's Mat and Rect objects, so that Storm can wrap them in tuples.
* Serializable.Mat - kryo serializable analog of opencv_core.Mat object.<p>
* Serializable.Rect - kryo serializable analog of opencv_core.Rect object.<p>
* Serializable.PatchIdentifier is also kryo serializable object,
* which is used to identify each patch of the frame.<p>
* <p>
*
* @author Nurlan Kanapin
* @see Serializable.Mat
* @see Serializable.Rect
* @see Serializable.PatchIdentifier
*/
public class Serializable {
/**
* Kryo Serializable Mat class.
* Essential fields are image data itself, rows and columns count and type of the data.
*/
public static class Mat implements KryoSerializable, java.io.Serializable {
private byte[] data;
private int rows, cols, type;
public int getRows() {
return rows;
}
public int getCols() {
return cols;
}
public int getType() {
return type;
}
public Mat() {
}
/**
* Creates new serializable Mat given its format and data.
*
* @param rows Number of rows in the Mat object
* @param cols Number of columns in the Mat object
* @param type OpenCV type of the data in the Mat object
* @param data Byte data containing image.
*/
public Mat(int rows, int cols, int type, byte[] data) {
this.rows = rows;
this.cols = cols;
this.type = type;
this.data = data;
}
/**
* Creates new serializable Mat from opencv_core.Mat
*
* @param mat The opencv_core.Mat
*/
public Mat(opencv_core.Mat mat) {
if (!mat.isContinuous())
mat = mat.clone();
this.rows = mat.rows();
this.cols = mat.cols();
this.type = mat.type();
int size = mat.arraySize();
this.data = new byte[size];
mat.getByteBuffer().get(this.data);
// ByteBuffer bb = mat.getByteBuffer();
// bb.rewind();
// this.data = new byte[size];
// while (bb.hasRemaining()) // should happen only once
// bb.get(this.data);
}
/**
* Creates new serializable Mat given its format and data.
*
* @param input Byte data containing image.
*/
public Mat(byte[] input) {
ByteArrayInputStream bis = new ByteArrayInputStream(input);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
this.rows = in.readInt();
this.cols = in.readInt();
this.type = in.readInt();
int size = in.readInt();
this.data = new byte[size];
int readed = 0;
while (readed < size) {
readed += in.read(data, readed, size - readed);
}
//System.out.println("in: " + this.rows + "-" + this.cols + "-" + this.type + "-" + size + "-" + readed);
} catch (IOException e) {
e.printStackTrace();
}
}
public byte[] toByteArray() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeInt(this.rows);
out.writeInt(this.cols);
out.writeInt(this.type);
out.writeInt(this.data.length);
out.write(this.data);
out.close();
byte[] int_bytes = bos.toByteArray();
bos.close();
//System.out.println("out: " + this.rows + "-" + this.cols + "-" + this.type + "-" + this.data.length + "-" + int_bytes.length);
return int_bytes;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static byte[] toByteArray(Serializable.Mat rawFrame, Serializable.Mat optFlow) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeInt(rawFrame.rows);
out.writeInt(rawFrame.cols);
out.writeInt(rawFrame.type);
out.writeInt(rawFrame.data.length);
out.write(rawFrame.data);
out.writeInt(optFlow.rows);
out.writeInt(optFlow.cols);
out.writeInt(optFlow.type);
out.writeInt(optFlow.data.length);
out.write(optFlow.data);
out.close();
byte[] int_bytes = bos.toByteArray();
bos.close();
//System.out.println("out: " + this.rows + "-" + this.cols + "-" + this.type + "-" + this.data.length + "-" + int_bytes.length);
return int_bytes;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static Serializable.Mat[] toSMat(byte[] input) {
ByteArrayInputStream bis = new ByteArrayInputStream(input);
ObjectInput in = null;
Serializable.Mat rawFrame = new Serializable.Mat();
Serializable.Mat optFlow = new Serializable.Mat();
try {
in = new ObjectInputStream(bis);
rawFrame.rows = in.readInt();
rawFrame.cols = in.readInt();
rawFrame.type = in.readInt();
int size = in.readInt();
rawFrame.data = new byte[size];
int readed = 0;
while (readed < size) {
readed += in.read(rawFrame.data, readed, size - readed);
}
optFlow.rows = in.readInt();
optFlow.cols = in.readInt();
optFlow.type = in.readInt();
size = in.readInt();
optFlow.data = new byte[size];
readed = 0;
while (readed < size) {
readed += in.read(optFlow.data, readed, size - readed);
}
return new Serializable.Mat[]{rawFrame, optFlow};
//System.out.println("in: " + this.rows + "-" + this.cols + "-" + this.type + "-" + size + "-" + readed);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @return Converts this Serializable Mat into JavaCV's Mat
*/
public opencv_core.Mat toJavaCVMat() {
return new opencv_core.Mat(rows, cols, type, new BytePointer(data));
}
@Override
public void write(Kryo kryo, Output output) {
output.writeInt(this.rows);
output.writeInt(this.cols);
output.writeInt(this.type);
output.writeInt(this.data.length);
output.writeBytes(this.data);
}
@Override
public void read(Kryo kryo, Input input) {
this.rows = input.readInt();
this.cols = input.readInt();
this.type = input.readInt();
int size = input.readInt();
this.data = input.readBytes(size);
}
}
/**
* Kryo Serializable Rect class.
*/
public static class Rect implements KryoSerializable, java.io.Serializable {
/**
* x, y, width, height - x and y coordinates of the left upper corner of the rectangle, its width and height
*/
public int x, y, width, height;
public Rect() {
}
public Rect(opencv_core.Rect rect) {
x = rect.x();
y = rect.y();
width = rect.width();
height = rect.height();
}
public Rect(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
public opencv_core.Rect toJavaCVRect() {
return new opencv_core.Rect(x, y, width, height);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Rect rect = (Rect) o;
if (height != rect.height) return false;
if (width != rect.width) return false;
if (x != rect.x) return false;
if (y != rect.y) return false;
return true;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
result = 31 * result + width;
result = 31 * result + height;
return result;
}
@Override
public void write(Kryo kryo, Output output) {
output.writeInt(x);
output.writeInt(y);
output.writeInt(width);
output.writeInt(height);
}
@Override
public void read(Kryo kryo, Input input) {
x = input.readInt();
y = input.readInt();
width = input.readInt();
height = input.readInt();
}
}
/**
* This is a serializable class used for patch identification. Each patch needs to be distinguished form others.
* Each patch is uniquely identified by the id of its frame and by the rectangle it corresponds to.
*/
public static class PatchIdentifier implements KryoSerializable, java.io.Serializable {
/**
* Frame id of this patch
*/
public int frameId;
/**
* Rectangle or Region of Interest of this patch.
*/
public Rect roi;
public PatchIdentifier() {
}
/**
* Creates PatchIdentifier with given frame id and rectangle.
*
* @param frameId
* @param roi
*/
public PatchIdentifier(int frameId, Rect roi) {
this.roi = roi;
this.frameId = frameId;
}
@Override
public void write(Kryo kryo, Output output) {
output.writeInt(frameId);
output.writeInt(roi.x);
output.writeInt(roi.y);
output.writeInt(roi.width);
output.writeInt(roi.height);
}
@Override
public void read(Kryo kryo, Input input) {
frameId = input.readInt();
int x = input.readInt();
int y = input.readInt();
int width = input.readInt();
int height = input.readInt();
roi = new Rect(x, y, width, height);
}
/**
* String representation of this patch identifier.
*
* @return the string in the format N%04d@%04d@%04d@%04d@%04d if roi is not null, and N%04d@null otherwise.
*/
public String toString() {
if (roi != null)
return String.format("N%04d@%04d@%04d@%04d@%04d", frameId, roi.x, roi.y, roi.x + roi.width, roi.y + roi.height);
return String.format("N%04d@null", frameId);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PatchIdentifier that = (PatchIdentifier) o;
if (frameId != that.frameId) return false;
if (roi != null ? !roi.equals(that.roi) : that.roi != null) return false;
return true;
}
@Override
public int hashCode() {
int result = frameId;
result = 31 * result + (roi != null ? roi.hashCode() : 0);
return result;
}
}
public static class CvPoint2D32f implements KryoSerializable, java.io.Serializable {
float x;
float y;
public CvPoint2D32f() {
}
public CvPoint2D32f(opencv_core.CvPoint2D32f p) {
this.x = p.x();
this.y = p.y();
}
public CvPoint2D32f(CvPoint2D32f p) {
this.x = p.x();
this.y = p.y();
}
public opencv_core.CvPoint2D32f toJavaCvPoint2D32f() {
return new opencv_core.CvPoint2D32f().x(this.x).y(this.y);
}
public float x() {
return this.x;
}
public float y() {
return this.y;
}
public void x(float x) {
this.x = x;
}
public void y(float y) {
this.y = y;
}
@Override
public void write(Kryo kryo, Output output) {
output.writeFloat(this.x);
output.writeFloat(this.y);
}
@Override
public void read(Kryo kryo, Input input) {
this.x = input.readFloat();
this.y = input.readFloat();
}
}
/**
* This is a serializable class used for patch identification. Each patch needs to be distinguished form others.
* Each patch is uniquely identified by the id of its frame and by the rectangle it corresponds to.
*/
public static class PatchIdentifierMat implements java.io.Serializable {
public PatchIdentifier identifier;
public Mat sMat;
/**
* Creates PatchIdentifier with given frame id and rectangle.
* @param frameId
* @param roi
* @param sMat
*/
public PatchIdentifierMat(int frameId, Rect roi, Mat sMat) {
this.identifier = new PatchIdentifier(frameId, roi);
this.sMat = sMat;
}
/**
* String representation of this patch identifier.
*
* @return the string in the format N%04d@%04d@%04d@%04d@%04d if roi is not null, and N%04d@null otherwise.
*/
public String toString() {
return this.identifier.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PatchIdentifierMat that = (PatchIdentifierMat) o;
return this.identifier.equals(that.identifier);
}
@Override
public int hashCode() {
return this.identifier.hashCode();
}
}
}