• 基于TCP协议与Python中Socket模块的人群分布数据传输与远程CNN识别模型部署


    目录
    基于 TCP 协议与 Python 中 Socket 模块的人群分布数据传输与远程 CNN 识别模型部署 1

    1. 概述 2
      1.1 问题提出 2
      1.2 程序总体设计 3
      1.3 最终成果简述 3
      1.4 报告结构 3
    2. 基本概念与原理 4
      2.1 TCP 4
      2.1.1 TCP 原理概述 4
      2.1.2 发展历史与应用 4
      2.1.3 运作方式 5
      2.1.4 可靠传输 7
      2.1.5 流量控制 10
      2.1.6 拥塞控制 11
      2.1.7 报文段格式 11
      2.2 Python Socket 11
      2.1.1 概述 12
      2.1.2 Socket 类型 12
      2.1.3 Socket 函数 12
      2.1.4 Socket 程序的整体一般结构 14
    3. 程序实现 15
      3.1 客户端Python 程序client.py 15
      3.1.1 程序框图 15
      3.1.2 详细实现步骤与部分关键代码 16
      3.2 服务端Python 程序server.py 18
      3.3 socket_send_recv.py 文件 21
    4. 问题排查与解决方法 23
      4.1 出现的问题 23
      4.2 问题排查与解决 26
      4.2.1 假设一与分析 26
      4.2.2 假设二与分析 26

    开启多线程服务器,一次连接一个线程 29

    1. 结果展示 31
      5.1 项目成果 31
      5.2 利用WireShark 抓包分析 32
    2. 总结与心得 34

    1.2 程序总体设计
    运行在本地端的 client.py 文件能够本地的图片或视频流上传到服务器;
    运行在服务器端的 server.py 文件能够通过 CNN 计算出密度图再回传至本地;其中,server.py 函数调用的 socket_send_recv.py 文件中含有专门用于处理传输相关的函数。

    1.3 最终成果简述
    最终成果的演示视频包括 caffe_predict.mp4 和 caffe_predict_camera.mp4 文件,可在 res_video 文件夹中找到查看。

    1.4 报告结构
    本报告包括六大部分,分别为概述、基本原理与概念、程序具体实现原理、遇到的问题与解决方法、结果验证与分析,以及最后的总结心得。第一部分即为此部分,包括问题的提出背景、程序的总体设计、最终成果的简要概述以及本报告的结构概述。第二部分为本项目设计的基本概念与原理,本文转载自http://www.biyezuopin.vip/onews.asp?id=16741包括 TCP 和 Python 中 Socket 应用相关内容。第三部分分文件详细解释程序的设计、实现与功能。第四部分设计程序设计与应用等过程中碰到的问题与解决方法。第五部分为本项目的结果验证与分析,包括使用 Wireshark 进行抓包验证等讨论。第六部分为组员在完成本次项目之后的感想与收获。

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    """
    @author: Xiaobo Yang
    @contact: hal_42@zju.edu.cn
    @software: PyCharm
    @file: client.py
    @time: 2019/5/18 8:23
    @desc:
    """
    
    import socket
    import cv2
    import numpy as np
    import logging
    from socket_send_recv import *
    from data_preprocession import MinMaxNormalize
    import re
    import os
    import datetime
    import glob
    
    from typing import Union
    
    
    logging.basicConfig(level=logging.DEBUG)
    
    '''
    @description: Establish TCP Conection To the server
    @param addr: Server Address
    @param port: Server Process Port
    @return: sock(connection to the server)
    '''
    def InitClient(addr: str, port: int) :
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 阻塞模式
        sock.setblocking(True)
        # sock.setsockopt(socket.SOL_SOCKET, socket.TCP_MAXSEG, 1)
        try:
            # 连接服务器
            sock.connect((addr, port))
            # Debug
            logging.info("Client's Peer Name"+str(sock.getpeername()))
            logging.info("Client's Name"+str(sock.getsockname()))
        except Exception as err:
            print(err)
            print("Can't connect to " + addr + ":" + str(port))
            sock.close()
            return None
        else:
            print("Client has connected to " + addr + ":" + str(port))
            return sock
    
    def SendStream(addr: str, port: int,src: Union[int, str]):
        sock = InitClient(addr, port)
        if not sock:
            raise RuntimeError("Failed to Establish Socket Connect")
    
        # 处理图片(可以不看)
        if isinstance(src, str) and (None != re.search('\.jpg', src) or None != re.search('\.png', src)):
            frame = cv2.imread(src, 1)
            if not isinstance(frame, np.ndarray):
                raise RuntimeError("No such Img at " + src)
            frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
            frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
            send_img(sock, frame)
    
            cv2.imshow('Client Cam', frame)
    
            data_len = recv_data_len(sock)
            predict_density = recv_img(sock, data_len, is_density=True)
    
            # debug
            print(predict_density)
    
            density_count = np.sum(predict_density)
            print("Current Count=" + str(density_count))
            show_density = MinMaxNormalize(predict_density, 0, 255).astype(np.uint8)
            show_density = cv2.applyColorMap(show_density, cv2.COLORMAP_JET)
            cv2.imshow('Client Received Density Map', show_density)
    
            file_path, img_name = os.path.split(src)
    
            if not os.path.isdir(os.path.join(file_path, 'test_result')):
                os.mkdir(os.path.join(file_path, 'test_result'))
            cv2.imwrite(os.path.join(file_path, 'test_result',img_name + "_test.jpg"), show_density)
    
            with open(os.path.join(file_path, 'test_result.txt'), 'a') as txt_f:
                now = datetime.datetime.now()
                txt_f.write("----------------------------------------------------------------" + '\n')
                txt_f.write("Testing Result Recorded at: " + now.strftime("%Y-%m-%d %H:%M:%S") + '\n')
                txt_f.write("Test img " + img_name + " has density count of:" + str(density_count) + '\n')
    
            if cv2.waitKey() == 27:
                pass
        else:
            # 处理视频
            capture = cv2.VideoCapture(src)
            while True:
                ret, frame = capture.read()
                if not ret:
                    break
    
                # 读取图像,转化为三通道灰度图后发送
                frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
                frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
                if 0 != send_img(sock, frame):
                    break
    
                cv2.namedWindow('Client Cam', 2)
                cv2.imshow('Client Cam', frame)
    
                # 读入带有数据头(指出密度图字节流的长度)的密度图(对付粘包问题)
                data_len = recv_data_len(sock)
                predict_density = recv_img(sock, data_len, is_density=True)
    
                # Debug
                print(predict_density)
    
                # 显示返回的密度图
                density_count = np.sum(predict_density)
                print("Current Count=" + str(density_count))
                show_density = MinMaxNormalize(predict_density, 0, 255).astype(np.uint8)
                cv2.namedWindow('Client Received Density Map', 2)
                show_density = cv2.applyColorMap(show_density, cv2.COLORMAP_JET)
                cv2.imshow('Client Received Density Map', show_density)
    
                if cv2.waitKey(100) == 27:
                    break
        sock.close()
        if src == 0:
            print("Connection End By User")
        else:
            print("Connection End for Video has been Send Out")
        cv2.destroyAllWindows()
    
    
    def TestDir(dir_path):
        for img_path in glob.glob(os.path.join(dir_path, '*.jpg')):
            SendStream('10.13.71.169', 12345, img_path)
        for img_path in glob.glob(os.path.join(dir_path, '*.png')):
            SendStream('10.13.71.169', 12345, img_path)
    
    
    if __name__ == '__main__':
        try:
            # 选择连接的服务器(可以是本地127.0.0.1),或者远程服务器
            # 可以上传图片,视频,或者0(笔记本摄像头),程序会自动识别算出做相应操作
            # 上传图片会给出图片人群计数结果保存为txt,视频则会实时显示原图像和密度图
    
            print("Start Sending Stream")
            # TestDir('..\\dataset\\My_Test')
            # SendStream('10.13.71.169', 12345, '..\\dataset\\My_Test\\tq.jpg')
            # SendStream('10.13.71.169', 12345, '..\\dataset\\My_Test\\yb1.mp4')
            # SendStream('10.13.71.169', 12345, '..\\dataset\\UCF_CC_50\\1.jpg')
            SendStream('10.13.71.169', 12345, 0)
            # SendStream('127.0.0.1', 12345, '..\\dataset\\My_Test\\hz_front1.jpg')
    
        except RuntimeError as err:
            logging.error(err)
        except Exception as err:
            logging.error("Unkown Error")
            logging.error(err)
        finally:
            print("Connection End")
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    PCB叠层设计
    【操作系统】进程间的通信——信号
    快速学习nginx反向代理
    基于Spark的数据清洗与转换
    vue el-button 封装及使用
    多维时序 | MATLAB实现SSA-CNN-BiGRU-Attention多变量时间序列预测(SE注意力机制)
    ES6 Generator 函数
    路由器ARP和ARP-proxy(华为)
    浪漫表白编程丨程序员的520表白代码 _ 程序员专属情人节表白网站
    SMART PLC星三角延时启动功能块(梯形图FC)
  • 原文地址:https://blog.csdn.net/newlw/article/details/126886066