Để có thể gửi hình ảnh qua HTTP, bạn cũng cần phải mã hóa chiều rộng, chiều cao và loại của nó. Bạn cần phải tuần tự hóa Mat
vào luồng và mã hóa luồng đó bằng libb64. Ở phía bên kia, bạn cần phải giải mã luồng đó và deserialize hình ảnh để lấy nó.
Tôi đã triển khai một chương trình thử nghiệm nhỏ thực hiện việc tuần tự hóa và deserialization này bằng cách sử dụng std::stringstream
làm bộ đệm. Tôi đã chọn nó vì nó mở rộng cả hai std::istream
và std::ostream
mà libb64 sử dụng.
Chức năng serialize
tuần tự hóa cv::Mat
thành std::stringstream
. Trong đó, tôi viết chiều rộng hình ảnh, chiều cao, loại, kích thước của bộ đệm và chính bộ đệm.
Chức năng deserialize
làm ngược lại. Nó đọc chiều rộng, chiều cao, loại, kích thước của bộ đệm và bộ đệm. Nó không hiệu quả vì nó có thể là do nó cần phân bổ một bộ đệm tạm thời để đọc dữ liệu từ chuỗi. Ngoài ra, nó cần phải sao chép các hình ảnh để nó không dựa vào bộ đệm tạm thời và nó sẽ xử lý phân bổ bộ nhớ riêng của nó. Tôi chắc chắn rằng với một số tinkering nó có thể được thực hiện hiệu quả hơn.
Chức năng chính tải hình ảnh, tuần tự hóa nó, mã hóa nó bằng cách sử dụng libb64, sau đó giải mã nó, deserializes nó và hiển thị nó trong một cửa sổ. Điều này sẽ mô phỏng những gì bạn đang cố gắng làm.
// 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);
}
Bạn đang cố gắng hoàn thành những gì cuối cùng? Bạn có muốn tuần tự hóa hình ảnh (bạn có muốn đọc nó ở phía bên kia) không? Nếu bạn chỉ mã hóa dữ liệu hình ảnh, thì bạn sẽ không biết chiều rộng, chiều cao hoặc số kênh của nó. Tại sao bạn không base64 mã hóa các tập tin đầu vào thay vì Mat? Ngoài ra, nếu bạn muốn gửi hình ảnh trên một ổ cắm, bạn không thực sự cần phải mã hóa base64, bạn chỉ có thể gửi nó như là và giảm chi phí. – Ove
@Ove đầu kia trên ổ cắm có thể là kiến trúc hoặc nền tảng khác nhau và sẽ không sử dụng C++. Tôi đã hy vọng tôi sẽ tránh những vấn đề nhất định bằng cách serialising với base64, nhưng tôi mở cho bất kỳ đề xuất. Vì vậy, bạn nghĩ rằng nó chỉ tốt hơn để serialise hình ảnh thay vì cv :: Mat? Vấn đề là, có thể không có bất kỳ hình ảnh nào, nhưng một hình ảnh được chụp bằng máy ảnh. Ngoài ra, socket đang sử dụng giao thức HTTP, vì vậy tôi đang đăng văn bản JSON. –