I have the following code that I've been struggling to get images from. There's a topic "CompressedImage" that has jpeg images from a camera in my robot. Below is my attempt. Terminal just gives me the versions from print and exits out.
#!/usr/bin/env python
import cv2
import numpy as np
from timeit import default_timer as timer
from std_msgs.msg import Float64
from sensor_msgs.msg import Image, CompressedImage
from cv_bridge import CvBridge, CvBridgeError
import rospy
import sys
print(sys.version)
print(cv2.__version__)
height = 480
width = 640
global_frame = np.zeros((height,width,3), np.uint8)
def camera_callback(data):
bridge = CvBridge()
try:
global_frame = bridge.compressed_imgmsg_to_cv2(data)
except CvBridgeError as e:
print(e)
height, width, channels = global_frame.shape
# print(height)
cv2.imshow("Original", global_frame)
def lane_pose_publisher():
# Set the node name
rospy.init_node('lane_pose_publisher', anonymous=True)
rospy.Subscriber('/camera/image_raw/compressed', CompressedImage, camera_callback, queue_size = 1)
# set rate
rate = rospy.Rate(1000) # 1000hz
if __name__ == '__main__':
try:
lane_pose_publisher()
except rospy.ROSInterruptException:
pass
This is because you are not spinning ROS. Check out the corresponding ROS tutorial to create a subscriber where
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
is called to ensure ROS can do his job (calling callbacks, ...).
So you should replace your lines
# set rate
rate = rospy.Rate(1000) # 1000hz
with the spinning ones.
Also you should add
cv2.waitKey(1)
after calling
cv2.imshow("Original", global_frame)
to ensure the image gets displayed.
Related
I need to know how much this particular line of code loads my cpu when whole program is executed:
cap.set(cv.CAP_PROP_POS_FRAMES,random_frame)
This line is part of a certain program. But I'm only interested in how this particular line loads the cpu. I don't know exactly how to measure it.
To be more precised, this is my full code:
import cv2 as cv
import random
cap = cv.VideoCapture('file_name.avi')
random_frame = random.randint(1,99999)
cap.set(cv.CAP_PROP_POS_FRAMES,random_frame)
ret, frame = cap.read()
cv.imshow("random_frame",frame)
while cap.isOpened():
if cv.waitKey(1) == ord('q'):
break
cap.release()
cv.destroyAllWindows()
Windows 7 operating system
import multiprocessing as mp
import psutil
import random
import cv2 as cv
import random
cap = cv.VideoCapture ('file_name.avi')
random_frame = random.randint (1, 99999)
def monitorFunction():
cap.set (cv.CAP_PROP_POS_FRAMES,random_frame)
def monitor (target):
worker_process = mp.Process(target=target)
worker_process.start()
p = psutil.Process(worker_process.pid)
# log cpu usage of `worker_process` every 10 ms
cpu_percents = []
while worker_process.is_alive():
cpu_percents.append(p.cpu_percent())
time.sleep(0.01)
worker_process.join()
return cpu_percents
cpu_percents = monitor(target=monitorFunction)
print (cpu_percents)
This should work.
Recently, I want to show tello stream with image detection. My first thought is to save model’s output to my local with save() method, and show it by cv2.imshow() method. It works but the stream with objects detection will have a delay about 4~5 second.
My code:
from threading import Thread
from djitellopy import Tello
import cv2, math, time
import torch
import os
import numpy as np
import asyncio
import imutils
from PIL import Image
path = r'C:\yolov5-master'
model = torch.hub.load(path, 'yolov5s',source='local', pretrained=True)
tello = Tello()
tello.connect()
tello.streamon()
frame_read = tello.get_frame_read()
class VideoStreamWidget(object):
def __init__(self, src=0):
# Start the thread to read frames from the video stream
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
def update(self):
# Read the next frame from the stream
global frame
while True:
self.frame = cv2.cvtColor(frame_read.frame,cv2.COLOR_RGB2BGR)
time.sleep(.01)
def show_frame(self):
# Display frames in main program
wee = model(self.frame)
arr = wee.datah().cpu().numpy()
img = Image.fromarray.fromarray(arr, 'RGB')
result = cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
cv2.imshow('frame', result)
key = cv2.waitKey(1)
if __name__ == '__main__':
video_stream_widget = VideoStreamWidget()
time.sleep(1)
while True:
try:
video_stream_widget.show_frame()
except AttributeError:
pass
I'm wondering what data type is the output of model( ).
And I tried:
wee = model(self.frame)
print( type( wee ) )
output:
<class 'models.common.Detections'>
How can I convert this kind of data to the thing fit cv2.imshow( ) method? Or is there any way to show a real-time stream with object detection without delay?
Appreciate.
When I run the below code. The camera opens and we can read the barcode. What I need is that the camera window remains at the side of my Tkinter GUI application rather than poping up. Here's the code
from imutils.video import VideoStream
from pyzbar import pyzbar
import argparse
import datetime
from datetime import datetime
import imutils
import time
import cv2
import winsound
frequency = 600 # Set Frequency To 2500 Hertz
duration = 800 # Set Duration To 1000 ms == 1 second
ap = argparse.ArgumentParser()
ap.add_argument("-o", "--output", type=str, default="barcodesData.csv",
help="path to output CSV file ")
args = vars(ap.parse_args())
print("Starting webcam")
vs = VideoStream(src=0).start()
time.sleep(2.0)
csvWrite = open(args["output"], "w")
found = set()
while True:
frameData = vs.read()
frameData = imutils.resize(frameData, width=600)
barcodes = pyzbar.decode(frameData)
for barcode in barcodes:
(x, y, width, height) = barcode.rect
cv2.rectangle(frameData, (x, y), (x + width, y + height), (0, 0, 255), 2)
barcodeData = barcode.data.decode("utf-8")
barcodeType = barcode.type
textData = "{} ({})".format(barcodeData, barcodeType)
cv2.putText(frameData, textData, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
if barcodeData not in found:
csvWrite.write("{},{}\n".format(datetime.today().strftime('%Y-%m-%d'),
barcodeData))
csvWrite.flush()
found.add(barcodeData)
winsound.Beep(frequency, duration)
cv2.imshow("Barcode Scanner", frameData)
key = cv2.waitKey(1) & 0xFF
if key == ord("e"):
break
# close the output CSV file do a bit of cleanup
print("\nWait while we calculate cost...")
csvWrite.close()
cv2.destroyAllWindows()
vs.stop()
time.sleep(1.0)
TO be specific. I'm making a billing software where I can read the barcodes of the products and make a bill. The camera separate screen is annoying so if the camera is on any side of the canvas all the time. It would be more quick.
I encoded the IDs of each product/item in my database in a QR code. When that particular item is being sought for, I used CV2 to detect and decode the QR code.
Here is the code:
def encode_qr():
import qrcode
import random as r
item_code = r.randint(00000000,99999999)
data = item_code
qrfile = "qr_image_name_for_specified_item.png"
# generate qrcode
qrimage = qrcode.make(data)
# save image
fl = qrimage.save(qrfile)
print("Done generating qrcode")
def decode_qr():
import cv2
filename="qr_image_name_for_specified_item.png"
# alternatively webcam cv2.VideoCapture(0)
# read image
image = cv2.imread(filename)
# initialize qrcode detector
detector = cv2.QRCodeDetector()
# detect and decode
info, v_array, binary_qrcode=detector.detectAndDecode(image)
# if null?
if v_array is None:
print("No qrcode detected or probably some technical issues occurred")
else:
print("QRCODE data")
print(info)
# below i am working with the import sqlite3 as sql3
sqldb = sql3.connect("your_database.db")
cur = sqldb.cursor()
cur.execute("select * from table where ID=?, (info,))
rows = cur.fetchall()
for r in rows:
print(r) # this will loop all the item details with the itemcode
print(r[1]) # a specific detail with the item_code
Hi I have just started with holoviews and I am trying to prepare a small streaming video app using holoviews, opencv. I have very limited experience with tornado and async programming.
from holoviews.streams import Pipe, Buffer
from tornado.ioloop import IOLoop
from tornado import gen
import cv2
#gen.coroutine
def f():
pipe = Pipe(data=[])
#print(pipe)
vd = cv2.VideoCapture("TestVideo.mp4")
width = int(vd.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(vd.get(cv2.CAP_PROP_FRAME_HEIGHT))
frames = int(vd.get(cv2.CAP_PROP_FRAME_COUNT))
print("Hello")
for i in range(frames):
ret, frame = vd.read()
#print(i)
try:
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
gen.sleep(10000000000)
pipe.send(rgb[:])
#print(str(i)+'x')
except:
#print(str(i)+'Error')
print("Error at Frame:"+str(i))
pass
vd.release()
cv2.destroyAllWindows()
IOLoop.current().add_callback(f)
hv.DynamicMap(hv.RGB, streams=[pipe])
I am not getting running/streaming updates. I just get a single image with last frame. Can somebody help me with figuring out my mistake here
Apart from the comment about gen.sleep taking the time in seconds, you need want to write your callback as a generator. Something like this should do it:
from holoviews.streams import Pipe, Buffer
from tornado.ioloop import IOLoop
from tornado import gen
import cv2
#gen.coroutine
def f():
vd = cv2.VideoCapture("TestVideo.mp4")
width = int(vd.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(vd.get(cv2.CAP_PROP_FRAME_HEIGHT))
frames = int(vd.get(cv2.CAP_PROP_FRAME_COUNT))
while frames > 0:
ret, frame = vd.read()
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
pipe.send(rgb)
frames -= 1
yield gen.sleep(1)
vd.release()
cv2.destroyAllWindows()
pipe = Pipe(data=[])
IOLoop.current().add_callback(f)
hv.DynamicMap(hv.RGB, streams=[pipe])
Thank you #philippjfr
In the end I got something workable using streamz python library . However this approach works. This is my working solution based on above approach.
```
import numpy as np
import pandas as pd
import holoviews as hv
hv.extension('bokeh', 'matplotlib')
from holoviews.streams import Pipe, Buffer
from tornado.ioloop import IOLoop
from tornado import gen
import cv2
#gen.coroutine
def f():
width = int(vd.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(vd.get(cv2.CAP_PROP_FRAME_HEIGHT))
frames = int(vd.get(cv2.CAP_PROP_FRAME_COUNT))
while frames > 0:
ret, frame = vd.read()
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frames -= 1
yield pipe.send(rgb)
vd.release()
cv2.destroyAllWindows()
vd = cv2.VideoCapture("TestVideo.mp4")
ret, frame0 = vd.read()
rgb = cv2.cvtColor(frame0, cv2.COLOR_BGR2RGBA)
pipe = Pipe(data=rgb)
#pipe = Pipe(data=[])
IOLoop.current().add_callback(f)
hv.DynamicMap(hv.RGB, streams=[pipe])
```
I am a beginner with multiprocessing in Python. I am developing a multiprocessing script for OpenCV, since my computer does not succeed in real-time processing of OpenCV frames.
I aim at loading and processing frames in the main process, and displaying them using a child process. My problem is that I do not understand how to build the display loop from the queued frames. Can someone please help?
My code:
#!/usr/bin/env python
from multiprocessing import Process, Queue
from Queue import Empty
from PIL import Image
import cv2
import cv2.cv as cv
import numpy as np
def image_display(taskqueue):
cv2.namedWindow ('image_display', cv2.CV_WINDOW_AUTOSIZE)
while True:
if taskqueue.get()==None:
continue
else:
image = taskqueue.get()
im = Image.fromstring(image['mode'], image['size'], image['pixels'])
num_im = np.asarray(im)
cv2.imshow ('image_display', num_im)
if __name__ == '__main__':
taskqueue = Queue()
vidFile = cv2.VideoCapture('doppler.wmv')
p = Process(target=image_display, args=(taskqueue,))
p.start()
while True:
flag, image=vidFile.read()
if flag == 0:
break
im = Image.fromarray(image)
im_dict = {
'pixels': im.tostring(),
'size': im.size,
'mode': im.mode,
}
taskqueue.put(im_dict)
p.join()
cv.DestroyAllWindows()
EDIT
Thanks to the answers, I was able to find the problem. Below is a modified script in which I slowed my loops on purpose and added an outqueue for debugging. It appears that although the frames captured with vidFile.read() are indeed passed as numpy arrays through the queue and are then passed unmodified as argument to cv2.imshow(),cv2.imshow() refuses to display the image for an unknown reason. Any help to fix that issue would be immensly appreciated!
modified code:
#!/usr/bin/env python
from multiprocessing import Process, Queue
from Queue import Empty
import cv2
import cv2.cv as cv
import numpy as np
import time
def image_display(taskqueue, outqueue):
cv2.namedWindow ('image_display', cv2.CV_WINDOW_AUTOSIZE)
while True:
try:
outqueue.put('trying')
time.sleep(1)
image = taskqueue.get()
outqueue.put(image)
cv2.imshow('image_display', image)
except:
continue
if __name__ == '__main__':
taskqueue = Queue()
outqueue = Queue()
vidFile = cv2.VideoCapture('doppler.wmv')
p = Process(target=image_display, args=(taskqueue, outqueue))
p.start()
while True:
print outqueue.get()
flag, image=vidFile.read()
if flag == 0:
break
taskqueue.put(image)
time.sleep(0.010)
p.join()
cv.DestroyAllWindows()
This should work (explanation of changes below):
#!/usr/bin/env python
from multiprocessing import Process, Queue
from Queue import Empty
from PIL import Image
import cv2
import cv2.cv as cv
import numpy as np
def image_display(taskqueue):
cv2.namedWindow ('image_display', cv2.CV_WINDOW_AUTOSIZE)
while True:
image = taskqueue.get() # Added
if image is None: break # Added
cv2.imshow ('image_display', image) # Added
cv2.waitKey(10) # Added
continue # Added
if taskqueue.get()==None:
continue
else:
image = taskqueue.get()
im = Image.fromstring(image['mode'], image['size'], image['pixels'])
num_im = np.asarray(im)
cv2.imshow ('image_display', num_im)
if __name__ == '__main__':
taskqueue = Queue()
vidFile = cv2.VideoCapture('doppler.wmv')
p = Process(target=image_display, args=(taskqueue,))
p.start()
while True:
flag, image=vidFile.read()
taskqueue.put(image) # Added
import time # Added
time.sleep(0.010) # Added
continue # Added
if flag == 0:
break
im = Image.fromarray(image)
im_dict = {
'pixels': im.tostring(),
'size': im.size,
'mode': im.mode,
}
taskqueue.put(im_dict)
taskqueue.put(None)
p.join()
cv.DestroyAllWindows()
I tried to make minimal changes to your code by just adding lines (lines containing comments # Added):
1) Just put the image itself (the original NumPy array) on the queue.
2) Pause a little bit in the master process before reading another frame. You need this so as not to overrun the queue, because imshow() in the spawned process may take a bit longer since it's calling X. You might need to increase this value (in seconds) depending on your system.
3) Spawned process has to do the waitKey() after every imshow().
4) Master process puts the special None image on the queue when it's done.