Skip to content

Commit

Permalink
✨ ⚗️ #1 Could able to stream webcam with monkey patching and threads
Browse files Browse the repository at this point in the history
  • Loading branch information
Balaji-Ganesh committed Jun 14, 2023
1 parent d5870ef commit e3d5c68
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 40 deletions.
6 changes: 5 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Perform monkey patching.. to support asynchronous behaviour
import eventlet
eventlet.monkey_patch()

from flask import Flask
from flask_socketio import SocketIO
from .middleware.communication import esp32_comm, web_comm
Expand All @@ -13,7 +17,7 @@ def create_app():
from .web import web as main_blueprint # for displaying web-pages

# Initialize socketio
socketio.init_app(app=app, cors_allowed_origins="*")
socketio.init_app(app=app, cors_allowed_origins="*", async_mode="eventlet")
# , logger=True, engineio_logger=True) # to run websockets for this flask app. A new server runs for this.

# Register blueprints..
Expand Down
50 changes: 39 additions & 11 deletions app/middleware/communication/web_communicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
This file gets the processed output of the algorithm and sends it to the web-app.
"""
import asyncio
from multiprocessing import Process
from threading import Thread
# Event handlers for socketio

import cv2
import base64

def handle_connect(self, ):
print("[DEBUG] web: Client connected successfully")
Expand All @@ -22,31 +23,58 @@ def handle_ack(self, data):

def stream_cam(self):
# from .esp32_communicator import get_cam_feed
from . import esp32_comm
asyncio.get_event_loop().run_until_complete(esp32_comm.get_cam_feed())
# from . import esp32_comm
# asyncio.get_event_loop().run_until_complete(esp32_comm.get_cam_feed())
# Stream from webcam
# -- test: First, could able to stream the webcam or not? w/ a separate process or thread.
# With threading (after monkey patching), this way working.
cap = cv2.VideoCapture(0)
while (cap.isOpened()):
ret, img = cap.read()
if ret:
cv2.imshow("img", img)
img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)
frame = cv2.imencode('.jpg', img)[1].tobytes()
frame = base64.encodebytes(frame).decode("utf-8")
self.sock.emit('img_data', frame)
self.sock.sleep(0)
if cv2.waitKey(1) == 27:
break
else:
print("Can't stream ")
break
pass


def handle_stream(self, response):
# Get the camera streamer..
print("[DEBUG] web: (stream event) client sent: "+str(response))
print("[[[[[[[[[[[[[[[[[[[[[[[[[[[STREAMING BEGINS]]]]]]]]]]]]]]]]]]]]]]]]]]]")

print("[DEBUG] web: Creating proceses to begin streaming")
from . import web_comm
camThread = Thread(target=web_comm.stream_cam)
print("[DEBUG] web: about to start spawned process for streaming")
camThread.start()
print("[DEBUG] web: Started spawned process for streaming")
camThread.join()

# A test -- whether could able to stream without creating separate process/thread or not.
# Test result: This way (w/o any process or thread) is working
# cap = cv2.VideoCapture(0)
# while (cap.isOpened()):
# ret, img = cap.read()
# if ret:
# cv2.imshow("img", img)
# img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)
# frame = cv2.imencode('.jpg', img)[1].tobytes()
# frame = base64.encodebytes(frame).decode("utf-8")
# self.sock.emit('img_data', frame)
# self.sock.sleep(0)
# if cv2.waitKey(1) == 27:
# break
# else:
# print("Can't stream ")
# break
print("[DEBUG] web: Creating proceses to begin streaming")
from . import web_comm
camProcess = Process(target=web_comm.stream_cam)
print("[DEBUG] web: about to start spawned process for streaming")
camProcess.start()
print("[DEBUG] web: Started spawned process for streaming")
camProcess.join()

print("[DEBUG] web: Streaming ended")
21 changes: 0 additions & 21 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,28 +74,7 @@
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.min.js"></script> -->

<script type="text/javascript" charset="utf-8">
const socket = io.connect('http://127.0.0.1:5000'); // url of the python server

socket.on('connect', function(){
socket.emit('ack', {
msg: 'CONN_ESTABLISHED'
});
console.log('Connected to server')
});

socket.on('disconnect', function(){
console.log("Disconnecting with the server")
socket.emit('ack', {
msg: 'CONN_TERMINATED'
});
})

socket.on('json', (data)=>{
console.log('server replied: ', data)
})

</script>
{% block socketio_connection %}
{% endblock %}

Expand Down
30 changes: 24 additions & 6 deletions app/templates/manualMode.htm
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ <h1>Manual Mode</h1>
alt="camera feed"
id="cam_feed"
/> -->
<img src="" id="cam_img"/>
<img id="cam_img">
<div class="collision-avoidance-feed">
<form class="form-inline" action="" method="">
<div class="form-group">
Expand Down Expand Up @@ -175,18 +175,36 @@ <h1>Manual Mode</h1>

{% block socketio_connection %}
<script type="text/javascript" charset="utf-8">
// Connection is already setup with variable `socket` in `base.html`, which will be top of this in final rendering.
// here just using setting up those events, which are specific to the page
// FIXME: Currently this page doesn't need cam feed. Later move to that specific pages
const socket = io.connect('http://127.0.0.1:5000'); // url of the python server, later use namespace/room specific to mode

socket.on('connect', function(){
socket.emit('ack', {
msg: 'CONN_ESTABLISHED'
});
console.log('Connected to server')
});

socket.on('disconnect', function(){
console.log("Disconnecting with the server")
socket.emit('ack', {
msg: 'CONN_TERMINATED'
});
})

socket.on('json', (data)=>{
console.log('server replied: ', data)
})

if(confirm("Start streaming?") == true){
console.log('streaming begins...')
socket.emit('stream', {msg: 'start streaming'})
}
socket.on('img_data', function(msg){
console.log("Image received")
img_element = document.getElementById("cam_feed")
const img_element = document.getElementById("cam_img")
console.log(typeof(img_element))
console.log(img_element)
img_element.src="data:image/jpeg;base64,"+msg;
})

</script>
{% endblock %}
2 changes: 1 addition & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
print("[DEBUG] main: About to establish communications")
webapp = create_app()
web_comm.init_communication(socketio)
esp32_comm.init_communication(ip='192.168.0.165')
# esp32_comm.init_communication(ip='192.168.157.165')
# from app.middleware.communication.web_communicator import * # register event handlers
print("[DEBUG] main: Communications established")

Expand Down

0 comments on commit e3d5c68

Please sign in to comment.