Send live Video Over network through Python socket

Hello Guys,


Welcome Again To My Blog, Well Friends Today, I am going to share very interesting Solution To Transfer/Send Live Video From One Device To Another Device Through Network Using Python Socket Module.


In Simple Words, Today I am going to share my solution To Share Live Video Feedback from my raspberry Pi Machine To My Main Desktop Using Python Socket Module.

Some Pre-Requested Things,

1. Network Connection Between Client And Server machine.
2. Python
3. Numpy Python Module
4. Image Libraries Like (OpenCV for Desktop & picamera for Raspberry Pi) 


So, Let's Quickly Start With Some Basic information,

Q. What is Raspberry Pi?

Ans. According To Wikipedia "The Raspberry Pi is a series of small single-board computers developed in the United Kingdom by the Raspberry Pi Foundation to promote teaching of basic computer science in schools and in developing countries. The original model became far more popular than anticipated, selling outside its target market for uses such as robotics. It does not include peripherals (such as keyboards and mice) and cases. However, some accessories have been included in several official and unofficial bundles"



Q 2. Tell me About Numpy?


Ans. According To Wikipedia "NumPy is a library for the Python programming language, adding support for large, multi-dimensional arrays and matrices, along with a large collection of high-level mathematical functions to operate on these arrays"

In Simple Words, Numpy is a Python programming library, Written in C/C++ With Python Wrapper To Perform Big Mathematical Calculations With Lighting Speed. And One of the main feature of Numpy is, It comes with various type of automatic mathematical calculations function built In. So, You Can Say, It's Damn Good!


Q 3. OpenCV and PiCamera Module?

Ans. According To Wikipedia "OpenCV is a library of programming functions mainly aimed at real-time computer vision. Originally developed by Intel, it was later supported by Willow Garage then Itseez. The library is cross-platform and free for use under the open-source BSD license."

Basically, OpenCV is a Image Processing Library That Support Almost All Types Of Image Related Operations, Calculations, Transformations And Other Thing and PiCamera is a raspberry Pi Module To provide a Easy Access, To Use Raspberry Pi Camera.


How We Going to Do?

Well Friends, Read Below Line One By One and Try To Understand Every Single Word.

1. Capture Image From Raspberry Pi Camera.
2. Create A Socket Connection Network Connection Between Client And Server.
3. Create A Python Socket Network Connection Object To Send Data.
4. Convert PiCamera Image Into Numpy Array.
5. Create Python Provide, File Input/Output Manipulation Object Like io module.
6. Save Numpy Array Into io module object
7. Read Complete Binary Data From io object.
8. Find Out The Length Of Data, Send it Over Network Using Struct Module.
9. Also, Sent Those Numpy Save Binary Data Over Network.
10. Receive And Extract Length of Data.
11. Receive That Numpy Binary Data From Server Side
12. Again, Create io module object and Save Receive Data To That object.
13. Again, Use Numpy To Load Same Array by providing That io object as file.
14. Boom! Same Array Now Available At Server Side. Use OpenCv To Represent It.

Example Code [Client Side]

# Sent Image Continously
class ImageRail:
 def __init__(self, sock):
  self.sock = sock 
  self.mstream = self.sock.makefile(mode='wb') # Make File Handler
  self.fstream = io.BytesIO() # In-Memory Byte Storing Class
  self.initialise_setups()


 def initialise_setups(self):
  print '[*] Going To Start Streaming Live Images..'
  with pi_api.PiCamera() as cam:
   while True: # Use While For Continue Streaming
    self.fstream.seek(0)
    #print '[*] First Image Streamed.'
    img = cam.getimage()
    np.save(self.fstream, img)
    #self.fstream.seek(0)
    imgsize = self.fstream.tell() # image Size
    self.fstream.seek(0)
    self.mstream.write(struct.pack('I', imgsize))
    #print imgsize
    self.mstream.flush()
    #time.sleep(1)
    self.mstream.write(self.fstream.read(imgsize))
    self.mstream.flush()
    #print '[*] Image Sent'
  return

Example Code [Server Side]

# Server Side Class To Receive Image As np array From Network
class DStream:
 '''
 DStream :
  function to receive live image data from connect socket and 
   convert it to cv2.imread object.

 '''
 # initialise function
 def __init__(self):
  self.sock = socket.socket()
  self.connection()
  self.createFileBuffers()

 # file buffer handling variables
 def createFileBuffers(self): 
  self.fstream = io.BytesIO()
  self.mstream = self.sock.makefile('rb')
  return

 # get image from socket
 def getimage(self):
  self.fstream.seek(0)
  imgsize = struct.unpack('I', self.mstream.read(4))[0]
  self.fstream.write(self.mstream.read(imgsize))
  self.fstream.seek(0)
  return np.load(self.fstream)


 # establish socket connection
 def connection(self):
  while True:
   try:
    print '[*] Trying To Connect...'
    self.sock.connect((STREAM_VIDEO_INPUT_IP, STREAM_VIDEO_INPUT_PORT))
    break
   except socket.error, E:
    print ' [-] Socket Not Connecting. ', E
    print ' [-] Trying IP : {} PORt : {}'.format(STREAM_VIDEO_INPUT_IP, STREAM_VIDEO_INPUT_PORT)
    time.sleep(3)
  return

 def __enter__(self, *args, **kwargs):
  return self

 def close(self):
  return self.sock.close()

 def __exit__(self, *args, **kwargs):
  return self.close()


I Think Both Above Example Codes are Self-Explainable.

Now, Let Me Show You complete Code To Make The Process Of Sending Live Cam Image From Raspberry To Computer Automatically and Continously.

Complete Code For Client Side



#!/usr/bin/python
#
#
# =++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#       ____     _    __     ____                                __     _             ____       
#      / __ )   (_)  / /_   / __/  ____    _____  ___    _____  / /_   (_)   ____    / __/  ____ 
#     / __  |  / /  / __/  / /_   / __ \  / ___/ / _ \  / ___/ / __/  / /   / __ \  / /_   / __ \
#    / /_/ /  / /  / /_   / __/  / /_/ / / /    /  __/ (__  ) / /_   / /   / / / / / __/  / /_/ /
#   /_____/  /_/   \__/  /_/     \____/ /_/     \___/ /____/  \__/  /_/   /_/ /_/ /_/     \____/ 
#                                                                                              
# =++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                                     
#
#                                                                          Suraj Singh Bisht
#                                                                          surajsinghbisht054@gmail.com
#
# 
#
#           This Script Is A Part Of RC-AIA Framework.
#           Created For Educational And Practise purpose Only.
#   Please Don't Remove Author Initials.
#
#

__author__      = "Suraj Singh Bisht"
__description__ = "Self Driving Phase One"
__version__     = "Beta"
__date__     = "OCT, 2018"
__email__     = "surajsinghbisht054@gmail.com"


# import modules
import socket
import pi_api
import time
import struct
from config import *
import io 
import numpy as np 

# Sent Image Continously
class ImageRail:
 def __init__(self, sock):
  self.sock = sock 
  self.mstream = self.sock.makefile(mode='wb') # Make File Handler
  self.fstream = io.BytesIO() # In-Memory Byte Storing Class
  self.initialise_setups()


 def initialise_setups(self):
  print '[*] Going To Start Streaming Live Images..'
  with pi_api.PiCamera() as cam:
   while True: # Use While For Continue Streaming
    self.fstream.seek(0)
    #print '[*] First Image Streamed.'
    img = cam.getimage()
    np.save(self.fstream, img)
    #self.fstream.seek(0)
    imgsize = self.fstream.tell() # image Size
    self.fstream.seek(0)
    self.mstream.write(struct.pack('I', imgsize))
    #print imgsize
    self.mstream.flush()
    #time.sleep(1)
    self.mstream.write(self.fstream.read(imgsize))
    self.mstream.flush()
    #print '[*] Image Sent'
  return




class Streamer:
 def __init__(self, ip, port, listen):
  self.ip = ip
  self.port = port
  self.listen = listen
  self.initialize_setups()

 def __enter__(self):
  return self

 def __exit__(self, *args, **kwargs):
  return self.close()


 def start(self):
  # Use While 
  if True:
   # Receive Connection
   print '[*] Waiting For Connection......'
   (clientsocket, address) = self.sock.accept()
   # Not Using Any Multi-Thread, Because Only One Core System Needed..
   print '[*] Receive Connection : ', address
   # Image Rail Activated
   ImageRail(clientsocket)

  return

 def close(self):
  print '[*] Socket Close'
  self.sock.close()
  return

 def initialize_setups(self):
  # create Socket
  self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  # bind socket
  self.sock.bind((self.ip, self.port))
  # listen
  self.sock.listen(self.listen)

  try:
   # Start Server
   self.start()
  except Exception as E:
   print '[-] An Error Caught :- ', E
   self.close()
  return


# main function
def main():
 with Streamer(STREAM_VIDEO_INPUT_IP, STREAM_VIDEO_INPUT_PORT, 5) as obj:
  pass
 return


# main trigger function
if __name__=='__main__':
 main()


Complete Code for Server Side


#!/usr/bin/python
#
#
# =++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#       ____     _    __     ____                                __     _             ____       
#      / __ )   (_)  / /_   / __/  ____    _____  ___    _____  / /_   (_)   ____    / __/  ____ 
#     / __  |  / /  / __/  / /_   / __ \  / ___/ / _ \  / ___/ / __/  / /   / __ \  / /_   / __ \
#    / /_/ /  / /  / /_   / __/  / /_/ / / /    /  __/ (__  ) / /_   / /   / / / / / __/  / /_/ /
#   /_____/  /_/   \__/  /_/     \____/ /_/     \___/ /____/  \__/  /_/   /_/ /_/ /_/     \____/ 
#                                                                                              
# =++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                                     
#
#                                                                          Suraj Singh Bisht
#                                                                          surajsinghbisht054@gmail.com
#
# 
#
#           This Script Is A Part Of RC-AIA Framework.
#           Created For Educational And Practise purpose Only.
#   Please Don't Remove Author Initials.
#
#

__author__      = "Suraj Singh Bisht"
__description__ = "Self Driving Phase One"
__version__     = "Beta"
__date__     = "OCT, 2018"
__email__     = "surajsinghbisht054@gmail.com"


# import modules
import socket
import pi_api
import cv2
import time
import struct
from config import *
import io 
import numpy as np 
from utili import imshow



# Server Side Class To Receive Image As np array From Network
class DStream:
 '''
 DStream :
  function to receive live image data from connect socket and 
   convert it to cv2.imread object.

 '''
 # initialise function
 def __init__(self):
  self.sock = socket.socket()
  self.connection()
  self.createFileBuffers()

 # file buffer handling variables
 def createFileBuffers(self): 
  self.fstream = io.BytesIO()
  self.mstream = self.sock.makefile('rb')
  return

 # get image from socket
 def getimage(self):
  self.fstream.seek(0)
  imgsize = struct.unpack('I', self.mstream.read(4))[0]
  self.fstream.write(self.mstream.read(imgsize))
  self.fstream.seek(0)
  return np.load(self.fstream)


 # establish socket connection
 def connection(self):
  while True:
   try:
    print '[*] Trying To Connect...'
    self.sock.connect((STREAM_VIDEO_INPUT_IP, STREAM_VIDEO_INPUT_PORT))
    break
   except socket.error, E:
    print ' [-] Socket Not Connecting. ', E
    print ' [-] Trying IP : {} PORt : {}'.format(STREAM_VIDEO_INPUT_IP, STREAM_VIDEO_INPUT_PORT)
    time.sleep(3)
  return

 def __enter__(self, *args, **kwargs):
  return self

 def close(self):
  return self.sock.close()

 def __exit__(self, *args, **kwargs):
  return self.close()



# main function
def main():
 with DStream() as obj:
  while True:
   try:
    NAME = 'PREVIEW'
    img = obj.getimage()
    if imshow(NAME, img):
     break
   except Exception as e:
    print e

 return

if __name__ == '__main__':
 main()

I Hope, You friends learnt something New.

Have A Nice Day!

Share this

Related Posts

Previous
Next Post »