繁体   English   中英

使用 Python 中的 Sockets 将图像从客户端发送到服务器

[英]Sending an Image from Client to Server using Sockets in Python

我想通过套接字从我的移动应用程序将捕获的图像发送到桌面服务器。 我目前实现了一个服务器/客户端应用程序。 我的问题是,目前移动应用程序是每次捕获后发送帧的服务器。 然后,作为客户端的桌面没有时间连接到作为移动应用程序的服务器并接收图像,因为套接字随即关闭。

我想要做的是将桌面端设置为接收图像的服务器,而不是发送并保持套接字打开,因此每次从移动应用程序作为客户端发送帧时,服务器都会读取并显示它。

这是我目前的尝试,将移动应用程序作为发送图像的服务器:

Java class:

private final OnClickListener mOnClickListener = new OnClickListener() {
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.save_button:
                    setValue(UVCCamera.CTRL_ZOOM_ABS, 0x80ff);
                    Toast.makeText(getApplicationContext(), "保存成功", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.button_camera:
                    if (!Check.isFastClick()) {
                        return;
                    }
                    if (mCameraHandler != null) {
                        if (mCameraHandler.isOpened()) {
                            if (checkPermissionWriteExternalStorage()) {
                                Python py = Python.getInstance();
                                Bitmap bitmap = Bitmap.createBitmap(mImageView .getWidth(), mImageView .getHeight(), Bitmap.Config.ARGB_8888);
                                imageString = getStringImage(bitmap);
                                PyObject pyo = py.getModule("script");
                                PyObject obj = pyo.callAttr("__main__", imageString);
                                mCameraHandler.captureStill(MediaMuxerWrapper.getCaptureFile(Environment.DIRECTORY_DCIM, ".png").toString());

                            }
                        }
                    }
                    break;
      }
}

移动应用中的服务器:

import numpy as np
import cv2
from PIL import Image
import base64
import io
import socket
import pickle
import struct
import imutils

def main(data):

    server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    host_name  = socket.gethostname()
    host_ip = socket.gethostbyname(host_name)
    port = 9999
    socket_address = (host_ip, port)
    server_socket.bind(socket_address)
    server_socket.listen(5)
    while True:
        client_socket, addr = server_socket.accept()
        if client_socket:
            decoded_data = base64.b64decode(data)
            frame_decoded = np.fromstring(decoded_data, np.uint8)
            frame = cv2.imdecode(frame_decoded , cv2.IMREAD_UNCHANGED)
            // The image captured is initially received as a string of bytes
            a = pickle.dumps(frame)
            message = struct.pack("Q",len(a))+a
            client_socket.sendall(message)

当前在桌面的客户端代码:

import socket,cv2, pickle,struct

client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_ip = '192.168.0.12' 
port = 9999
client_socket.connect((host_ip,port))
data = b""
payload_size = struct.calcsize("Q")
while True:
    while len(data) < payload_size:
        packet = client_socket.recv(4*1024) 
        if not packet: break
        data+=packet
    packed_msg_size = data[:payload_size]
    data = data[payload_size:]
    msg_size = struct.unpack("Q",packed_msg_size)[0]
    
    while len(data) < msg_size:
        data += client_socket.recv(4*1024)
    frame_data = data[:msg_size]
    data  = data[msg_size:]
    frame = pickle.loads(frame_data)
    cv2.imshow("Image Captured",frame)
    key = cv2.waitKey(1) & 0xFF
    if key  == ord('q'):
        break
client_socket.close()

 

基本上,我想从我目前的方法中改变谁在发送和谁在接收。 我想从移动应用程序作为客户端发送图像并在桌面作为服务器接收,我尝试四处搜索,但大多数示例显示如何从服务器发送图像。 但是,我需要在服务器端打开套接字,因此每次捕获都会立即接收到图像。

考虑这样的架构。 每次有来自客户端的新连接时,服务器 class 都会创建一个新的RequestHandler 在这里,我只是将套接字存储在一个全局列表中,然后进行读取。 我不希望有任何数据,所以读取会阻塞,但如果连接断开,读取将失败,我们可以返回。 当有新数据时,我们只需扫描等待的 sockets 列表并将数据发送给所有这些列表。

import socketserver

open_connections = []

def newFrame(data):
    # If there are no open connections, there's nothing to do.
    if not open_connections:
        return

    decoded_data = base64.b64decode(data)
    frame_decoded = np.fromstring(decoded_data, np.uint8)
    frame = cv2.imdecode(frame_decoded , cv2.IMREAD_UNCHANGED)
    # The image captured is initially received as a string of bytes
    a = pickle.dumps(frame)
    message = struct.pack("Q",len(a))+a

    for sock in open_connections:
        sock.sendall(message)

class RequestHandler(socketserver.BaseRequestHandler):
    # Called for each new connection.
    def handle(self):
        open_connections.append( self.request )
        # We don't ever expect data, but if this returns then the 
        # connection has been lost.
        self.request.read(10)
        open_connections.remove( sock )

if __name__ == '__main__':
    print( "Listening on 9999..." )
    socketserver.TCPServer.allow_reuse_address = True
    tcpserver = socketserver.ThreadingTCPServer(('localhost', 9999), RequestHandler)
    tcpserver.serve_forever()

我设法设置了一个将图像发送到服务器的工作客户端代码,而服务器等待发送图像。

发送图像的客户端:

import numpy as np
import cv2
from PIL import Image
import base64
import io
import socket
import pickle
import struct
import io

    def main(data):
        decoded_data = base64.b64decode(data)
        np_data = np.fromstring(decoded_data, np.uint8)
        img = cv2.imdecode(np_data, cv2.IMREAD_UNCHANGED)
    
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client_socket.connect(('192.168.0.14', 9999))
        connection = client_socket.makefile('wb')
    
    
        result, frame = cv2.imencode('.png', img)
    
        data = pickle.dumps(frame, 0)
    
        size = len(data)
        client_socket.sendall(struct.pack(">L", size) + data)

服务器收到一张图片:

import socket
import sys
import cv2
import pickle
import numpy as np
import struct ## new

HOST='192.168.0.14'
PORT=9999

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print('Socket created')

s.bind((HOST,PORT))
print('Socket bind complete')
s.listen(10)
print('Socket now listening')

conn,addr=s.accept()

data = b""
payload_size = struct.calcsize(">L")
print("payload_size: {}".format(payload_size))
while True:
    while len(data) < payload_size:
        print("Recv: {}".format(len(data)))
        data += conn.recv(4096)

    print("Done Recv: {}".format(len(data)))
    packed_msg_size = data[:payload_size]
    data = data[payload_size:]
    msg_size = struct.unpack(">L", packed_msg_size)[0]
    print("msg_size: {}".format(msg_size))
    while len(data) < msg_size:
        data += conn.recv(4096)
    frame_data = data[:msg_size]
    data = data[msg_size:]

    frame=pickle.loads(frame_data, fix_imports=True, encoding="bytes")
    frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
    filename = '/home/server/Desktop/frames_savedsaved/Image.jpg'
    cv2.imwrite(filename, frame)
    cv2.imshow('ImageWindow',frame)
    cv2.waitKey(1)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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