如何不经过文件,把char*格式的jpeg图转为opencv::Mat ?

重点是怎么从char*格式的图片数据获取高度和宽度? 一直都是先把图片存在硬盘上再去用imread载入Mat;现在需要节省时间,请问怎么可以把二进制数…
关注者
5
被浏览
9,399

4 个回答

错了别怪我,我是看到问题后瞎试试的,或许有更好的办法

#include "D:/OpenCV-2.4.6/build/include/opencv2/core/core.hpp"
#include "D:/OpenCV-2.4.6/build/include/opencv2/highgui/highgui.hpp"
#ifndef NDEBUG
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/lib/opencv_core246d.lib" )
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/lib/opencv_highgui246d.lib" )
#else
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/staticlib/opencv_core246.lib" )
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/staticlib/opencv_highgui246.lib" )
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/staticlib/IlmImf.lib" )
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/staticlib/libjpeg.lib" )
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/staticlib/libpng.lib" )
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/staticlib/libtiff.lib" )
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/staticlib/libjasper.lib" )
    #pragma comment( lib, "D:/OpenCV-2.4.6/build/x86/vc9/staticlib/zlib.lib" )
    #pragma comment( lib, "User32.lib" )
#endif
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
using namespace cv;
int main( void )
    ifstream infile( ".\\a.bmp", ios::binary );
    if( !infile )
        return 1;
    std::vector<char> data( (std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>() );
    Mat test = imdecode( data, CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR );
    imwrite( ".\\b.bmp", test );

python客户端发射

_, imgEncode = cv2.imencode(".jpg", img, [cv2.IMWRITE_JPEG_QUALITY, self._jpgQuality])
data = np.array(imgEncode).tostring()
dataLength = "{0:0{width}}".format(len(data), width=10).encode()
self.sock.send(dataLength)
self.sock.send(data)

完整python

from copy import deepcopy
import json
import cv2
import socket
import logging
import time
import numpy as np
import threading
logger = logging.getLogger(__name__)
class ClientSend(threading.Thread):
    def __init__(self, address: str, port: int, idx: int, jpgQuality=15) -> None:
        threading.Thread.__init__(self)
        self._socketAddress = (address, port)
        self._idx = idx
        self._jpgQuality = jpgQuality
        self._data = None
    def _init_socket(self):
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.connect()
        except socket.error as msg:
            logger.warning("init socket failed(cannot access server):\n\t{}".format(msg))
        except AttributeError as msg:
            logger.warning("init socket failed:\n\t{}".format(msg))
    def send_img(self, img: np.ndarray):
        timeStamp = "{}".format(int(time.time() * 1000))
        dataType = "1"
        _, imgEncode = cv2.imencode(".jpg", img, [cv2.IMWRITE_JPEG_QUALITY, self._jpgQuality])
        data = "{}{}{}".format(self._idx, timeStamp, dataType).encode()
        data += np.array(imgEncode).tostring()
        self._data = deepcopy(data)
    def send_dict(self, result: dict, timeStamp: float):
        if timeStamp is None:
            timeStamp = time.time()
        timeStamp = "{}".format(int(timeStamp * 1000))
        dataType = "2"
        data = "{}{}{}".format(self._idx, timeStamp, dataType).encode()
        data += json.dumps(result, ensure_ascii=True).encode()
        self._data = deepcopy(data)
    def run(self):
        while True:
            if self._data is None:
                time.sleep(0.01)
                continue
            data = deepcopy(self._data)
            dataLength = "{0:0{width}}".format(len(data), width=10).encode()
            try:
                self._init_socket()
                self.sock.send(dataLength)
                self.sock.send(data)
            except socket.error as msg:
                logger.warning("socket send failed(server inner error):\n\t{}".format(msg))
            except AttributeError as msg:
                logger.warning("socket send failed:\n\t{}".format(msg))

C++服务器端接收

            namespace asio = boost::asio;  
            uchar* buf = new uchar[100000];
            std::size_t length = 0;
            std::size_t readlen = 0;
            socket_->read_some(asio::buffer(buf, 10));
            for (int i = 0; i < 10; i++) {
                length *= 10;
                length += buf[i] - 48;
            for(;;) {
                readlen += socket_->read_some(
                    asio::buffer(&buf[readlen], 32768)
                if (readlen >= length) { break; }