python openCV 基于TCP的socket网络传输视频(三)

系统 2366 0

  在这个版本中,我实现了两个客户端,一个服务器的操作,其实有时候解决问题,就差这么一点,一点就通。我来说说我这个版本,一个客户端可以采集视频,另一个客户端可以观看视频,服务器可以建在本地,也可以搭建在云平台上,就是可以被外网访问。
  服务器的思路:采用多线程,采集视频一个客户端,观看视频一个客户端,其中有个要关注的点,就是有一个线程要加延时,不然的话观看视频会太卡。另外我这只是实现了,有需要注意的地方很多,代码还不完善,先开服务器,再开采集,最后开观看客户端,错了顺序就不好使了,等我把多线程旅顺了,再更新整理。主要是这个思路。

服务器

            
              
                #!/usr/bin/python
              
              
                # -*-coding:utf-8 -*-
              
              
                import
              
               socket

              
                import
              
               threading

              
                import
              
               cv2

              
                import
              
               numpy

              
                from
              
               time 
              
                import
              
               sleep



              
                def
              
              
                recv_all
              
              
                (
              
              sock
              
                ,
              
               count
              
                )
              
              
                :
              
              
    buf 
              
                =
              
              
                ''
              
              
                while
              
               count
              
                :
              
              
        newbuf 
              
                =
              
               sock
              
                .
              
              recv
              
                (
              
              count
              
                )
              
              
                if
              
              
                not
              
               newbuf
              
                :
              
              
                return
              
              
                None
              
              
        buf 
              
                +=
              
               newbuf
        count 
              
                -=
              
              
                len
              
              
                (
              
              newbuf
              
                )
              
              
                return
              
               buf



              
                # 线程锁
              
              
threadLock 
              
                =
              
               threading
              
                .
              
              Lock
              
                (
              
              
                )
              
              
                # 视频buf
              
              
                # videoDatastr = ''
              
              
                # 客户端套接字
              
              
conn_list 
              
                =
              
              
                [
              
              
                ]
              
              
                def
              
              
                robotVideoThread
              
              
                (
              
              sock
              
                )
              
              
                :
              
              
                global
              
               videoDatastr
    
              
                # 接受TCP链接并返回(conn, addr),其中conn是新的套接字对象,可以用来接收和发送数据,addr是链接客户端的地址。
              
              
    conn
              
                ,
              
               addr 
              
                =
              
               sock
              
                .
              
              accept
              
                (
              
              
                )
              
              
                print
              
              
                'robot Connected with'
              
              
                +
              
              
                ' '
              
              
                +
              
               addr
              
                [
              
              
                0
              
              
                ]
              
              
                +
              
              
                ':'
              
              
                +
              
              
                str
              
              
                (
              
              addr
              
                [
              
              
                1
              
              
                ]
              
              
                )
              
              
    conn_list
              
                .
              
              append
              
                (
              
              conn
              
                )
              
              
                while
              
              
                True
              
              
                :
              
              
        length 
              
                =
              
               recv_all
              
                (
              
              conn
              
                ,
              
              
                16
              
              
                )
              
              
                # 首先接收来自客户端发送的大小信息
              
              
                if
              
              
                len
              
              
                (
              
              length
              
                )
              
              
                ==
              
              
                16
              
              
                :
              
              
                # 若成功接收到大小信息,进一步再接收整张图片
              
              
                #threadLock.acquire()
              
              
            videoDatastr 
              
                =
              
               recv_all
              
                (
              
              conn
              
                ,
              
              
                int
              
              
                (
              
              length
              
                )
              
              
                )
              
              
                #threadLock.release()
              
              
                def
              
              
                userVideoThread
              
              
                (
              
              sock
              
                )
              
              
                :
              
              
                global
              
               videoDatastr
    
              
                # 接受TCP链接并返回(conn, addr),其中conn是新的套接字对象,可以用来接收和发送数据,addr是链接客户端的地址。
              
              
    conn
              
                ,
              
               addr 
              
                =
              
               sock
              
                .
              
              accept
              
                (
              
              
                )
              
              
                print
              
              
                'user Connected with'
              
              
                +
              
              
                ' '
              
              
                +
              
               addr
              
                [
              
              
                0
              
              
                ]
              
              
                +
              
              
                ':'
              
              
                +
              
              
                str
              
              
                (
              
              addr
              
                [
              
              
                1
              
              
                ]
              
              
                )
              
              
    conn_list
              
                .
              
              append
              
                (
              
              conn
              
                )
              
              
                while
              
              
                True
              
              
                :
              
              
                #threadLock.acquire()
              
              
        conn
              
                .
              
              send
              
                (
              
              
                str
              
              
                (
              
              
                len
              
              
                (
              
              videoDatastr
              
                )
              
              
                )
              
              
                .
              
              ljust
              
                (
              
              
                16
              
              
                )
              
              
                )
              
              
        conn
              
                .
              
              send
              
                (
              
              videoDatastr
              
                )
              
              
                #threadLock.release()
              
              
        sleep
              
                (
              
              
                0.1
              
              
                )
              
              
                if
              
               __name__ 
              
                ==
              
              
                '__main__'
              
              
                :
              
              

    s_robot 
              
                =
              
               socket
              
                .
              
              socket
              
                (
              
              socket
              
                .
              
              AF_INET
              
                ,
              
               socket
              
                .
              
              SOCK_STREAM
              
                )
              
              
    address 
              
                =
              
              
                (
              
              
                '10.0.0.30'
              
              
                ,
              
              
                8888
              
              
                )
              
              
    s_robot
              
                .
              
              bind
              
                (
              
              address
              
                )
              
              
    s_robot
              
                .
              
              listen
              
                (
              
              
                True
              
              
                )
              
              
                print
              
              
                'robot服务器初始化成功'
              
              

    s_user 
              
                =
              
               socket
              
                .
              
              socket
              
                (
              
              socket
              
                .
              
              AF_INET
              
                ,
              
               socket
              
                .
              
              SOCK_STREAM
              
                )
              
              
    address 
              
                =
              
              
                (
              
              
                '10.0.0.30'
              
              
                ,
              
              
                9999
              
              
                )
              
              
    s_user
              
                .
              
              bind
              
                (
              
              address
              
                )
              
              
    s_user
              
                .
              
              listen
              
                (
              
              
                True
              
              
                )
              
              
                print
              
              
                'user服务器初始化成功'
              
              

    threading
              
                .
              
              Thread
              
                (
              
              target
              
                =
              
              robotVideoThread
              
                ,
              
               args
              
                =
              
              
                (
              
              s_robot
              
                ,
              
              
                )
              
              
                )
              
              
                .
              
              start
              
                (
              
              
                )
              
              
    threading
              
                .
              
              Thread
              
                (
              
              target
              
                =
              
              userVideoThread
              
                ,
              
               args
              
                =
              
              
                (
              
              s_user
              
                ,
              
              
                )
              
              
                )
              
              
                .
              
              start
              
                (
              
              
                )
              
            
          

采集客户端

            
              
                #!/usr/bin/python
              
              
                # -*-coding:utf-8 -*-
              
              
                import
              
               socket

              
                import
              
               cv2

              
                import
              
               numpy

              
                from
              
               time 
              
                import
              
               sleep


              
                # socket.AF_INET 用于服务器与服务器之间的网络通信
              
              
                # socket.SOCK_STREAM 代表基于TCP的流式socket通信
              
              
sock 
              
                =
              
               socket
              
                .
              
              socket
              
                (
              
              socket
              
                .
              
              AF_INET
              
                ,
              
               socket
              
                .
              
              SOCK_STREAM
              
                )
              
              
                # 连接服务端
              
              
address_server 
              
                =
              
              
                (
              
              
                '10.0.0.30'
              
              
                ,
              
              
                8888
              
              
                )
              
              
sock
              
                .
              
              connect
              
                (
              
              address_server
              
                )
              
              
                # 从摄像头采集图像
              
              
                # 参数是0,表示打开笔记本的内置摄像头,参数是视频文件路径则打开视频
              
              
capture 
              
                =
              
               cv2
              
                .
              
              VideoCapture
              
                (
              
              
                0
              
              
                )
              
              
                # capture.read() 按帧读取视频
              
              
                # ret,frame 是capture.read()方法的返回值
              
              
                # 其中ret是布尔值,如果读取帧正确,返回True;如果文件读到末尾,返回False。
              
              
                # frame 就是每一帧图像,是个三维矩阵
              
              
ret
              
                ,
              
               frame 
              
                =
              
               capture
              
                .
              
              read
              
                (
              
              
                )
              
              
encode_param 
              
                =
              
              
                [
              
              
                int
              
              
                (
              
              cv2
              
                .
              
              IMWRITE_JPEG_QUALITY
              
                )
              
              
                ,
              
              
                50
              
              
                ]
              
              
                while
              
               ret
              
                :
              
              
                # 首先对图片进行编码,因为socket不支持直接发送图片
              
              
                # '.jpg'表示把当前图片frame按照jpg格式编码
              
              
                # result, img_encode = cv2.imencode('.jpg', frame)
              
              
                # img_encode = cv2.imencode('.jpg', frame, encode_param)[1]
              
              
    result
              
                ,
              
               img_encode 
              
                =
              
               cv2
              
                .
              
              imencode
              
                (
              
              
                '.jpg'
              
              
                ,
              
               frame
              
                )
              
              
                # data = numpy.array(img_encode)
              
              
                # stringData = data.tostring()
              
              
    stringData 
              
                =
              
               img_encode
              
                .
              
              tostring
              
                (
              
              
                )
              
              
                # 首先发送图片编码后的长度
              
              
    sock
              
                .
              
              send
              
                (
              
              
                str
              
              
                (
              
              
                len
              
              
                (
              
              stringData
              
                )
              
              
                )
              
              
                .
              
              ljust
              
                (
              
              
                16
              
              
                )
              
              
                )
              
              
                # 然后一个字节一个字节发送编码的内容
              
              
                # 如果是python对python那么可以一次性发送,如果发给c++的server则必须分开发因为编码里面有字符串结束标志位,c++会截断
              
              
                # for i in range(0, len(stringData)):
              
              
                #     sock.send(stringData[i])
              
              
    sock
              
                .
              
              send
              
                (
              
              stringData
              
                )
              
              
                # sleep(1)
              
              
    ret
              
                ,
              
               frame 
              
                =
              
               capture
              
                .
              
              read
              
                (
              
              
                )
              
              
    cv2
              
                .
              
              resize
              
                (
              
              frame
              
                ,
              
              
                (
              
              
                640
              
              
                ,
              
              
                480
              
              
                )
              
              
                )
              
              

sock
              
                .
              
              close
              
                (
              
              
                )
              
              
cv2
              
                .
              
              destroyAllWindows
              
                (
              
              
                )
              
            
          

观看客户端

            
              
                #!usr/bin/python
              
              
                # coding=utf-8
              
              
                import
              
               socket

              
                import
              
               cv2

              
                import
              
               numpy



              
                # 接受图片大小的信息
              
              
                def
              
              
                recv_size
              
              
                (
              
              sock
              
                ,
              
               count
              
                )
              
              
                :
              
              
    buf 
              
                =
              
              
                ''
              
              
                while
              
               count
              
                :
              
              
        newbuf 
              
                =
              
               sock
              
                .
              
              recv
              
                (
              
              count
              
                )
              
              
                if
              
              
                not
              
               newbuf
              
                :
              
              
                return
              
              
                None
              
              
        buf 
              
                +=
              
               newbuf
        count 
              
                -=
              
              
                len
              
              
                (
              
              newbuf
              
                )
              
              
                return
              
               buf



              
                # socket.AF_INET 用于服务器与服务器之间的网络通信
              
              
                # socket.SOCK_STREAM 代表基于TCP的流式socket通信
              
              
sock 
              
                =
              
               socket
              
                .
              
              socket
              
                (
              
              socket
              
                .
              
              AF_INET
              
                ,
              
               socket
              
                .
              
              SOCK_STREAM
              
                )
              
              
                # 连接服务端
              
              
address_server 
              
                =
              
              
                (
              
              
                '10.0.0.30'
              
              
                ,
              
              
                9999
              
              
                )
              
              
sock
              
                .
              
              connect
              
                (
              
              address_server
              
                )
              
              
                while
              
              
                True
              
              
                :
              
              
    length 
              
                =
              
               recv_size
              
                (
              
              sock
              
                ,
              
              
                16
              
              
                )
              
              
                # 首先接收来自客户端发送的大小信息
              
              
                if
              
              
                len
              
              
                (
              
              length
              
                )
              
              
                ==
              
              
                16
              
              
                :
              
              
                # 若成功接收到大小信息,进一步再接收整张图片
              
              
        stringData 
              
                =
              
               recv_size
              
                (
              
              sock
              
                ,
              
              
                int
              
              
                (
              
              length
              
                )
              
              
                )
              
              
        data 
              
                =
              
               numpy
              
                .
              
              fromstring
              
                (
              
              stringData
              
                ,
              
               dtype
              
                =
              
              
                'uint8'
              
              
                )
              
              
        decimg 
              
                =
              
               cv2
              
                .
              
              imdecode
              
                (
              
              data
              
                ,
              
              
                1
              
              
                )
              
              
                # 解码处理,返回mat图片
              
              
        img 
              
                =
              
               cv2
              
                .
              
              resize
              
                (
              
              decimg
              
                ,
              
              
                (
              
              
                640
              
              
                ,
              
              
                480
              
              
                )
              
              
                )
              
              
        cv2
              
                .
              
              imshow
              
                (
              
              
                'SERVER'
              
              
                ,
              
               img
              
                )
              
              
                if
              
               cv2
              
                .
              
              waitKey
              
                (
              
              
                1
              
              
                )
              
              
                ==
              
              
                27
              
              
                :
              
              
                break
              
              
                # print('Image recieved successfully!')
              
              



sock
              
                .
              
              close
              
                (
              
              
                )
              
              
cv2
              
                .
              
              destroyAllWindows
              
                (
              
              
                )
              
            
          

更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论