Reducing Lag in Pi Camera - python

I found a code that can scan a barcode using the Raspberry Pi camera V2.1.
It works as expected and can detect a barcode when I present it to the camera. But if I move the camera around a little, there is a lag in the video. I tried increasing the camera. framerate but that doesn't do anything. Neither does change the resolution. Even if I remove the dec() function, the video still looks laggy.
How can I improve the camera framerate so it does not lag?
Also the code opens up a window where I can see the video. For now it is useful for debugging, but I was wondering how I could stop the Pi from opening the video window later on?
from ftplib import FTP
from pyzbar.pyzbar import decode
import os, sys, cv2
import numpy as np
from picamera.array import PiRGBArray
from picamera import PiCamera
import imutils, time
detectedBarcode = False
def dec(frame):
global detectedBarcode
x=decode(frame)
for i in x:
detectedBarcode = True
(x, y, w, h) = i.rect
cv2.rectangle(frame,(x, y),(x + w, y + h),(0, 0, 255),2)
barcodeData = i.data.decode("utf-8")
barcodeType = i.type
print(barcodeData, type(barcodeData))
#sys.exit()
return(barcodeData,barcodeType,1)
return('','',0)
def cameraReader():
fourcc = cv2.VideoWriter_fourcc(*'X264')
camera=PiCamera()
camera.resolution=(1296,730)
camera.framerate = 30
rawCapture=PiRGBArray(camera)
cv2.namedWindow("QR Scanner",cv2.WINDOW_NORMAL)
global detectedBarcode
avg = None
for frame in camera.capture_continuous(rawCapture,format="bgr",use_video_port=False):
image=frame.array
cv2.line(image, (650, 0), (650, 1000), (0, 255,0), 2)
x,y,p=dec(image)
cv2.imshow("QR Scanner",image)
if cv2.waitKey(2) & 0xFF == ord('q'):
break
rawCapture.truncate(0)
#cap.release()
cv2.destroyAllWindows()
cameraReader()

Related

Why does my image taken with OpenCV appear smaller than that of libcamera?

I am currently working on a project which makes use of a Raspberry Pi and its Camera Module v2.1.
I need to scan some barcodes with the camera of which I am using the OpenCV and pyzbar libraries.
I am running into some trouble with the image that OpenCV is returning, example below:
Image returned from running libcamera-hello:
Image returned from running my script:
As you can see the images are very different, the OpenCV image is more zoomed in.
I've tried resizing the image and even changing the size of the frame but it doesn't seem to help, the image just gets stretched!
Does anyone have any ideas on why this might be happening?
My script for capturing the images is below:
import cv2
from pyzbar import pyzbar
from gpiozero import Button
from readBarcodeData import read_text
button = Button(25)
def read_barcodes(frame):
barcodes = pyzbar.decode(frame)
for barcode in barcodes:
x, y , w, h = barcode.rect
barcode_info = barcode.data.decode('utf-8')
cv2.rectangle(frame, (x, y),(x+w, y+h), (0, 255, 0), 2)
with open("barcode_result.txt", mode ='w') as file:
file.write(str(barcode_info).replace("'", ""))
return frame
def main():
while True:
if button.is_pressed:
camera = cv2.VideoCapture(0)
ret, frame = camera.read()
while ret:
ret, frame = camera.read()
frame = read_barcodes(frame)
cv2.imshow('Barcode Scanner', frame)
if cv2.waitKey(0) & 0xFF == 27:
break
break
camera.release()
cv2.destroyAllWindows()
read_text()
if __name__ == '__main__':
main()
EDIT:
I have also tried capturing an image using the following code:
import cv2
vid = cv2.VideoCapture(0)
while(True):
# Capture the video frame
ret, frame = vid.read()
# Display the resulting frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# After the loop release the cap object
vid.release()
# Destroy all the windows
cv2.destroyAllWindows()
But I still get a cropped image.
EDIT 2:
Returned properties from the video capture:
CV_CAP_PROP_FRAME_WIDTH: '640.0'
CV_CAP_PROP_FRAME_HEIGHT : '480.0'
[ WARN:0] global /tmp/pip-wheel-j62hpwu1/opencv-python_19cf39855c924932a2df50dd2b502cd2/opencv/modules/videoio/src/cap_v4l.cpp (1911) getProperty VIDEOIO(V4L2:/dev/video0): Unable to get camera FPS
CAP_PROP_FPS : '-1.0'
CAP_PROP_POS_MSEC : '911170.05'
CAP_PROP_FRAME_COUNT : '-1.0'
CAP_PROP_BRIGHTNESS : '-1.0'
CAP_PROP_CONTRAST : '-1.0'
CAP_PROP_SATURATION : '-1.0'
CAP_PROP_HUE : '-1.0'
CAP_PROP_GAIN : '-1.0'
CAP_PROP_CONVERT_RGB : '1.0'
I managed to "fix" this by using the PiCamera library to capture the image and then run it through cv2:
Code for reading in PiCamera image is below:
import cv2
from time import sleep
from pyzbar import pyzbar
from gpiozero import Button
from picamera.array import PiRGBArray
import picamera
from readBarcodeData import read_text
button = Button(25)
def read_barcodes(frame):
barcodes = pyzbar.decode(frame)
for barcode in barcodes:
x, y , w, h = barcode.rect
barcode_info = barcode.data.decode('utf-8')
cv2.rectangle(frame, (x, y),(x+w, y+h), (0, 255, 0), 2)
with open("barcode_result.txt", mode ='w') as file:
file.write(str(barcode_info).replace("'", ""))
return frame
def main():
while True:
if button.is_pressed:
with picamera.PiCamera() as camera:
rawCapture = PiRGBArray(camera)
#camera.resolution = (3280, 2464)
camera.start_preview()
#sleep(1)
camera.capture(rawCapture, format="bgr")
img = rawCapture.array
#camera = cv2.VideoCapture(0)
#ret, frame = camera.read()
ret = True
while ret:
#ret, frame = img
frame = read_barcodes(img)
#cv2.imshow('Barcode Scanner', frame)
#print(frame.shape)
#if cv2.waitKey(0) & 0xFF == 27:
#break
break
cv2.destroyAllWindows()
read_text()
if __name__ == '__main__':
main()
The image captured by PiCamera seems to return the full image with no cropping so works a treat.

how to fix opencv video freeze few second when sound play?

i try create application motion detector, when detected will play alarm. the program is running but the problem is when sound play video will freeze few second. so how to fix that?
I was tired of looking for references, but couldn't find anything.
import cv2
import numpy as np
import os
from playsound import playsound
# Video Capture
capture = cv2.VideoCapture(1)
fgbg = cv2.createBackgroundSubtractorMOG2(50, 200, True)
# frame
frameCount = 0
while(1):
# frame value
ret, frame = capture.read()
# cek frame
if not ret:
break
frameCount += 1
# resize frame
resizedFrame = cv2.resize(frame, (0, 0), fx=0.50, fy=0.50)
# foreground
fgmask = fgbg.apply(resizedFrame)
# jumlah Pixel
count = np.count_nonzero(fgmask)
if (frameCount > 1 and count > 5000):
playsound('tune.mp3')
os.system('cls' if os.name == 'nt' else 'clear')
print('Frame: %d, Pixel Count: %d' % (frameCount, count))
cv2.imshow('Frame', resizedFrame)
cv2.imshow('Mask', fgmask)
k = cv2.waitKey(1)
if k == 27:
break
capture.release()
cv2.destroyAllWindows()
Unfortunately, opencv when You play a sound from playsound. Even if You try calling plahsound using threads it will still freeze.
However, You can use Pygame's Mixer, which doesn't interrupt opencv's window. You can play a sound by:
from pygame import mixer
mixer.init()
sound = mixer.Sound('mysound.ogg')
sound.play()
However, I think Pygame's mixer is incompatible with mp3 files. You might wanna use .wav instead, or convert your mp3 file to .ogg format.

Using opencv to detect faces and play music at the same time

I wrote a program that will play a warning sound when a face is detected (play audio file)
However, the sound file will always start playing after 10 ~ 30 seconds when the detection condition is triggered.
And if it is removed from the conditional sentence and played as background music,there is no problem.
May I ask how to solve it?
Thanks!
THE code I use to play sound:
winsound.PlaySound('1.wav', winsound.SND_FILENAME|winsound.SND_ASYNC)
The full code:
# -*- coding: utf-8 -*-
import dlib
import cv2
import imutils
import winsound
import os
import multiprocessing
import winsound
import time
from winsound import SND_ASYNC
import pygame
from pygame import mixer
#chose camera
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
#change size
cap.set(cv2. CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2. CAP_PROP_FRAME_HEIGHT, 360)
#Get the default face detector
detector = dlib.get_frontal_face_detector()
#Load 68 feature point models according to the shape_predictor method, this method is a detector for facial expression recognition
predictor = dlib.shape_predictor( 'shape_predictor_68_face_landmarks.dat')
#When the camera is turned on, each frame is detected
#pygame.mixer.init()
#mixer.music.load('incoming.mp3')
#mixer.music.play(-1)
#winsound.PlaySound('incoming.wav', winsound.SND_FILENAME| winsound.SND_ASYNC )
while(cap.isOpened()):
#Read frame information
ret, frame = cap.read()
#Detect faces
face_rects, scores, idx = detector.run(frame, 0)
#Retrieve the detection result
for i, d in enumerate(face_rects):
x1 = d.left()
y1 = d.top()
x2 = d.right()
y2 = d.bottom()
text = " %2.2f ( %d )" % (scores[i], idx[i])
#Draw a rectangular area for detecting faces
cv2.rectangle(frame, (x1, y1), (x2, y2), ( 0, 255, 0), 4, cv2. LINE_AA)
#Mark the face detection score and face direction sub-detector number
cv2.putText(frame, text, (x1, y1), cv2. FONT_HERSHEY_DUPLEX,
0.7, ( 255, 255, 255), 1, cv2. LINE_AA)
#play sound
if scores[i]>0.3 and idx[i]==0 :
print(text)
#pygame.mixer.pre_init(48000, 16, 2, 4096)
winsound.PlaySound('incoming.wav', winsound.SND_FILENAME| winsound.SND_ASYNC )
#Output to screen
cv2.imshow( "Face Detection", frame)
#If you press the ESC key, you exit
if cv2.waitKey( 10) == 27:
break
#Free memory
cap.release()
#Close all windows
cv2.destroyAllWindows()
and the gprof2dothere

Detect Circles in Raspberry pi with PiCamera

I want the Raspberry pi B+ to detect circles in images. I've been looking for some code, and I tried to use them with the raspberry pi. Here is my conclusion code, but the mainly problem is that it doesn't get the image with the detected objects (I am using as an example a tennis ball), it just get the image without the draw circle and rectangle.
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
import cv2
import os
import numpy as np
os.system('sudo modprobe bcm2835-v4l2')
h=200
w=300
camera = PiCamera()
camera.resolution = (w, h)
camera.framerate = 24
rawCapture = PiRGBArray(camera, size=(w, h))
time.sleep(0.1)
for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
image_RGB = frame.array
copy_RGB = image_RGB.copy()
grey = cv2.cvtColor(image_RGB, cv2.COLOR_BGR2GRAY)
img_circles = None
img_circles = cv2.HoughCircles(grey, cv2.cv.CV_HOUGH_GRADIENT, 1.2, 100)
if img_circles is not None:
img_circles = np.round(img_circles[0, :]).astype("int")
for (x, y, r) in img_circles:
cv2.circle(copy_RGB, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(copy_RGB, (x - 5, y - 5),(x + 5, y + 5), (0, 128, 255, -1))
cv2.imshow("Copy with Detected Object", copy_RGB)
key = cv2.waitKey(1) & 0xFF
rawCapture.truncate(0)
if key == ord("q"):
break
Any Help is appreciated.

Superimposing image over webcam feed using OpenCV 2.4.7.0 in Python 2.7

I am trying to superimpose an image over a camera feed in python. I can get an image to superimpose over another image, but when I apply the same thing to my camera feed it doesn't work. Here's my code so far:
#!/usr/bin/python
import cv2
import time
cv2.cv.NamedWindow("Hawk Eye", 1)
capture = cv2.cv.CaptureFromCAM(0)
cv2.cv.SetCaptureProperty(capture, cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 800)
cv2.cv.SetCaptureProperty(capture, cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 600)
x_offset=y_offset=50
arrows = cv2.imread("arrows.png")
while True:
webcam=cv2.cv.QueryFrame(capture)
#webcam[y_offset:y_offset+arrows.shape[0], x_offset:x_offset+arrows.shape[1]]=arrows
cv2.cv.ShowImage("Hawk Eye", webcam)
if cv2.cv.WaitKey(10) == 27:
break
cv2.cv.DestroyAllWindows()
If I uncomment:
img[y_offset:y_offset+arrows.shape[0], x_offset:x_offset+arrows.shape[1]]=arrows
the line that imposes the image, it shows just the camera feed, but when I add it in my loop it stops working. Thanks!
This works OK using the cv2 API:
import cv2
import time
cv2.namedWindow("Hawk Eye", 1)
capture = cv2.VideoCapture(0)
capture.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 800)
capture.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 600)
x_offset=y_offset=50
arrows = cv2.imread("hawk.png")
while True:
ret, webcam = capture.read()
if ret:
webcam[y_offset:y_offset+arrows.shape[0], x_offset:x_offset+arrows.shape[1]]=arrows
cv2.imshow("Hawk Eye", webcam)
if cv2.waitKey(10) == 27:
break
cv2.destroyAllWindows()

Categories