目录
基于 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")

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

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐