Per poter inviare un'immagine tramite HTTP, è inoltre necessario codificarne larghezza, altezza e tipo. È necessario serializzare lo Mat
in uno stream e codificare quel flusso con libb64. Dall'altra parte è necessario decodificare quel flusso e deserializzare l'immagine per recuperarla.
Ho implementato un piccolo programma di test che esegue questa serializzazione e deserializzazione utilizzando std::stringstream
come buffer. L'ho scelto perché estende sia std::istream
e std::ostream
che libb64 utilizza.
La funzione serialize
serializza un cv::Mat
in un std::stringstream
. In esso, scrivo la larghezza, l'altezza, il tipo, la dimensione del buffer e il buffer stesso.
La funzione deserialize
esegue il contrario. Legge la larghezza, l'altezza, il tipo, la dimensione del buffer e il buffer. Non è così efficiente come potrebbe essere perché ha bisogno di allocare un buffer temporaneo per leggere i dati dallo stringstream. Inoltre, ha bisogno di clonare l'immagine in modo che non faccia affidamento sul buffer temporaneo e gestirà la propria allocazione di memoria. Sono sicuro che con qualche ritocco può essere reso più efficiente.
La funzione principale carica un'immagine, la serializza, la codifica utilizzando libb64, quindi la decodifica, la deserializza e la visualizza in una finestra. Questo dovrebbe simulare ciò che stai cercando di fare.
// Serialize a cv::Mat to a stringstream
stringstream serialize(Mat input)
{
// We will need to also serialize the width, height, type and size of the matrix
int width = input.cols;
int height = input.rows;
int type = input.type();
size_t size = input.total() * input.elemSize();
// Initialize a stringstream and write the data
stringstream ss;
ss.write((char*)(&width), sizeof(int));
ss.write((char*)(&height), sizeof(int));
ss.write((char*)(&type), sizeof(int));
ss.write((char*)(&size), sizeof(size_t));
// Write the whole image data
ss.write((char*)input.data, size);
return ss;
}
// Deserialize a Mat from a stringstream
Mat deserialize(stringstream& input)
{
// The data we need to deserialize
int width = 0;
int height = 0;
int type = 0;
size_t size = 0;
// Read the width, height, type and size of the buffer
input.read((char*)(&width), sizeof(int));
input.read((char*)(&height), sizeof(int));
input.read((char*)(&type), sizeof(int));
input.read((char*)(&size), sizeof(size_t));
// Allocate a buffer for the pixels
char* data = new char[size];
// Read the pixels from the stringstream
input.read(data, size);
// Construct the image (clone it so that it won't need our buffer anymore)
Mat m = Mat(height, width, type, data).clone();
// Delete our buffer
delete[]data;
// Return the matrix
return m;
}
void main()
{
// Read a test image
Mat input = imread("D:\\test\\test.jpg");
// Serialize the input image to a stringstream
stringstream serializedStream = serialize(input);
// Base64 encode the stringstream
base64::encoder E;
stringstream encoded;
E.encode(serializedStream, encoded);
// Base64 decode the stringstream
base64::decoder D;
stringstream decoded;
D.decode(encoded, decoded);
// Deserialize the image from the decoded stringstream
Mat deserialized = deserialize(decoded);
// Show the retrieved image
imshow("Retrieved image", deserialized);
waitKey(0);
}
Cosa stai cercando di realizzare alla fine? Vuoi serializzare l'immagine (vuoi poterla leggere dall'altra parte)? Se si codificano solo i dati dell'immagine, non si conoscono la larghezza, l'altezza o il numero di canali. Perché non basi64 codificare il file di input invece del Mat? Inoltre, se si desidera inviare l'immagine su un socket, non è necessario codificarlo base64, è sufficiente inviarlo così com'è e ridurre il sovraccarico. – Ove
@ L'altra estremità sul socket può essere diversa per architettura o piattaforma e non utilizzerà C++. Speravo di evitare certi problemi serializzando con base64, ma sono aperto a qualsiasi suggerimento. Quindi, pensi che sia meglio serializzare la foto invece del cv :: Mat? Il problema è che potrebbe non esserci alcuna immagine, ma un'immagine catturata da una telecamera. Inoltre, il socket utilizza il protocollo HTTP, quindi sto postando testo JSON. –