欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

树莓派通过socket传输图片流-Python

程序员文章站 2022-04-24 11:13:27
...

树莓派通过socket传输图片流的Python实现

socket设置

客户端

这里将树莓派当做socket的客户端。代码如下:

"""set ip address"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.1.1', 8000))

服务器端

服务器端socket设置如下:

host = '0.0.0.0'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 定义socket类型
s.bind((host, port))  # 绑定需要监听的Ip和端口号,tuple格式
s.listen(5)

host设置空表示接受所有ip的访问。
listen()值表示等待的资源池为5。

具体实现

客户端

# -*- coding: UTF-8 -*-
import socket, os, struct
import time
from picamera import  PiCamera

"""set ip address"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.123.174', 8000))

"""set camera"""
camera = PiCamera()
camera.resolution = (1920,1080)
camera.framerate = 60

"""get opencv-classifier"""
face_cascade = cv2.CascadeClassifier('/home/pi/opencv-3.3.0/data/lbpcascades/lbpcascade_frontalface.xml' )

while True:
    camera.capture('/home/pi/class/0.jpg')
    filepath = '/home/pi/class/0.jpg'
    image = cv2.imread(filepath)
    gray = cv2.cvtColor( image, cv2.COLOR_BGR2GRAY )
    faces = face_cascade.detectMultiScale( gray )
    if os.path.isfile(filepath) and len(faces):
        fileinfo_size = struct.calcsize('128sl')  # 定义打包规则
        # 定义文件头信息,包含文件名和文件大小
        fhead = struct.pack('128sl', os.path.basename(filepath), os.stat(filepath).st_size)
        s.send(fhead)
        print('client filepath: ', os.path.basename(filepath), os.stat(filepath).st_size)

        # with open(filepath,'rb') as fo: 这样发送文件有问题,发送完成后还会发一些东西过去
        fo = open(filepath, 'rb')
        while True:
            filedata = fo.read(1024)
            if not filedata:
                break
            s.send(filedata)
        #time.sleep(0.5)
        fo.close()
        print('send over...')
    #time.sleep(0.5)
        # s.close()

服务器端实现

import socket, time, struct, os, threading
import sqlite3

host = '0.0.0.0'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 定义socket类型
s.bind((host, port))  # 绑定需要监听的Ip和端口号,tuple格式
s.listen(5)


def conn_thread(connection, address):
    con = sqlite3.connect('test.db')
    location = ''
    i = 0
    while True:
        try:
            connection.settimeout(600)
            fileinfo_size = struct.calcsize('128sl')
            buf = connection.recv(fileinfo_size)
            #print(buf)
            if buf:  # 如果不加这个if,第一个文件传输完成后会自动走到下一句
                filename, filesize = struct.unpack('128sl', buf)
                print("照片大小:"+str(filesize))
                if filesize< 0 or filesize > 2432075:
                    # da = connection.recv()
                    continue
                filename = filename.decode().strip('\00')
                # print(filename)
                #filename = os.path.join('e:\\', ('new_' + filename))
                print('file new name is %s, filesize is %s' % (filename, filesize))

                # 获取当前时间
                localtime = time.time()
                # 获取地址
                # if(address == ''):
                #     location = 'netlab_530'
                location = 'netlab_530'
                # 构造文件路径
                filepath = './face/netlab_530-'+ str(i) + '.jpg'
                # 将文件名加入链表
                cur = con.cursor()
                for t in [(location,localtime)]:
                    cur.execute("INSERT INTO image (location,localtime) \
                              VALUES (?,?)",t)
                con.commit()
                file = open(filepath,'wb')
                # file = open('./face/'+filename, 'wb')
                print('stat receiving...filesize:' + str(filesize))
                recvd_size = 0  # 定义接收了的文件大小
                while recvd_size != filesize:
                    if filesize - recvd_size >= 1024:
                        rdata = connection.recv(1024)
                        recvd_size += len(rdata)
                    elif filesize - recvd_size <1024 and filesize - recvd_size > 0:
                        print(filesize - recvd_size)
                        rdata = connection.recv(filesize - recvd_size)
                        recvd_size += len(rdata)
                    file.write(rdata)
                file.close()
                print('receive done')
                # connection.close()
            i += 1
        except socket.timeout:
            connection.close()
            con.close()



def main():
    while True:
        print("开始接收图片")
        connection, address = s.accept()
        print('Connected by ', address)
        thread = threading.Thread(target=conn_thread, args=(connection, address))  # 使用threading也可以
        thread.start()
        # threading.start_new_thread(conn_thread, (connection, address))

    s.close()


if __name__ == '__main__':
    main()

出现问题

在实现中会出现一开始传输正常但是后面会出现问题,debug了很久才发现是服务器端接收的时候对图片尺寸的计算有些逻辑错误造成的。