In my code I am constantly grabbing frames from a camera to check if there is any human body present or not. whenever there is a human, crop the body and upload it on server. and keep doing this.
PROBLEM: Whenever I start a thread to upload photo to server my program execution stops and wait for the upload thread to finish. I don't want my program execution to stop and wait. I want it to run without stopping. I want to start a separate thread to upload photo that runs parallel, does its job without disturbing normal flow and finishes after it. it should do this every time there is a body detected.
# USAGE
# python detect.py --images images
# import the necessary packages
from __future__ import print_function
from imutils.object_detection import non_max_suppression
from imutils import paths
import numpy as np
import argparse
import imutils
import cv2
import time
import threading
import Queue
import multiprocessing
import requests
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
import urllib2
from urllib2 import Request, urlopen, URLError
import Queue
import urllib
import traceback
size = 2
i=0
#Queues to store data
queue_FACES = multiprocessing.Queue()
(im_width, im_height) = (112, 112)
# initialize the HOG descriptor/person detector
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
# Capture Camera Stream
#webcam = cv2.VideoCapture('/home/irum/Desktop/WIN_20170529_09_53_13_Pro.mp4')
webcam = cv2.VideoCapture(0)
#h=4.27 w=4.29 AVG = 4.28
# Upload to server
def upload_internet(filename2,sampleFile,check_path1):
#print("upoading....")
filename2 = filename2+'.jpg'
#print (filename2)
register_openers()
datagen, headers = multipart_encode({"sampleFile": open(sampleFile), "name": filename2})
#request = urllib2.Request("http://videoupload.hopto.org:5000/api/Sync_log", datagen, headers)
request = urllib2.Request("http://videoupload.hopto.org:5002/api/Synclog", datagen, headers)
try:
#print ("***UPLOAD SERVER RESPONSE***")
response = urllib2.urlopen(request)
html=response.read()
print ("html ",html)
#resp = json.loads(html)
# with open('output_file.txt', "wb") as code: #CHANGE PATH
# code.write(curr_time+"\n"+html +"\n")
except URLError , e:
if hasattr(e, 'reason'):
#print ('We failed to reach a server.')
print ('Reason: ', e.reason)
elif hasattr(e, 'code'):
#print ('The server couldn\'t fulfill the request.')
print ('Error code: ', e.code)
except Exception:
print ('generic exception: ' + traceback.format_exc())
while True:
# read each frame
ret, frame = webcam.read()
# resize it
image = imutils.resize(frame, width=min(300, frame.shape[1]))
orig = image.copy()
# detect people in the frame
(rects, weights) = hog.detectMultiScale(image, winStride=(4, 4),
padding=(8, 8), scale=1.05)
# draw the original bounding boxes
for i in range(len(rects)):
body_i = rects[i]
(x, y, w, h) = [v * 1 for v in body_i]
cv2.rectangle(orig, (x, y), (x + w, y + h), (0, 0, 255), 2)
# apply non-maxima suppression
rects = np.array([[x, y, x + w, y + h] for (x, y, w, h) in rects])
pick = non_max_suppression(rects, probs=None, overlapThresh=0.65)
# draw the final bounding boxes
for i in range(len(rects)):
body_i = rects[i]
(xA, yA, xB, yB) = [int(v * 1) for v in body_i]
# rect on scaled image
cv2.rectangle(image, (xA, yA), (xB, yB), (0, 255, 0), 2)
# rects to map on original frame
(x1, y1, w1, h1) = [int(v * 4.28) for v in body_i]
cv2.rectangle(frame, (x1, y1), (w1, h1), (0, 45, 255), 2)
# Crop body from Original frame
body_big = frame[y1:y1+h1, x1:x1+w1]
# Save body
save_body_path = '/home/irum/Desktop/pedestrian-detection/BIG_BODY'
cur_date = (time.strftime("%Y-%m-%d"))
cur_time = (time.strftime("%H:%M:%S"))
new_pin =cur_date+"-"+cur_time
filename1 = 'BIG'
filename2 = str(filename1)+"-"+str(new_pin)
print ("filename2",filename2)
sampleFile = ('%s/%s.jpg' % (save_body_path, filename2))
print ("sampleFile",sampleFile)
cv2.imwrite('%s/%s.jpg' % (save_body_path, filename2), body_big)
# upload body
upload_process = threading.Thread(target=upload_internet(filename2,sampleFile,save_body_path))
upload_process.start()
# show the output images
cv2.imshow("Before NMS", orig)
cv2.imshow("After NMS", image)
cv2.imshow("BIG BODY", frame)
# cv2.imshow("FACE", body_big2)
key = cv2.waitKey(10)
if key == 27:
break
Correction:
Use cThread = threading.Thread( target= , args=() ) to define a
new thread instance
Use cThread.start() to launch it, of course you don't have join since your process is continuous.
simplified code so I could test-run it at my end:
import time
import threading
import multiprocessing
from time import sleep
def upload_internet(filename,sampleFile,check_path):
print ("//// WAITING FOR SERVER RESPONSE")
time.sleep(3)
print ("RECEIVED SERVER RESPONSE \\\\\\")
filename = "filename"
sampleFile = "sampleFile"
save_body_path = "save_body_path"
key = 1
while True:
rects = range(0,10)
# draw the original bounding boxes
range_len_rects = range(len(rects))
for i in range_len_rects:
print("Main starts")
rects = range(0,10)
thread_list = []
for i in range_len_rects:
# upload body
thread_list.append ( threading.Thread( target=upload_internet, args=( filename + "-" + str(i) ,sampleFile,save_body_path) ) )
thread_list[i].start()
print ("Exiting Launch Thread loop :"+ str(i) + "/" + str(range_len_rects[i]) )
print("Main sleep for 10 seconds")
time.sleep(10);
if key == 27:
break
PS: Remember the thread is not destroyed and you must ensure the upload_internet() doesn't stuck in memory for any reason, or you can control number of instance you have and set cap and manage zombie threads to avoid process crash and bad memory management
Related
I'm trying to implement a code that takes a video and divides it into frames while also filtering the frames and saving them to a different directory.
I am running into an error that says:
TypeError: cannot pickle 'cv2.VideoCapture' object
I have tried to understand why this problem occurs but I'm still unsure why.
here is my code:
import cv2
import os
import time
import matplotlib.image as pltim
from multiprocessing import Process, Lock
import matplotlib.pyplot as plt
def saveFramesUnfiltered(vid, lock):
currentFrame = 0 # counter for frames (to organize them by order)
while True:
success, frame = vid.read()
lock.acquire()
cv2.imwrite("./framesBefore/frame" + str(currentFrame) + '.jpg',
frame) # save unfiltered frame to folder and show the video (using the frames)
lock.release()
currentFrame = currentFrame + 1
if cv2.waitKey(1) & 0xFF == ord('q'):
break # end loop when finished
time.sleep(0.01)
def saveFramesFiltered(lock):
currentFrame = 0
framemax = 215
while currentFrame < framemax:
if os.path.exists("framesBefore/frame" + str(currentFrame) + '.jpg'):
lock.acquire()
image = pltim.imread("./framesBefore/frame" + str(currentFrame) + '.jpg')
lock.release()
r, g, b = image[:, :, 0], image[:, :, 1], image[:, :, 2]
grayImage = 0.299 * r + 0.587 * g + 0.114 * b
plt.plot(grayImage, cmap="gray")
plt.axis("off")
lock.acquire()
plt.savefig("./framesAfter/grayImage" + str(currentFrame) + ".jpg", bbox_inches='tight', pad_inches=0)
lock.release()
time.sleep(0.01)
def main():
if not os.path.exists('framesBefore'):
os.makedirs('framesBefore') # create a folder for the unfiltered frames
if not os.path.exists('framesAfter'):
os.makedirs('framesAfter') # create a folder for the filtered frames
lock = Lock()
vid = cv2.VideoCapture("maxwell cat.mp4") # getting the video
unfiltered_process = Process(target=saveFramesUnfiltered, args=(vid, lock))
filtered_process = Process(target=saveFramesFiltered, args=lock)
unfiltered_process.start()
filtered_process.start()
unfiltered_process.join()
filtered_process.join()
vid.release()
cv2.destroyAllWindows() # clear memory
if __name__ == '__main__':
main()
I am also new at using threads in python and in general so I would like to know if the way I implemented it is correct.
thanks!
The server is sending video by video using the same RTSP URL(rtsp://192.168.0.2:8554/)
I can capture and display video using opencv.
import numpy as np
import cv2 as cv
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp"
cap = cv.VideoCapture('rtsp://192.168.0.2:8554/')
while cap.isOpened():
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
cv.imshow('frame', frame)
if cv.waitKey(1) == ord('q'):
break
cap.release()
cv.destroyAllWindows()
This program returns error when going on to the next video.
I tried this, but this didn't work.
import cv2 as cv
import os
import time
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp"
cap = cv.VideoCapture('rtsp://192.168.0.26:8554/')
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
try:
time.sleep(2)
# Capture frame-by-frame
ret, frame = cap.read()
# if frame is read correctly ret is True
# Our operations on the frame come here
# Display the resulting frame
cv.imshow('frame',frame)
if cv.waitKey(1) == ord('q'):
break
except:
print("Exception!!")
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
Can I get some help?
Thanks in advance!
I solved this by using multi-threaded program.
Main file
from datasets import LoadStreams
import threading
import os
import logging
import cv2
import torch
import time
logger = logging.getLogger(__name__)
def select_device(device='', batch_size=None):
# device = 'cpu' or '0' or '0,1,2,3'
cpu_request = device.lower() == 'cpu'
if device and not cpu_request: # if device requested other than 'cpu'
os.environ['CUDA_VISIBLE_DEVICES'] = device # set environment variable
assert torch.cuda.is_available(), f'CUDA unavailable, invalid device {device} requested' # check availablity
cuda = False if cpu_request else torch.cuda.is_available()
if cuda:
c = 1024 ** 2 # bytes to MB
ng = torch.cuda.device_count()
if ng > 1 and batch_size: # check that batch_size is compatible with device_count
assert batch_size % ng == 0, f'batch-size {batch_size} not multiple of GPU count {ng}'
x = [torch.cuda.get_device_properties(i) for i in range(ng)]
s = f'Using torch {torch.__version__} '
for i, d in enumerate((device or '0').split(',')):
if i == 1:
s = ' ' * len(s)
logger.info(f"{s}CUDA:{d} ({x[i].name}, {x[i].total_memory / c}MB)")
else:
logger.info(f'Using torch {torch.__version__} CPU')
logger.info('') # skip a line
return torch.device('cuda:0' if cuda else 'cpu')
def detect(rtsp_url):
dataset = LoadStreams(rtsp_url)
device = select_device('')
count = 0
view_img = True
# img = torch.zeros((1, 3, imgsz, imgsz), device=device) # init img
try:
for frame_idx, (path, img, im0s, vid_cap) in enumerate(dataset): # for every frame
count += 1
im0 = im0s[0].copy()
if view_img:
cv2.imshow(str(path), im0)
# if cv2.waitKey(1) == ord('q'): # q to quit
# raise StopIteration
except:
print("finish execption")
dataset.stop()
return "good"
if __name__ == '__main__':
rtsp_url = "rtsp://192.168.0.26:8554/"
while True:
for thread in threading.enumerate():
print(thread.name)
print(detect(rtsp_url))
dataset class file
import glob
import logging
import math
import os
import random
import shutil
import time
import re
from itertools import repeat
from multiprocessing.pool import ThreadPool
from pathlib import Path
from threading import Thread
import cv2
import numpy as np
import torch
class LoadStreams: # multiple IP or RTSP cameras
def __init__(self, sources='streams.txt', img_size=640):
self.mode = 'stream'
self.img_size = img_size
self.capture = None
self.my_thread = None
self.stopFlag = False
if os.path.isfile(sources):
with open(sources, 'r') as f:
sources = [x.strip() for x in f.read().strip().splitlines() if len(x.strip())]
else:
sources = [sources]
n = len(sources)
self.imgs = [None] * n
self.sources = [clean_str(x) for x in sources] # clean source names for later
s = sources[0]
# for i, s in enumerate(sources):
# Start the thread to read frames from the video stream
# print('%g/%g: %s... ' % (i + 1, n, s), end='')
cap = cv2.VideoCapture(eval(s) if s.isnumeric() else s)
assert cap.isOpened(), 'Failed to open %s' % s
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS) % 100
self.ret, self.imgs[0] = cap.read() # guarantee first frame
thread = Thread(target=self.update, args=([0, cap]), daemon=True)
print(' success (%gx%g at %.2f FPS).' % (w, h, fps))
thread.start()
self.capture = cap
self.my_thread = thread
print('') # newline
# check for common shapes
s = np.stack([letterbox(x, new_shape=self.img_size)[0].shape for x in self.imgs], 0) # inference shapes
self.rect = np.unique(s, axis=0).shape[0] == 1 # rect inference if all shapes equal
if not self.rect:
print('WARNING: Different stream shapes detected. For optimal performance supply similarly-shaped streams.')
def update(self, index, cap):
# Read next stream frame in a daemon thread
n = 0
while cap.isOpened() and not self.stopFlag:
n += 1
# _, self.imgs[index] = cap.read()
cap.grab()
if n == 4: # read every 4th frame
_, self.imgs[index] = cap.retrieve()
n = 0
time.sleep(0.01) # wait time
def stop(self):
self.stopFlag = True
try:
# self.capture.release()
# self.my_thrsead.join()
print("stop thread!!")
except:
print("ERROR stopping thread!!")
def __iter__(self):
self.count = -1
return self
def __next__(self):
self.count += 1
img0 = self.imgs.copy()
if cv2.waitKey(1) == ord('q'): # q to quit
cv2.destroyAllWindows()
raise StopIteration
if not self.ret:
print("error!!!")
self.stop()
# Letterbox
img = [letterbox(x, new_shape=self.img_size, auto=self.rect)[0] for x in img0]
# Stack
img = np.stack(img, 0)
# Convert
img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
img = np.ascontiguousarray(img)
return self.sources, img, img0, None
def __len__(self):
return 0 # 1E12 frames = 32 streams at 30 FPS for 30 years
# def stop(self):
def clean_str(s):
# Cleans a string by replacing special characters with underscore _
return re.sub(pattern="[|##!¡·$€%&()=?¿^*;:,¨´><+]", repl="_", string=s)
def letterbox(img, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleFill=False, scaleup=True):
# Resize image to a 32-pixel-multiple rectangle https://github.com/ultralytics/yolov3/issues/232
shape = img.shape[:2] # current shape [height, width]
if isinstance(new_shape, int):
new_shape = (new_shape, new_shape)
# Scale ratio (new / old)
r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
if not scaleup: # only scale down, do not scale up (for better test mAP)
r = min(r, 1.0)
# Compute padding
ratio = r, r # width, height ratios
new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
if auto: # minimum rectangle
dw, dh = np.mod(dw, 32), np.mod(dh, 32) # wh padding
elif scaleFill: # stretch
dw, dh = 0.0, 0.0
new_unpad = (new_shape[1], new_shape[0])
ratio = new_shape[1] / shape[1], new_shape[0] / shape[0] # width, height ratios
dw /= 2 # divide padding into 2 sides
dh /= 2
if shape[::-1] != new_unpad: # resize
img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR)
top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border
return img, ratio, (dw, dh)
while cap.isOpened() and not self.stopFlag:
this line is especially important because
without this line the threads will be stacked and will have memory error
as the stack stacks up.
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
>> my py script is running fine but when i created .py to .exe the below error is generated.
OpenCV(4.1.1) C:\projects\opencv-python\opencv\modules\videoio\src\cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): http://admin:admin#192.168.1.86/axis-cgi/mjpg/video.cgi in function 'cv::icvExtractPattern'
My py script is below and its generate.
import face_recognition
import cv2
import time
import requests
import json
from http.client import responses
from datetime import datetime
from datetime import timedelta
import sys
from truepy import License
from getmac import get_mac_address as gma
import easygui
# global variables
ChangeLayoutTime = time.localtime()
IsApiCall = False
currentTime = datetime.now()
afterTime=datetime.now()
layout_duration=0
#import json file parameters here
with open('config.json', 'r') as f:
distros_dict = json.load(f)
XiboClient_id = distros_dict['client_id']
XiboClient_secret=distros_dict["client_secret"]
XiboUrl=distros_dict["url"]
XiboDisplaygroup=distros_dict["displaygroup"]
XiboLayoutId=distros_dict["layoutId"]
IpCamStreamUrl=distros_dict["ipCamStreamUrl"]
playerIpAddress=distros_dict["playerIpAddress"]
print(IpCamStreamUrl)
# print(xiboclient_id)
# print(xiboclient_secret)
# print(xibourl)
# print(xibodisplaygroup)
# print(xibolayoutid)
# sys.exit()
# url = "'"+XiboClient_id+"'"
# print(url)
#check lic
def validateLicense():
# Load the certificate
with open('certificate.pem', 'rb') as f:
certificate = f.read()
# Load the license
with open('license.lic', 'rb') as f:
license = License.load(f, b'stech_lic_78324')
# Verify the license; this will raise License.InvalidSignatureException if
# the signature is incorrect
license.verify(certificate)
if license.data.extra != gma(ip=playerIpAddress):
print(license.data.extra)
print(gma(ip=playerIpAddress))
# shutdown the application and notify user about invalid license
easygui.msgbox("Your camera module license is invalid please contact to S-Tech team", title="Invalid License!")
sys.exit()
def __draw_label(img, text, pos, bg_color):
font_face = cv2.FONT_HERSHEY_SIMPLEX
scale = .4
color = (0, 0, 0)
thickness = cv2.FILLED
margin = 2
txt_size = cv2.getTextSize(text, font_face, scale, thickness)
end_x = pos[0] + txt_size[0][0] + margin
end_y = pos[1] - txt_size[0][1] - margin
cv2.rectangle(img, pos, (end_x, end_y), bg_color, thickness)
cv2.putText(img, text, pos, font_face, scale, color, 1, cv2.LINE_AA)
# Get a reference to webcam #0 (the default one)
video_capture = cv2.VideoCapture(IpCamStreamUrl)
# video_capture = cv2.VideoCapture("http://192.168.1.20:8080/video")
# Initialize some variables
face_locations = []
while True:
# Grab a single frame of video
ret, frame = video_capture.read()
if ret ==False:
break
# Resize frame of video to 1/4 size for faster face detection processing
small_frame = cv2.resize(frame, (0,0),fx=1,fy=1,interpolation = cv2.INTER_AREA)
# Find all the faces and face encodings in the current frame of video
face_locations = face_recognition.face_locations(small_frame, model="hog")
print(face_locations)
if face_locations is ():
break
if datetime.now().strftime("%S") == afterTime.strftime("%S"):
IsApiCall=False
# Display the results
i=0
genders=[]
ages=()
for top, right, bottom, left in face_locations:
# Scale back up face locations since the frame we detected in was scaled to 1/4 size
top *= 4
right *= 4
bottom *= 4
left *= 4
# Extract the region of the image that contains the face
face_image = frame[top:bottom, left:right]
height,width = face_image.shape[:2]
if width>144:
image='face{}.jpg'.format(i)
cv2.imwrite(image,face_image)
if datetime.now().strftime("%S") == afterTime.strftime("%S"):
IsApiCall=False
# customization by basit for layout change digisign player
if IsApiCall is False:
#check License
validateLicense()
# Access Token api
url = "http://"+XiboUrl+"/api/authorize/access_token"
data = {
'client_id': XiboClient_id,
'client_secret': XiboClient_secret,
'grant_type': 'client_credentials'
}
response = requests.request("POST", url, data=data)
obj=json.loads(response.text)
temp = obj["access_token"]
# Change layout Api
url = "http://"+XiboUrl+"/api/displaygroup/"+XiboDisplaygroup+"/action/changeLayout?envelope=1"
data = {
'layoutId': XiboLayoutId,
'changeMode': 'replace'
}
headers = {
'Authorization': 'Bearer '+temp
}
response = requests.request("POST", url, headers=headers, data=data)
print("Layout change = Success")
IsApiCall = True
# Get layout duration api
url = "http://"+XiboUrl+"/api/layout/status/"+XiboLayoutId+"?envelope=1"
headers = {
'Authorization': 'Bearer '+temp
}
response = requests.request("GET", url, headers=headers)
objj=json.loads(response.text)
temp1 = objj["data"]
layout_duration=temp1["duration"]
print("Current layout duration is " +str(layout_duration)+ " second")
currentTime = datetime.now()
afterTime = (datetime.now() + timedelta(seconds=layout_duration+10))
print("Next layout change after "+afterTime.strftime("%H")+":"+afterTime.strftime("%M")+":"+afterTime.strftime("%S"))
else:
currentTime=(datetime.now())
if (currentTime.strftime("%S") == afterTime.strftime("%S")):
IsApiCall = False
#For Vedio display window
cv2.namedWindow('Video', cv2.WINDOW_NORMAL)
cv2.imshow('Video', frame)
# Hit 'q' on the keyboard to quit!
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Release handle to the webcam
video_capture.release()
cv2.destroyAllWindows()
I'm working on a university project combining MQTT and Face recognition, using a raspberry pi.
First of all I want to say that face recognition works normally when it's being run on its own but I have something that bugs me when applying it with MQTT.
Inside the Try section, when a person is being recognized or unknown it publishes really fine every 3 secs.
The strange thing is that if I put my hand in front of the camera or if I get out of range, it keeps on sending the ID of the last person it had recognized.
I want it either do nothing or publish none.
Any idea or suggestion to fix this?
Thanks in advance
EDIT 1: Basically as I figured out, it has to do more with the face recognition part. When using just a face recognition code using opencv it runs smoothly. But the thing complicates when I put my hand in front of the camera or go away, because the capture freezes at the last thing it sees so it keeps on printing/publishing the same thing. Haven't figured out a way to avoid this yet. Any help would be appreciated
import cv2
import json
import time
import datetime as dt
import paho.mqtt.client as mqtt
detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
recognizer = cv2.face.LBPHFaceRecognizer_create()
broker = "*****"
port = *****
username = '*****'
password = '*****'
def on_connect(client, userdata, flags, rc):
print("Connected with code: ", rc)
client.subscribe('test/#')
def on_message(client, userdata, msg):
print(str(msg.payload))
client = mqtt.Client("Python1")
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(username, password)
client.connect(broker, port, 60)
client.loop_start()
time.sleep(1)
def facerecognizer():
recognizer.read("trainerdir/training.yml")
font = cv2.FONT_HERSHEY_SIMPLEX
# Loading data
with open('data.json', 'r') as f:
names = json.load(f)
# reverse the data
# NOTE: for k, v !!
# else it raises error !
names = {v: k for k, v in names.items()}
# print(names)
print("[INFO] Face recognition is starting..")
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 360)
try:
while True:
ret, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector.detectMultiScale(gray,
scaleFactor=1.3,
minNeighbors=5
# minSize = (20,20)
)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
roi_gray = gray[y:y + h, x:x + w]
roi_color = img[y:y + h, x:x + w]
ID, confidence = recognizer.predict(roi_gray)
if (confidence < 100):
ID = names[ID]
confidence = "{}%".format(round(100 - confidence))
while True:
client.publish("Tutorial/", ID + " " + str(dt.datetime.now()))
print('ID sent')
time.sleep(3)
else:
client.publish("Tutorial/", 'None')
print('ID sent')
time.sleep(3)
client.loop_forever()
else:
ID = "Unkown"
confidence = "{}%".format(round(100 - confidence))
print(ID, dt.datetime.now())
while True:
client.publish("Tutorial/", ID + " " + str(dt.datetime.now()))
print('ID sent')
time.sleep(3)
else:
client.publish("Tutorial/", 'None')
print('ID sent')
time.sleep(3)
client.loop_forever()
# except UnboundLocalError:
# print("Error occured. Exitting..")
except KeyboardInterrupt:
pass
except KeyError as K:
print(K)
print('[INFO] Name Value is a string and not an integer')
print("[INFO] Exiting program..")
cap.release()
From the documentation on mqtt clients, you seem to be misusing the client.loop_forever() method.
http://www.steves-internet-guide.com/loop-python-mqtt-client/
TLDR
Use client.loop(timeout) in a loop to control processing of updates.
Use client.loop_start() starts a new thread which handles updates for you.
Use client.loop_forever() to block and process updates.
Since you have already called client.loop_start(), you don't need to call loop_forever(). Removing those calls from your code should resolve the issue.
Side note: your time.sleep(3) call could be moved to the end of the loop, since it should happen no matter which conditional path it takes.
By using if True: instead of while True: I fixed it. I also removed the subclient.loop_forever() and it works fine.
Here is the sample code that is different from the code I posted to my question
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
roi_gray = gray[y:y + h, x:x + w]
# roi_color = img[y:y + h, x:x + w]
ID, confidence = recognizer.predict(roi_gray)
# 0 is 100% accuracy , and 100 is 0% accuracy
if (confidence < 100):
ID = names[ID]
if True:
subclient.publish("project/IDReceiver", ID + " " + str(dt.datetime.now()))
print('ID sent')
time.sleep(3)
# subclient.loop_forever()
else:
ID = "Unknown"
if True:
subclient.publish("project/IDReceiver", "Unknown " + str(dt.datetime.now()))
print('ID sent')
time.sleep(3)