ROS/OpenCV/Flask - How to stream? - opencv

I'm trying to create a web stream interface of a camera that is connected to ROS.
A node publishes photo of the camera every 2 seconds to this topic: webcam/image_raw
image_message = bridge.cv2_to_imgmsg(frame_empty, encoding="bgr8")
pub_image_raw.publish(image_message)
And the other node subscribes to it and renders it on a web page via Flask.
#!/usr/bin/env python
import rospy
import threading
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
from flask import Flask, render_template, redirect, Response
app = Flask(__name__)
bridge = CvBridge()
cv_image = 0
def callback(data):
global cv_image
try:
cv_image = bridge.imgmsg_to_cv2(data, "bgr8")
#cv2.imshow("Image window", cv_image)
except CvBridgeError as e:
print(e)
threading.Thread(target=lambda: rospy.init_node('test_node5', disable_signals=True)).start()
image_sub = rospy.Subscriber("webcam/image_raw", Image, callback)
def gen():
global cv_image
while True:
#success, image = video.read()
ret, jpeg = cv2.imencode('.jpg', cv_image)
frame = jpeg.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
#app.route('/')
def video_feed():
return Response(gen(),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
# from og server
app.run(host='0.0.0.0', port=5000, debug=True)
Until now it's kinda working but there is a lot of random errors.
Is there a way to improve this code?
Thank!

Related

12200 - Schema validation warning twilio

Hi team i need to fix the 12200 - Schema validation warning twilio.
everything is working but i dont receive the whatsapp respond back .
enter image description here
here is the app.py code:
from helper.openai_api import text_complition
from helper.twilio_api import send_message
from twilio.twiml.messaging_response import MessagingResponse
from flask import Flask, request
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
#app.route('/')
def home():
return 'All is well...'
#app.route('/twilio/receiveMessage', methods=['POST'])
def receiveMessage():
try:
message = request.form['Body']
sender_id = request.form['From']
# Placeholder code
result = {}
result['status'] = 1
result['response'] = "Hi, I'm CODAI, I have received your message."
send_message(sender_id, result['response'])
except:
pass
return 'OK', 200
here is the openai.py code:
import os
import openai
from dotenv import load_dotenv
from twilio.twiml.messaging_response import MessagingResponse
load_dotenv()
openai.api_key = os.getenv('OPENAI_API_KEY')
def text_complition(prompt: str) -> dict:
'''
Call Openai API for text completion
Parameters:
- prompt: user query (str)
Returns:
- dict
'''
try:
response = openai.Completion.create(
model='text-davinci-003',
prompt=f'Human: {prompt}\nAI: ',
temperature=0.9,
max_tokens=150,
top_p=1,
frequency_penalty=0,
presence_penalty=0.6,
stop=['Human:', 'AI:']
)
return {
'status': 1,
'response': response['choices'][0]['text']
}
except:
return {
'status': 0,
'response': ''
}
here is the twilio.py code:
import os
from twilio.twiml.messaging_response import MessagingResponse
from twilio.rest import Client
from dotenv import load_dotenv
load_dotenv()
account_sid = os.getenv('TWILIO_ACCOUNT_SID')
auth_token = os.getenv('TWILIO_AUTH_TOKEN')
client = Client(account_sid, auth_token)
def send_message(to: str, message: str) -> None:
'''
Send message through Twilio's WhatsApp API.
Parameters:
- to(str): recipient's phone number in the format of "whatsapp:+[country code][phone number]"
- message(str): text message to send
Returns:
- None
'''
_ = client.messages.create(
from_=os.getenv('FROM'),
body=message,
to="whatsapp:" + to
)
i need help to fix the error 12200 - Schema validation warning twilio

How to send result of function from Django Server to React Native App?

I am study React Native and Django Development and I create an app which recognize a text from image. I realized POST method from React Native to Django Server but I don't understand how to send the result of recognition back to React.
How I can resolve this problem?
Django Server:
views.py:
from .serializers import PostSerializer
from .models import Ocr
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework import status
# Create your views here.
from django.http.response import JsonResponse
# Create your views here.
# import pytesseract to convert text in image to string
import pytesseract
# import summarize to summarize the ocred text
from .forms import ImageUpload
import os
# import Image from PIL to read image
from PIL import Image
from django.conf import settings
# Create your views here.
class PostView(APIView):
parser_classes = (MultiPartParser, FormParser)
def get(self, request, *args, **kwargs):
posts = Ocr.objects.all()
serializer = PostSerializer(posts, many=True)
print(serializer.data)
return Response(serializer.data)
def post(self, request, *args, **kwargs):
posts_serializer = PostSerializer(data=request.data)
if posts_serializer.is_valid():
text = ""
message = ""
posts_serializer.save()
try:
posts_serializer.save()
image = request.FILES['image']
image = image.name
path = settings.MEDIA_ROOT
pathz = path + "/images/" + image
text = pytesseract.image_to_string(Image.open(pathz), lang='rus+eng')
os.remove(pathz)
except Exception:
message = "check your filename and ensure it doesn't have any space or check if it has any text"
context = {
'text': text,
'message': message
}
print(context)
return Response(posts_serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(posts_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
React-Native:
CameraScreen.js:
const postToServer = (img) => {
const formData = new FormData();
formData.append('image', {
uri: img.uri,
type: 'image/jpeg',
name: 'test.jpg',
})
formData.append('title', 'title');
fetch('http://192.168.0.149:8000/api/textocr/', {
method: 'POST',
body: formData,
// If you add this, upload won't work
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
}
});
}

How to send and receive image as part of http form-data using requests and flask

I would like to make an http POST request, and include an image as part of the multipart/form-data. I'd like to avoid encoding this image as base64, and just send it as a binary blob, which I know that http can handle.
Here is my code on the client side:
from __future__ import print_function
import requests
import json
import cv2
def post_encoded_image(url, headers):
img = open("cyrus.jpg", 'rb').read()
payload = {'image': img, 'identity': 'cyrus'}
r = requests.post(url + "encoded-image", data=payload)
print(r)
url = "http://localhost:8080/"
content_type = 'multipart/form-data'
headers = {'content-type': content_type}
post_encoded_image(url, headers)
On the server side, my code looks like this:
from flask import Flask, request
import flask
import tfsdk
import numpy as np
from colorama import Fore
from colorama import Style
import os
import cv2
#app.route('/encoded-image', methods=['POST'])
def test():
image = request.form.get("image")
nparr = np.fromstring(image, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
print(type(img))
return "success"
if __name__ == '__main__':
app.run()
When I make the request, the server prints the type of img as NoneType, meaning the call to imdecode didn't work, meaning something strange is going on the server side with the encoded image.
What is the proper way to do this?
Edit
I was able to achieve the desired functionality by doing the following:
client:
from __future__ import print_function
import requests
import json
import cv2
def post_encoded_image(url, headers):
img = open("cyrus.jpg", 'rb').read()
file = {'image': img}
data = {'identity': 'cyrus'}
r = requests.post(url + "encoded-image", data=data, files=file)
print(r)
url = "http://localhost:8080/"
content_type = 'multipart/form-data'
headers = {'content-type': content_type}
post_encoded_image(url, headers)
Server:
#app.route('/encoded-image', methods=['POST'])
def test():
ID = request.form.get("identity")
image = request.files['image'].read()
nparr = np.fromstring(image, np.uint8)
Is this the proper way of doing it?
I was able to achieve the desired functionality as follows:
Client:
from __future__ import print_function
import requests
import json
import cv2
def post_encoded_image(url, headers):
img = open("cyrus.jpg", 'rb').read()
file = {'image': img}
data = {'identity': 'cyrus'}
r = requests.post(url + "encoded-image", data=data, files=file)
print(r)
url = "http://localhost:8080/"
content_type = 'multipart/form-data'
headers = {'content-type': content_type}
post_encoded_image(url, headers)
Server:
#app.route('/encoded-image', methods=['POST'])
def test():
ID = request.form.get("identity")
image = request.files['image'].read()
nparr = np.fromstring(image, np.uint8)

widgetexceptionerror i am trying to build a simple app using python kivy and this is the error which i am getting

I am trying to build a app using kivy and I am getting a widget expression error
raise WidgetException('Cannot add %r, it already has a parent %r'
kivy.uix.widget.WidgetException: Cannot add <kivy.uix.button.Button object at 0x0000026C4F999E40>, it already has a parent <main.SpartanGrid object at 0x0000026C4F1480B0>
this is my code
import turtle
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
wn = turtle.Screen()
wn.setup(height=1.0,width=1.0)
wn.bgcolor('black')
turtle.hideturtle()
usr = turtle.textinput("what user wish to", "please tell weather you want to access or
write to the file")
usr.lower()
if usr == 'access':
with open("C:\\Users\\Badri\\Documents\\New folder\\pyproject.txt", 'r') as pr:
cont = pr.read()
turtle.color('red')
turtle.write(cont, align='center', font=('caliber', 25, 'normal'))
elif usr == 'write':
class SpartanGrid(GridLayout):
def __init__(self,**kwargs):
super(SpartanGrid,self).__init__()
self.cols=3
self.add_widget(Label(text="person Name:"))
self.s_name=TextInput()
self.add_widget(self.s_name)
self.add_widget(Label(text="person ph.no"))
self.s_no = TextInput()
self.add_widget(self.s_no)
self.press = Button(text="submit")
self.add_widget(self.press)
self.press.bind(on_press=self.submit)
self.add_widget(self.press)
def submit(self,instance):
print("successful")
class SpartanApp(App):
def build(self):
return SpartanGrid()
if __name__ == "__main__":
SpartanApp().run()
else:
turtle.write("the input is not valid",align='center',font=('caliber',25,'normal'))
turtle.bye()
turtle.done()

Python-socketio: How to emit message regulary from server to client?

I want to send a message from server to client at 1 second intervals,
writing the string 'send clock' to console before the message is sent.
However, client does not receive "clock" message.
I have got the echo message is working fine, so it's not a connection issue.
How can I send a message at 1 second intervals?
Server code(python):
import threading
import time
import socketio
import eventlet
socket = socketio.Server(async_mode='eventlet')
app = socketio.WSGIApp(socket)
#socket.on('echo')
def echo(sid, message):
socket.emit('echo', message)
def worker1():
eventlet.wsgi.server(eventlet.listen(('', 5030)), app)
def worker2():
while(1):
print("send clock")
socket.emit('clock', '1 sec')
time.sleep(1)
def main():
t1 = threading.Thread(target=worker1)
t2 = threading.Thread(target=worker2)
t1.start()
t2.start()
if __name__ == '__main__':
main()
Client code(nodejs):
const io = require("socket.io-client");
socket = io("http://xxx.xxx.xxx.xxx:5030", {
transports: ["websocket"],
});
socket.emit("echo", "test");
socket.on("echo", (data) => {
console.log(data);
});
socket.on("clock", (data) => {
console.log("receive clock");
});
My server side environment:
python: 3.7.3
python-socketio: 4.5.1
eventlet: 0.25.1
Thank you for reading it until the very end. <3
You can't combine threads or the sleep() function with eventlet, you should use greenlet based equivalents instead. The easiest way to do this is to start your background tasks with the socket.start_background_task() helper function, and sleep with socket.sleep(). I'm writing this by memory so there might be small mistakes, but your application could do something like the following:
import socketio
import eventlet
socket = socketio.Server(async_mode='eventlet')
app = socketio.WSGIApp(socket)
#socket.on('echo')
def echo(sid, message):
socket.emit('echo', message)
def worker1():
eventlet.wsgi.server(eventlet.listen(('', 5030)), app)
def worker2():
while(1):
print("send clock")
socket.emit('clock', '1 sec')
socket.sleep(1)
def main():
socket.start_background_task(worker2)
worker1()
if __name__ == '__main__':
main()

Resources