I am working on Yolov3, OpenCV,python and Flask. Here, I explain the details of usage for each item.
Yolov3 - To detect and recognize object in video input
Opencv - To capture images of detected object in video input.
Flask - As a web server since it's support python language.
My objective
To develop application which able to captured the image of the object and update in the flask web directly or real-time
For your information, currently my system able to capture image and save in one folder which name as images by using OpenCv and python. you can refer the code below.
opencv and python code to capture image of object detected
for i in range(len(boxes)):
if i in indexes:
x,y,w,h = boxes[i]
label = str(LABELS[class_ids[i]])
confidence= confidences[i]
color = colors[class_ids[i]]
crop_img = image[y:y + h, x:x + w]
imagesPath = "images/file_%d.jpg"%self.d
cv2.imwrite(imagesPath, crop_img)
self.d+=1
cv2.rectangle(image,(x,y),(x+w,y+h),color,2)
cv2.putText(image,label+" "+str(round(confidence,2)),(x,y+30),font,1,(255,255,255),2)
When the images successfully save in images folder. I convert all the images in to base64 and return as json in flask. Here I attach the python code in flask.
Covert image to base64 and render in html templates
#app.route("/images")
def get_images():
directory = os.listdir('C:/Users/HP/Miniconda3/envs/count_vechicle/coding/images')
os.chdir('C:/Users/HP/Miniconda3/envs/count_vechicle/coding/images')
image_list= list()
for file in directory:
data = dict()
base = os.path.basename(file)
data["label"] = base
open_file = open(file,'rb')
image_read = open_file.read()
image_64_encode = base64.encodebytes(image_read)
data["data"] = image_64_encode.decode('ascii')
image_list.append(data)
final_data = {'files':image_list}
return render_template('images.html', final_data=final_data)
images.html
<!DOCTYPE html>
<html>
<head>
<!DOCTYPE html>
<html lang="en">
<head>
<title>yolo</title>
</head>
<body>
<h1 class="logo">Results</h1>
<ul>
{% for data in final_data.files %}
<li>{{data.label}}</li>
<img alt="embedded" src="data:image/jpg;base64,{{data.data}}"/>
{% endfor %}
</ul>
</body>
</html>
Problem and question
I have two major problem here.
1) When i run my application, my application captured the images welly. But it's automatically stop when image.html page is open to display the picture. Why it's happen and how to solve this?
2) If the application able to capture image even i open the image.html page. What should i do to update my web directly or real-time?
Here I attach the full code. Because I have been works for many weeks but still not found the solution. Hope someone can helps. Let's me know if u need more information
code
App.py
from flask import Flask, render_template, Response,jsonify
from camera import VideoCamera
import numpy as np
import os
import time
import detect as dt
from PIL import Image
import cv2
import base64
import json
from pprint import pprint
app = Flask(__name__)
def success_handle(output, status=200, mimetype='application/json'):
return Response(output, status=status, mimetype=mimetype)
#app.route("/images")
def get_images():
directory = os.listdir('C:/Users/HP/Miniconda3/envs/count_vechicle/coding/images')
os.chdir('C:/Users/HP/Miniconda3/envs/count_vechicle/coding/images')
flist = list()
for file in directory:
data = dict()
base = os.path.basename(file)
data["label"] = base
open_file = open(file,'rb')
image_read = open_file.read()
image_64_encode = base64.encodebytes(image_read)
data["data"] = image_64_encode.decode('ascii')
flist.append(data)
final_data = {'files':flist}
return render_template('images.html', final_data=final_data)
#app.route('/')
def index():
return render_template('index.html')
def gen(camera):
frame_id = 0
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
#app.route('/video_feed')
def video_feed():
return Response(gen(VideoCamera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
camera.py
import cv2
import time
import os
import numpy as np
font = cv2.FONT_HERSHEY_PLAIN
starting_time= time.time()
frame_id = 0
count = 0
d = 0
labelsPath = os.path.sep.join(["yolo-coco", "coco.names"])
weightsPath = os.path.sep.join(["yolo-coco", "yolov3.weights"])
configPath = os.path.sep.join(["yolo-coco", "yolov3.cfg"])
#imagesPath = 'C:/Users/HP/Miniconda3/envs/count_vechicle/coding/images/file_%d.jpg"%d'
labelsPath = os.path.sep.join(["yolo-coco", "coco.names"])
VideoPath = os.path.sep.join(["videos", "highway.mp4"])
LABELS = open(labelsPath).read().strip().split("\n")
net = cv2.dnn.readNet(configPath, weightsPath)
layer_names = net.getLayerNames()
outputlayers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
colors= np.random.uniform(0,255,size=(len(LABELS),3))
class VideoCamera(object):
def __init__(self):
# Using OpenCV to capture from device 0. If you have trouble capturing
# from a webcam, comment the line below out and use a video file
# instead.
self.video = cv2.VideoCapture(VideoPath)
self.frame_id = 0
self.d = 0
# If you decide to use video.mp4, you must have this file in the folder
# as the main.py.
# self.video = cv2.VideoCapture('video.mp4')
def __del__(self):
self.video.release()
def get_frame(self):
success, image = self.video.read()
# We are using Motion JPEG, but OpenCV defaults to capture raw images,
# so we must encode it into JPEG in order to correctly display the
# video stream.
self.frame_id+=1
#print(frame_id)
height,width,channels = image.shape
#print (frame.shape)
#detecting objects
blob = cv2.dnn.blobFromImage(image,0.00392,(320,320),(0,0,0),True,crop=False) #reduce 416 to 320
net.setInput(blob)
outs = net.forward(outputlayers)
#print(outs)
print(outs[1])
#Showing info on screen/ get confidence score of algorithm in detecting an object in blob
class_ids=[]
confidences=[]
boxes=[]
for out in outs:
#print(out)
for detection in out:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
print(confidence)
if confidence > 0.8:
#object detected
center_x= int(detection[0]*width)
center_y= int(detection[1]*height)
w = int(detection[2]*width)
h = int(detection[3]*height)
#cv2.circle(img,(center_x,center_y),10,(0,255,0),2)
#rectangle co-ordinaters
x=int(center_x - w/2)
y=int(center_y - h/2)
#cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
boxes.append([x,y,w,h]) #put all rectangle areas
confidences.append(float(confidence)) #how confidence was that object detected and show that percentage
class_ids.append(class_id) #name of the object tha was detected
indexes = cv2.dnn.NMSBoxes(boxes,confidences,0.4,0.6)
# result = open('C:/Users/HP/Miniconda3/envs/count_vechicle/coding/images/frame%04d.txt'%(count), 'w')
for i in range(len(boxes)):
if i in indexes:
x,y,w,h = boxes[i]
label = str(LABELS[class_ids[i]])
# cv2.imwrite(label, crop_img)
confidence= confidences[i]
color = colors[class_ids[i]]
crop_img = image[y:y + h, x:x + w]
imagesPath = "images/file_%d.jpg"%self.d
cv2.imwrite(imagesPath, crop_img)
self.d+=1
cv2.rectangle(image,(x,y),(x+w,y+h),color,2)
cv2.putText(image,label+" "+str(round(confidence,2)),(x,y+30),font,1,(255,255,255),2)
elapsed_time = time.time() - starting_time
fps=frame_id/elapsed_time
cv2.putText(image,"FPS:"+str(round(fps,2)),(10,50),font,2,(0,0,0),1)
# cv2.imshow("Image",image)
# key = cv2.waitKey(1) #wait 1ms the loop will start again and we will process the next frame
# if key == 27: #esc key stops the process
# break;
ret, jpeg = cv2.imencode('.jpg', image)
return jpeg.tobytes()
index.html
<html>
<head>
<title>Object Detection</title>
</head>
<body>
<h1>Video Streaming Demonstration</h1>
<img src="{{ url_for('video_feed') }}">
</body>
</html>
images.html
<!DOCTYPE html>
<html>
<head>
<!DOCTYPE html>
<html lang="en">
<head>
<title>yolo</title>
</head>
<body>
<h1 class="logo">Results</h1>
<ul>
{% for data in final_data.files %}
<li>{{data.label}}</li>
<img alt="embedded" src="data:image/jpg;base64,{{data.data}}"/>
{% endfor %}
</ul>
</body>
</html>
I'm currently using Apache Thrift for an API project.
I started with a little test project in order to understand how Thrift works. So, I would like to use a python server with a browser-based javascript Client.
I've read the documentation entirely, but I still have an issue I can't resolve :( :
Server output :
127.0.0.1 - - [04/Dec/2018 17:04:34] code 501, message Unsupported method ('OPTIONS')
127.0.0.1 - - [04/Dec/2018 17:04:34] "OPTIONS / HTTP/1.1" 501 -
test.thrift
enum Modulation
{
BPSK
QPSK
APSK16
APSK32
}
struct Coordinate {
1: i32 X,
2: i32 Y
}
struct Constellation {
1: string name,
2: i32 timestamp,
3: list<Coordinate> coordinates
}
service Dealer
{
Constellation getConstellation()
Modulation getModulation()
void setModulation(1: Modulation new_modulation)
i32 getTimestamp()
}
server.py
import glob
import sys
sys.path.append('gen-py')
from TApp import Dealer
from TApp.ttypes import *
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import *
from thrift.server import TServer, THttpServer
import time
class DealerHandler:
def __init__(self):
self.modulation = Modulation.BPSK
def getConstellation(self):
c = Constellation()
c.name = "Test"
c.timestamp = self.getTimestamp()
c.coordinates = []
return c
def getModulation(self):
return self.modulation
def setModulation(self, new_modulation):
self.modulation = new_modulation
def getTimestamp(self):
return int(str(time.time()).split('.')[0])
if __name__ == '__main__':
handler = DealerHandler()
processor = Dealer.Processor(handler)
port = 9090
host = '127.0.0.1'
# HTTP SERVER
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TJSONProtocol.TJSONProtocolFactory()
# List of all protocols : https://thrift-tutorial.readthedocs.io/en/latest/thrift-stack.html
#server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
server = THttpServer.THttpServer(processor, (host, port), pfactory)
server.serve()
index.html
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
<div id="timestamp" style="margin:auto; width:70%; padding:15px; text-align:center; border:1px solid black;">
No Value
</div>
<br />
<button type="button" name="button" class="btn btn-info" style="width:100%" onclick="update_timestamp()">Start connection</button>
</body>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" charset="utf-8"></script>
<script src="thrift.js" charset="utf-8"></script>
<script src="test_types.js" charset="utf-8"></script>
<script src="Dealer.js" charset="utf-8"></script>
<script type="text/javascript">
function update_timestamp() {
var transport = new Thrift.TXHRTransport("http://localhost:9090");
var protocol = new Thrift.TJSONProtocol(transport);
var client = new DealerClient(protocol);
var val = client.getTimestamp();
document.getElementById("timestamp").innerHTML = val;
}
</script>
</html>
Just join to this community. I have python script that produce string in html :
from shelljob import proc
import flask
import os
import eventlet
eventlet.monkey_patch()
app = flask.Flask(__name__)
#app.route('/create')
def create():
g = proc.Group()
p = g.run("timeout 30s mycommand | grep -Eo 'https?://\S+'")
def read_process():
while g.is_pending():
lines = g.readlines()
for proc, line in lines:
yield "data:" + line + "\n\n"
return flask.Response( read_process(), mimetype= 'text/event-stream' )
#app.route('/')
def get_page():
return flask.send_file('page.html')
if __name__ == '__main__':
app.run(debug=True)
that code will produce something like :
This sample output with static result...
Please visit https://www.example.com/click?nonce=1a2b3c4d to bla bla bla.
This sample output with static result...
Please visit https://www.example.com/click?nonce=1a2b3c4d to bla bla bla.
How i can get url only like this one and only show first result :
https://www.example.com/click?nonce=1a2b3c4d
because if i type"timeout 30s mycommand | grep -Eo 'https?://\S+'" i can get exact url.
I can replace the text with javascript, but i'm still got list result instead 1 line. This my html "page.html"
<!DOCTYPE html>
<html>
<head>
<style type="text/css">.urldb{color: #ffffff;padding: 10px;background: red;text-decoration: none;}</style>
</head>
<body>
<div id="output"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery-linkify/2.1.4/linkify.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery-linkify/2.1.4/linkify-string.min.js"></script>
<script>
var source = new EventSource("/create");
var options = {className: 'urldb',target: {url: '_blank'}};
source.onmessage = function(event) {
document.getElementById("output").innerHTML += event.data.replace(/(\bhttps?:\/\/\S+)|[^]/g, '$1').linkify(options) + "<br/>";
if (event.data.indexOf('Welcome') > -1) {
$("#output").hide();
window.location.href = "https://example.com";
}
};
</script>
</body>
</html>
Using that script i got result like :
https://www.example.com/click?nonce=1a2b3c4d
https://www.example.com/click?nonce=1a2b3c4d
https://www.example.com/click?nonce=1a2b3c4d
Thanks and sorry if any wrong in my question.
Edit to add more alternative wrong in python or javascript and remove "e" to make clear.
You have maybe typo in the pattern. Change https?://e\S+ to https?://\S+ (remove e) and it works.
For output only fist match you can use -m1. For more informations see man page.
Is it possible to make reload the page when the data is updated?
import socket
import tornado.ioloop
import tornado.web
import tornado.gen
import tornado.ioloop
import tornado.iostream
import tornado.tcpserver
import os
import tornado.websocket
last_messages = dict()
class TcpClient(object):
client_id = 0
def __init__(self, stream):
super(TcpClient, self).__init__()
TcpClient.client_id += 1
self.id = 'Connection#%d' % TcpClient.client_id
self.stream = stream
self.stream.socket.setsockopt(
socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.stream.socket.setsockopt(
socket.IPPROTO_TCP, socket.SO_KEEPALIVE, 1)
self.stream.set_close_callback(self.on_disconnect)
#tornado.gen.coroutine
def on_disconnect(self):
self.log("disconnected")
yield []
#tornado.gen.coroutine
def dispatch_client(self):
try:
while True:
line = yield self.stream.read_until(b'\n')
text_line = line.decode('utf-8').strip()
last_messages[self.id] = text_line
# UPDATE GUI, webpage HERE
self.log('got |%s|' % text_line)
except tornado.iostream.StreamClosedError:
pass
#tornado.gen.coroutine
def on_connect(self):
raddr = 'closed'
try:
raddr = '%s:%d' % self.stream.socket.getpeername()
except Exception:
pass
self.log('new, %s' % raddr)
yield self.dispatch_client()
def log(self, msg, *args, **kwargs):
print('[%s] %s' % (self.id, msg.format(*args, **kwargs)))
class TcpServer(tornado.tcpserver.TCPServer):
#tornado.gen.coroutine
def handle_stream(self, stream, address):
connection = TcpClient(stream)
yield connection.on_connect()
class LastMessagesHandler(tornado.web.RequestHandler):
#tornado.web.asynchronous
def get(self):
self.render(
'template.html',
sources=last_messages
)
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def on_message(self, message):
print message
self.write(last_messages)
def main():
tcp = TcpServer()
tcp.listen(8008)
print('tcp://localhost:8008')
settings = dict(
template_path=os.path.join(os.path.dirname(__file__), 'templates'),
static_path=os.path.join(os.path.dirname(__file__), 'static'),
debug=True,
)
app = tornado.web.Application(
[
(r'/', LastMessagesHandler),
(r'/ws', WebSocketHandler)
],
**settings
)
app.listen(8009)
print('http://localhost:8009')
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
Here is the template.html
<html>
<head>
<title>TCP server</title>
</head>
<body>
<title>Tornado WebSockets</title>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
jQuery(function($){
if (!("WebSocket" in window)) {
alert("Your browser does not support web sockets");
}else{
setup();
}
function setup() {
var host = "ws://localhost:8008/ws";
var socket = new WebSocket(host);
// event handlers for websocket
if(socket){
socket.onopen = function(){
//alert("connection opened....");
}
socket.onmessage = function(msg){
showServerResponse(msg.data);
}
/*socket.onclose = function(){
//alert("connection closed....");
showServerResponse("The connection has been closed.");
}*/
}else{
console.log("invalid socket");
}
function showServerResponse(txt){
var p = document.createElement('p');
p.innerHTML = txt;
document.getElementById('output').appendChild(p);
}
}
});
</script>
<div>
<ul id="output">
{% for key, value in sources.iteritems() %}
<ul> {{key}} | {{value}} </ul>
{% end %}
</ul>
</div>
</body>
</html>
I need to update Client(webpage) whenever last_messages is changed (smth is removed form the dict, smth has been added to the dict). I can't do this using tornado.websocket. Could you please help? I need to update gui after reading line from the socket (you can find the comment in the code where i need to update the webpage: # UPDATE GUI, webpage HERE). So the socket can be still opened (we are continuing reading lines), but the gui must be updated. Is it possible to do it?
If you really want to reload the page then in your JavaScript you can initiate a call to window.location.reload().
However, this will close the WebSocket connection from the client side.
If you just wish to update the DOM (GUI), then listen to the incoming message on the client and update accordingly.
To observe and track data changes you can do it yourself in JavaScript, or with Object.observe if you're running only on modern Chrome, or with the polyfill, or use an existing tool, like Backbone.js.
Should you choose the latter, I can also recommend a tool to help you with working with WebSockets and Backbone.
Disclaimer: I'm the author of Backbone.WS.
I'm working on a Python package that uses Tornado to send data to the browser for visualization. In order to do this, I want the users to be able to write multiple arbitrary modules for the server to render together on a single page -- including each module's own JavaScript.
However, by default, the Tornado's UIModule class's embedded_javascript() method only appends JavaScript to <script>...</script> once per module class. I'm hoping there is a simple way to embed multiple pieces of JS, one for every UIModule (or another way to get the same effect).
Here's a minimal example of what I'm talking about:
import tornado.ioloop
import tornado.web
import tornado.template
class Element(tornado.web.UIModule):
'''
Module to add some custom JavaScript to the page.
'''
def render(self, element):
self.js_code = element.js_code
return ""
def embedded_javascript(self):
return self.js_code
class InterfaceElement(object):
'''
Object to store some custom JavaScript code.
'''
def __init__(self, js_code):
'''
Args:
js_code: Some JavaScript code in string form to add to the page.
'''
self.js_code = js_code
class MainPageHandler(tornado.web.RequestHandler):
def get(self):
elements = self.application.modules
self.render("uitest_template.html", app_name="Testing", elements=elements)
class ThisApp(tornado.web.Application):
def __init__(self, modules):
self.modules = modules
main_handler = (r'/', MainPageHandler)
#settings = {"ui_modules": {"Element": Element}}
settings = {"ui_modules": {"Element": Element},
"template_path": "ui_templates"}
super().__init__([main_handler], **settings)
# Create two objects with some custom JavaScript to render
module_1 = InterfaceElement("var a = 1;")
module_2 = InterfaceElement("var b = 2;")
app = ThisApp([module_1, module_2])
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()
And the template for uitest_template.html is just
<!DOCTYPE html>
<head>
<title> Hello World </title>
</head>
<body>
{% for element in elements %}
{%module Element(element) %}
{% end %}
</body>
The rendered page then includes a <script> tag in body that is:
<script type="text/javascript">
//<![CDATA[
var b = 2;
//]]>
</script>
And what I want is:
<script type="text/javascript">
//<![CDATA[
var a = 1;
var b = 2;
//]]>
</script>
Or something like it. Any ideas?
Added - my solution
Based on the answer below, here's how I ended up handling it:
import tornado.ioloop
import tornado.web
import tornado.template
class InterfaceElement(object):
include_js = [] # List of .js files to include
js_code = '' # JavaScript string to include
def __init__(self, include_js=[], js_code=''):
self.include_js = include_js
self.js_code = js_code
class MainPageHandler(tornado.web.RequestHandler):
def get(self):
self.render("modular_template.html",
includes=self.application.include_js,
scripts=self.application.js_code)
class ThisApp(tornado.web.Application):
def __init__(self, modules):
# Extract the relevant info from modules:
self.modules = modules
self.include_js = set()
self.js_code = []
for module in self.modules:
for include_file in module.include_js:
self.include_js.add(include_file)
if module.js_code != '':
self.js_code.append(module.js_code)
main_handler = (r'/', MainPageHandler)
settings = {"template_path": "ui_templates",
"static_path": "ui_templates"}
super().__init__([main_handler], **settings)
module_1 = InterfaceElement(js_code="var a = 1;")
module_2 = InterfaceElement(include_js=["test.js"], js_code="var b = 1;")
app = ThisApp([module_1, module_2])
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Which goes with the following template:
<!DOCTYPE html>
<head>
<title> Hello world </title>
</head>
<body>
<!-- Script includes go here -->
{% for file_name in includes %}
<script src="/static/{{ file_name }}" type="text/javascript"></script>
{% end %}
<script type="text/javascript">
// Actual script snippets go here.
{% for script in scripts %}
{% raw script %}
{% end %}
</script>
</body>
embedded_javascript and related methods are (effectively) class-level methods; they must return the same value for any instance of the class. (They're intended to be a kind of dependency-management system, so you can load a piece of javascript only on pages that include a module that needs it)
The only thing that is allowed to vary per instance is the output of render(), so to embed multiple pieces of javascript you should include the script tag in the result of your render() method.