I am doing a people counter activity on a live video using Raspberry pi 3 model B with PiCamera.
Following is our code :
# 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 RPi.GPIO as GPIO
from threading import Thread
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
# initialize the camera and grab a reference to the raw camera capture
resX = 240
resY = 180
camera = PiCamera()
camera.resolution = (resX,resY)
camera.framerate = 10
rawCapture = PiRGBArray(camera, size=(resX, resY))
# initialize textIn and textOut values
textIn = 0
textOut = 0
print(time.strftime("%H_%M_%S"))
#fourcc = cv2.VideoWriter_fourcc(*'XVID')
fourcc = cv2.cv.CV_FOURCC(*'XVID')
out = cv2.VideoWriter(time.strftime("%H_%M_%S")+'.avi',fourcc, 20.0, (resX, resY))
# initialize the HOG descriptor/person detector
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
detectFlag = 0
detectCounter = [0]
# allow the camera to warmup
time.sleep(0.1)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(16, GPIO.OUT)
# methods for IN and OUT counters
def testIntersectionIn(x, y, z):
if((x >= 75) and (x <= 90) and (x < z[0]) and (z[0]>0)):
print (x,z[0],"IN")
return True
return False
def testIntersectionOut(x, y, z):
if((x >= 75) and (x <= 90) and (x > z[0]) and (z[0]>0)):
print (x,z[0],"OUT")
return True
return False
previousObj = (0,0)
def classfier(testImage,threadNum,capTime, detectCounter):
global textIn, textOut, previousObj
#print(threadNum,capTime)
(rects, weights) = hog.detectMultiScale(testImage, winStride=(8, 8),
padding=(16, 16), scale=1.1)
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
cv2.line(image, (75,0), (75,192), (250, 0, 1), 2) #blue line
cv2.line(image, (90,0), (90,192), (0, 0, 255), 2)#red line
for (xA, yA, xB, yB) in pick:
print("Image detected")
print ("Previous Coord : ",previousObj)
detectCounter[0] = 0
cv2.rectangle(testImage, (xA, yA), (xB, yB), (0, 255, 0), 2)
rectangleCenterPont = ((xA + xB) /2, (yA + yB) /2 )
cv2.circle(testImage, rectangleCenterPont, 1, (0,0,255), 5)
print (rectangleCenterPont)
if(testIntersectionIn((xA + xB) /2, (yA + yB) /2,previousObj)):
textIn += 1
#print testIntersectionIn((x + x + w) / 2, (y + y + h) / 2)
if(testIntersectionOut((xA + xB) /2, (yA + yB) /2,previousObj)):
textOut += 1
#print textOut
previousObj = rectangleCenterPont
cv2.putText(image, "In: {}".format(str(textIn)), (10, 50),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(image, "Out: {}".format(str(textOut)), (10, 70),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
# print(pick,"\n");
curTime = time.time()
#print ("Total time from capture", curTime - capTime)
out.write(testImage)
cv2.imshow("After NMS", testImage)
# capture frames from the camera
i = 0
frameCount = 0
prevTime = time.time()
for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
if (detectCounter[0] < 10):
GPIO.output(16, GPIO.LOW)
print ("Waiting ", detectCounter[0])
detectCounter[0] += 1
else:
GPIO.output(16,GPIO.HIGH)
image = frame.array
captureTime = time.time()
# print("FRAME Time", captureTime-prevTime)
prevTime = captureTime
# if frameCount == 0:
# frameCount = 0
#if i == 0:
t1 = Thread(target = classfier, args = (image,i,captureTime,detectCounter))
t1.start()
threadPick = t1.join()
# cv2.imshow("Frame", image)
key = cv2.waitKey(1) & 0xFF
# clear the stream in preparation for the next frame
rawCapture.truncate(0)
# if the `q` key was pressed, break from the loop
if key == ord("q"):
cleanup_stop_thread();
sys.exit()
t1.stop()
break
In the above code
We draw two lines on the frame
Finding the center point of rectangle
When that center point falls between these two lines we increase our
counter
IN and OUT counter logic is based on the values from these two lines
The Problem I face here is
The rectangle over the human is not on it uniformly. It disappears and appearing again at random points in the frame.
For e.g, When the object comes close to the first line the rectangle disappears and comes again when he goes out of the line. So here the center point of rectangle will not fall between these lines so our counter will not increase for this case.
In some cases the detection is happening late. Not once the person comes into the frame.
Please suggest me any ways to avoid this and maintain that rectangle all the time when any person is in the frame.
Related
My opencv code is lagging in raspbpi but in pc its smooth. Can anyone help me make my hard code to a code that uses threading.
from cv2 import cv2
import numpy as np
from pyzbar.pyzbar import decode
import pickle,time
import os
import imutils
import screeninfo
from screeninfo import get_monitors
curr_path = os.getcwd()
#########models##################################################
print("Loading face detection model")
proto_path = os.path.join(curr_path, 'model', 'deploy.prototxt')
model_path = os.path.join(curr_path, 'model', 'res10_300x300_ssd_iter_140000.caffemodel')
face_detector = cv2.dnn.readNetFromCaffe(prototxt=proto_path, caffeModel=model_path)
print("Loading face recognition model")
recognition_model = os.path.join(curr_path, 'model', 'openface_nn4.small2.v1.t7')
face_recognizer = cv2.dnn.readNetFromTorch(model=recognition_model)
################pickles#########################################
recognizer = pickle.loads(open('recognizer.pickle', "rb").read())
le = pickle.loads(open('le.pickle', "rb").read())
print("Starting test video file")
#adjacents########################################################################
no_of_adjacent_prediction=0
no_face_detected=0 #to track the number of times the face is detected
prev_predicted_name='' #to keep track of the previously predicted face(w.r.t frame)
count_frames = total_no_face_detected = 0
#camera#########################################################################
font=cv2.FONT_HERSHEY_SIMPLEX
clr=(255,255,255)
cap = cv2.VideoCapture(0)
time.sleep(2)
profile = None
####TRY_COUNTS###########
MAX_TRY=3
tries=0 #
######flags############
flag = True
flag_face_recognised=False #to keep track if the user face is recognized
flag_face_not_recognised=False
#############FULLSCREEN###############
WINDOW_NAME = "Face-Rcognition and QRCODEQQQQQ"
screenid = 0
while True:
cv2.namedWindow(WINDOW_NAME, cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty(WINDOW_NAME, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
ret, frame = cap.read()
screen = screeninfo.get_monitors()[screenid]
screen_width, screen_height = screen.width,screen.height
frame = cv2.flip(frame, 1)
frame_height, frame_width, _ = frame.shape
scaleWidth = float(screen_width) / float(frame_width)
scaleHeight = float(screen_height) / float(frame_height)
if (flag):
access = open("AccessCodes.txt")
for i in decode(frame):
decoded_data = i.data.decode("utf-8") # converts bytes to string value
print(decoded_data)
# Drawing polygon on frame (tilts w.r.t orientation)
pts = np.array([i.polygon], np.int32)
pts = pts.reshape((-1, 1, 2))
cv2.polylines(frame, [pts], True, (0, 255, 0), 1)
# print(pts)
# Display text
rect_pts = i.rect # using rect point as origin for text as we don't want the text to tilt with the qrcode
fontScale = 0.8
thickness = 1
# cv2.putText(frame,decoded_data,(rect_pts[0],rect_pts[1]),cv2.FONT_HERSHEY_SIMPLEX,fontScale,(255,0,0),thickness)
# print(rect_pts)
if decoded_data.lower() in access.read(): # Check private key
flag = False
tries = 0
print("QRCODE is Valid.Proceed to FaceRecog")
time_out_no_of_frames_after_qrcode = 0
else:
# print("INVALID QR CODE")
print("Invalid QRCODE")
if scaleHeight > scaleWidth:
imgScale = scaleWidth
else:
imgScale = scaleHeight
newX, newY = frame.shape[1] * imgScale, frame.shape[0] * imgScale
frame = cv2.resize(frame, (int(newX), int(newY)))
cv2.imshow(WINDOW_NAME, frame)
else:
frame = cv2.resize(frame, (int(newX), int(newY)))
(h, w) = frame.shape[:2]
image_blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0), False, False)
face_detector.setInput(image_blob)
face_detections = face_detector.forward()
for i in range(0, face_detections.shape[2]):
confidence = face_detections[0, 0, i, 2]
if confidence > 0.90:
box = face_detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
face = frame[startY:endY, startX:endX]
(fH, fW) = face.shape[:2]
face_blob = cv2.dnn.blobFromImage(face, 1.0/255, (96, 96), (0, 0, 0), True, False)
face_recognizer.setInput(face_blob)
vec = face_recognizer.forward()
preds = recognizer.predict_proba(vec)[0]
j = np.argmax(preds)
proba = preds[j]
name = le.classes_[j]
text = "{}: {:.2f}".format(name, proba )
y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 0, 255), 2)
cv2.putText(frame, text, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)
cv2.putText(frame, "Welcome home " + name.replace('_', ' ').title(), (160, 460), font, 0.8, clr,
thickness+3, cv2.LINE_AA)
cv2.rectangle(frame, (startX, startY), (endX, endY), (255, 255, 255), 1)
if name == decoded_data.lower():
print("Face is Recognised: "+str(no_of_adjacent_prediction))
no_of_adjacent_prediction += 1
else:
print("Face not Recognised.")
cv2.putText(frame, "Face Not Recognised", (160, 460), font, 0.8, clr, thickness, cv2.LINE_AA)
flag_face_not_recognised = True
no_of_adjacent_prediction = 0
if (no_of_adjacent_prediction > 10): # no_of_adjacent_prediction is only updated when the confidence of classification is >80
flag_face_recognised = True
no_of_adjacent_prediction = 0
no_face_detected = 0
cv2.imshow(WINDOW_NAME, frame)
if (flag_face_recognised): # if face is recognized then open the door
# arduino.write(bytes('o', 'utf-8')) #Output the given byte string over the serial port.
print("DOOR is OPEN")
time.sleep(5)
# speak("Closing door")
# arduino.write(bytes('c', 'utf-8')) #Output the given byte string over the serial port.
print("DOOR is CLOSED")
flag_face_recognised = False
flag = True # to start from qrcode
if (flag_face_not_recognised):
# speak("Face not recognised. The door will remain closed")
time.sleep(2)
flag_face_not_recognised = False
tries += 1
if (tries >= MAX_TRY):
flag = True # to start from qrcode
tries = 0
if (time_out_no_of_frames_after_qrcode >= 400):
# speak("User authentication failed due to time out")
flag = True # to start from qrcode
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
cv2.destroyAllWindows()
FPS PC: 20 fps
FPS RASPBERRY PI : 9 fps
i tried various opencv codes and the result is still the same. I found a solution that threading increases the fps of opencv but i do not know how to apply this to my code due the fact that i am a noob python kid. a help would be nice. I want my fps in my raspberry ranging from 15-20 instead of 9 fps.
I have this code that performs the mouse functions using eyes and other facial gestures with opencv and dlib. I am running this code using a button click from a tkinter window. When this code starts to run, that tkinter window freezes (i.e, I cannot click any other button from that).
Is there a way that I can make the frame used by opencv a Top level, like top level frames in tkinter so that it doesn't freezes any other frames, or how can I replace opencv frame with Tkinter toplevel frame.
P.S: I have been on it for two days, literally tried anything I can find on the internet and can't seem to find a solution.
_, frame = vid.read()
frame = cv2.flip(frame, 1)
frame = imutils.resize(frame, width=cam_w, height=cam_h)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
This is the part where changes will be made I guess. Full code is shared below.
from imutils import face_utils
from utils import *
import numpy as np
import pyautogui as pag
import imutils
import dlib
import cv2
# Thresholds and consecutive frame length for triggering the mouse action.
MOUTH_AR_THRESH = 0.3
MOUTH_AR_CONSECUTIVE_FRAMES = 3
EYE_AR_THRESH = 0.20
EYE_AR_CONSECUTIVE_FRAMES = 5
WINK_AR_DIFF_THRESH = 0.001
WINK_AR_CLOSE_THRESH = 0.2
WINK_CONSECUTIVE_FRAMES = 4
# Initialize the frame counters for each action as well as
# booleans used to indicate if action is performed or not
MOUTH_COUNTER = 0
EYE_COUNTER = 0
WINK_COUNTER = 0
INPUT_MODE = False
EYE_CLICK = False
LEFT_WINK = False
RIGHT_WINK = False
SCROLL_MODE = False
ANCHOR_POINT = (0, 0)
WHITE_COLOR = (255, 255, 255)
YELLOW_COLOR = (0, 255, 255)
RED_COLOR = (0, 0, 255)
GREEN_COLOR = (0, 255, 0)
BLUE_COLOR = (255, 0, 0)
BLACK_COLOR = (0, 0, 0)
# Initialize Dlib's face detector (HOG-based) and then create
# the facial landmark predictor
shape_predictor = "model/shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(shape_predictor)
# Grab the indexes of the facial landmarks for the left and
# right eye, nose and mouth respectively
(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
(nStart, nEnd) = face_utils.FACIAL_LANDMARKS_IDXS["nose"]
(mStart, mEnd) = face_utils.FACIAL_LANDMARKS_IDXS["mouth"]
# Video capture
vid = cv2.VideoCapture(0)
resolution_w = 1366
resolution_h = 768
cam_w = 640
cam_h = 480
unit_w = resolution_w / cam_w
unit_h = resolution_h / cam_h
while True:
# Grab the frame from the threaded video file stream, resize
# it, and convert it to grayscale
# channels)
_, frame = vid.read()
frame = cv2.flip(frame, 1)
frame = imutils.resize(frame, width=cam_w, height=cam_h)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Detect faces in the grayscale frame
rects = detector(gray, 0)
# Loop over the face detections
if len(rects) > 0:
rect = rects[0]
else:
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
continue
# Determine the facial landmarks for the face region, then
# convert the facial landmark (x, y)-coordinates to a NumPy
# array
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
# Extract the left and right eye coordinates, then use the
# coordinates to compute the eye aspect ratio for both eyes
mouth = shape[mStart:mEnd]
leftEye = shape[lStart:lEnd]
rightEye = shape[rStart:rEnd]
nose = shape[nStart:nEnd]
# Because I flipped the frame, left is right, right is left.
temp = leftEye
leftEye = rightEye
rightEye = temp
# Average the mouth aspect ratio together for both eyes
mar = mouth_aspect_ratio(mouth)
leftEAR = eye_aspect_ratio(leftEye)
rightEAR = eye_aspect_ratio(rightEye)
ear = (leftEAR + rightEAR) / 2.0
diff_ear = np.abs(leftEAR - rightEAR)
nose_point = (nose[3, 0], nose[3, 1])
# Compute the convex hull for the left and right eye, then
# visualize each of the eyes
mouthHull = cv2.convexHull(mouth)
leftEyeHull = cv2.convexHull(leftEye)
rightEyeHull = cv2.convexHull(rightEye)
cv2.drawContours(frame, [mouthHull], -1, YELLOW_COLOR, 1)
cv2.drawContours(frame, [leftEyeHull], -1, YELLOW_COLOR, 1)
cv2.drawContours(frame, [rightEyeHull], -1, YELLOW_COLOR, 1)
for (x, y) in np.concatenate((mouth, leftEye, rightEye), axis=0):
cv2.circle(frame, (x, y), 2, GREEN_COLOR, -1)
# Check to see if the eye aspect ratio is below the blink
# threshold, and if so, increment the blink frame counter
if diff_ear > WINK_AR_DIFF_THRESH:
if leftEAR < rightEAR:
if leftEAR < EYE_AR_THRESH:
WINK_COUNTER += 1
if WINK_COUNTER > WINK_CONSECUTIVE_FRAMES:
pag.click(button='left')
WINK_COUNTER = 0
elif leftEAR > rightEAR:
if rightEAR < EYE_AR_THRESH:
WINK_COUNTER += 1
if WINK_COUNTER > WINK_CONSECUTIVE_FRAMES:
pag.click(button='right')
WINK_COUNTER = 0
else:
WINK_COUNTER = 0
else:
if ear <= EYE_AR_THRESH:
EYE_COUNTER += 1
if EYE_COUNTER > EYE_AR_CONSECUTIVE_FRAMES:
SCROLL_MODE = not SCROLL_MODE
# INPUT_MODE = not INPUT_MODE
EYE_COUNTER = 0
# nose point to draw a bounding box around it
else:
EYE_COUNTER = 0
WINK_COUNTER = 0
if mar > MOUTH_AR_THRESH:
MOUTH_COUNTER += 1
if MOUTH_COUNTER >= MOUTH_AR_CONSECUTIVE_FRAMES:
# if the alarm is not on, turn it on
INPUT_MODE = not INPUT_MODE
# SCROLL_MODE = not SCROLL_MODE
MOUTH_COUNTER = 0
ANCHOR_POINT = nose_point
else:
MOUTH_COUNTER = 0
if INPUT_MODE:
cv2.putText(frame, "READING INPUT!", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, RED_COLOR, 2)
x, y = ANCHOR_POINT
nx, ny = nose_point
w, h = 60, 35
multiple = 1
cv2.rectangle(frame, (x - w, y - h), (x + w, y + h), GREEN_COLOR, 2)
cv2.line(frame, ANCHOR_POINT, nose_point, BLUE_COLOR, 2)
dir = direction(nose_point, ANCHOR_POINT, w, h)
cv2.putText(frame, dir.upper(), (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, RED_COLOR, 2)
drag = 18
if dir == 'right':
pag.moveRel(drag, 0)
elif dir == 'left':
pag.moveRel(-drag, 0)
elif dir == 'up':
if SCROLL_MODE:
pag.scroll(40)
else:
pag.moveRel(0, -drag)
elif dir == 'down':
if SCROLL_MODE:
pag.scroll(-40)
else:
pag.moveRel(0, drag)
if SCROLL_MODE:
cv2.putText(frame, 'SCROLL MODE IS ON!', (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, RED_COLOR, 2)
# Show the frame
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# If the `Esc` key was pressed, break from the loop
if key == 27:
break
# Do a bit of cleanup
cv2.destroyAllWindows()
vid.release()
I want to ask how to change the color of Bounding Box and Font of a detected object when it is past a line. I am currently working on a project on human walking speed estimation by using Haar-cascade. The program works as such: the detected object passes two imaginary lines and when it passes the second line the program will show the speed. If the speed of the detected humans is below 3 km/h, the Bounding Box and the font will be shown in RED, but if it is more than 3 km/h it will be shown in GREEN. And I want the text of the speed to be shown for 5 seconds.
Hope you can help me solve this. Here's the program that I've worked on.
import time
cascade_src = 'haarcascade_fullbody.xml'
video_src = 'video-1.mp4'
#line a
ax1=15
ay=225
ax2=600
#line b
bx1=15
by=275
bx2=600
#car num
i = 1
start_time = time.time()
#video ....
cap = cv2.VideoCapture(video_src)
human_cascade = cv2.CascadeClassifier(cascade_src)
videoWidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
videoHeight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('wisuda-14.mp4', fourcc, 25.0, (videoWidth,videoHeight))
def Speed_Cal(time):
try:
Speed = (9.144*3600)/(time*1000)
return Speed
except ZeroDivisionError:
print (5)
while True:
ret, img = cap.read()
if (type(img) == type(None)):
break
#bluring to have exacter detection
blurred = cv2.blur(img, ksize=(3,3))
gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
human = human_cascade.detectMultiScale(gray, scaleFactor=1.04865, minNeighbors=6)
#line a #i know road has got
cv2.line(img,(ax1,ay),(ax2,ay),(255,0,0),2)
#line b
cv2.line(img,(bx1,by),(bx2,by),(255,0,0),2)
for (x,y,w,h) in human:
cv2.rectangle(img, (x,y), (x + w, y + h), (0, 0, 255), 2)
roi_blurred = blurred[x: x + h, y:y + w]
roi_gray = gray[x: x + h, y:y + w]
roi_img = img[x: x + h, y:y + w]
cv2.circle(img,(int((x+x+w)/2),int((y+y+h)/2)), 2,(0,255,0), -1)
#cv2.putText(img, "ID : " + str(i), (x, y-15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1);
while int(ay) == int((y+y+h)/2):
start_time = time.time()
break
while int(ay) <= int((y+y+h)/2):
if int(by) <= int((y+y+h)/2)&int(by+10) >= int((y+y+h)/2):
cv2.line(img, (bx1,by), (bx2,by), (0,255,0), 2)
Speed = Speed_Cal(time.time() - start_time)
print("ID Number "+str(i)+" Speed: " + str(int(Speed)))
i = i + 1
cv2.putText(img, "Speed: "+str(int(Speed))+"km/jam", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0), 2);
break
else :
break
out.write(img)
cv2.imshow('video', img)
cv2.imshow('Gray', gray)
cv2.imshow('Blurr', blurred)
if cv2.waitKey(33) == 27:
break
cap.release()
out.release()
cv2.destroyAllWindows()
I do really hope you can help me guys, please.
cv2.rectangle(img, (x,y), (x + w, y + h), (0, 0, 255), 2) the tuple with 3 elements: (0, 0, 255) is correspondent to the RGB (or BGR I forgot) value of the bounding rectangle, changing the values will change the color. For more information on bounding rectangles, check out the OpenCV drawing functions doc: https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html
As for the text color, cv2.putText(img, "Speed: "+str(int(Speed))+"km/jam", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0), 2), changing the tuple (255,0,0) will change the text color.
import time
start = time.time()
sec = 5
while True:
if condition:
start = time.time()
if time.time() - start < sec:
#do whatever
I am currently working on a project on human walking speed estimation by using Haar-cascade. The program works as such: the detected object passes two imaginary lines and when it passes the second line the program will show the speed. The currently program that I've worked only calculate the detected object that walks from above to the bottom, but I wanted the program will catch the calculation from below to the top too so it can calculating in both ways.
here's the program:
import cv2
import time
cascade_src = 'haarcascade_fullbody.xml'
video_src = 'video-1.mp4'
#line a
ax1=15
ay=225
ax2=600
#line b
bx1=15
by=275
bx2=600
#car num
i = 1
start_time = time.time()
#video ....
cap = cv2.VideoCapture(video_src)
human_cascade = cv2.CascadeClassifier(cascade_src)
videoWidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
videoHeight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('wisuda-14.mp4', fourcc, 25.0, (videoWidth,videoHeight))
def Speed_Cal(time):
try:
Speed = (9.144*3600)/(time*1000)
return Speed
except ZeroDivisionError:
print (5)
while True:
ret, img = cap.read()
if (type(img) == type(None)):
break
#bluring to have exacter detection
blurred = cv2.blur(img, ksize=(3,3))
gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
human = human_cascade.detectMultiScale(gray, scaleFactor=1.04865, minNeighbors=6)
#line a #i know road has got
cv2.line(img,(ax1,ay),(ax2,ay),(255,0,0),2)
#line b
cv2.line(img,(bx1,by),(bx2,by),(255,0,0),2)
for (x,y,w,h) in human:
cv2.rectangle(img, (x,y), (x + w, y + h), (0, 0, 255), 2)
roi_blurred = blurred[x: x + h, y:y + w]
roi_gray = gray[x: x + h, y:y + w]
roi_img = img[x: x + h, y:y + w]
cv2.circle(img,(int((x+x+w)/2),int((y+y+h)/2)), 2,(0,255,0), -1)
#cv2.putText(img, "ID : " + str(i), (x, y-15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1);
while int(ay) == int((y+y+h)/2):
start_time = time.time()
break
while int(ay) <= int((y+y+h)/2):
if int(by) <= int((y+y+h)/2)&int(by+10) >= int((y+y+h)/2):
cv2.line(img, (bx1,by), (bx2,by), (0,255,0), 2)
Speed = Speed_Cal(time.time() - start_time)
print("ID Number "+str(i)+" Speed: " + str(int(Speed)))
i = i + 1
cv2.putText(img, "Speed: "+str(int(Speed))+"km/jam", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0), 2);
break
else :
break
out.write(img)
cv2.imshow('video', img)
cv2.imshow('Gray', gray)
cv2.imshow('Blurr', blurred)
if cv2.waitKey(33) == 27:
break
cap.release()
out.release()
cv2.destroyAllWindows()
Hope you can help guys
I wish to alter this code in order to track a singular large object in motion, i.e. a person, when I run the code as is, the display will track a person as multiple objects rather than as one singular object.
Ignoring the firebase, I want to draw the rectangle around the entire object, rather than parts of the object.
Also, I wish to change the orientation of the lines set on the display from horizontal to vertical, please?
import datetime
import math
import cv2
import numpy as np
from firebase import firebase
# global variables
width = 0
height = 0
EntranceCounter = 0
ExitCounter = 0
min_area = 3000 # Adjust ths value according to your usage
_threshold = 70 # Adjust ths value according to your usage
OffsetRefLines = 150 # Adjust ths value according to your usage
# Check if an object in entering in monitored zone
def check_entrance_line_crossing(y, coor_y_entrance, coor_y_exit):
abs_distance = abs(y - coor_y_entrance)
if ((abs_distance <= 2) and (y < coor_y_exit)):
return 1
else:
return 0
# Check if an object in exitting from monitored zone
def check_exit_line_crossing(y, coor_y_entrance, coor_y_exit):
abs_distance = abs(y - coor_y_exit)
if ((abs_distance <= 2) and (y > coor_y_entrance)):
return 1
else:
return 0
camera = cv2.VideoCapture(0)
# force 640x480 webcam resolution
camera.set(3, 640)
camera.set(4, 480)
ReferenceFrame = None
# Frames may discard while adjusting to light
for i in range(0, 20):
(grabbed, Frame) = camera.read()
while True:
(grabbed, Frame) = camera.read()
height = np.size(Frame, 0)
width = np.size(Frame, 1)
# if cannot grab a frame, this program ends here.
if not grabbed:
break
# gray-scale and Gaussian blur filter applying
GrayFrame = cv2.cvtColor(Frame, cv2.COLOR_BGR2GRAY)
GrayFrame = cv2.GaussianBlur(GrayFrame, (21, 21), 0)
if ReferenceFrame is None:
ReferenceFrame = GrayFrame
continue
# Background subtraction and image manipulation
FrameDelta = cv2.absdiff(ReferenceFrame, GrayFrame)
FrameThresh = cv2.threshold(FrameDelta, _threshold, 255, cv2.THRESH_BINARY)[1]
# Dilate image and find all the contours
FrameThresh = cv2.dilate(FrameThresh, None, iterations=2)
_, cnts, _ = cv2.findContours(FrameThresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
qtty_of_count = 0
# plot reference lines (entrance and exit lines)
coor_y_entrance = (height // 2) - OffsetRefLines
coor_y_exit = (height // 2) + OffsetRefLines
cv2.line(Frame, (0, coor_y_entrance), (width, coor_y_entrance), (255, 0, 0), 2)
cv2.line(Frame, (0, coor_y_exit), (width, coor_y_exit), (0, 0, 255), 2)
# check all found count
for c in cnts:
# if a contour has small area, it'll be ignored
if cv2.contourArea(c) < min_area:
continue
qtty_of_count = qtty_of_count + 1
app = firebase.FirebaseApplication('https://finalyearproj-caa49.firebaseio.com/', None)
## result = app.post('/people', {'count': qtty_of_count})##
update = app.put('/people', "count", qtty_of_count)
print("Updated value in FB" + str(update))
# draw an rectangle "around" the object
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(Frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# find object's centroid
coor_x_centroid = (x + x + w) // 2
coor_y_centroid = (y + y + h) // 2
ObjectCentroid = (coor_x_centroid, coor_y_centroid)
cv2.circle(Frame, ObjectCentroid, 1, (0, 0, 0), 5)
if (check_entrance_line_crossing(coor_y_centroid, coor_y_entrance, coor_y_exit)):
EntranceCounter += 1
if (check_exit_line_crossing(coor_y_centroid, coor_y_entrance, coor_y_exit)):
ExitCounter += 1
print("Total countours found: " + str(qtty_of_count))
# Write entrance and exit counter values on frame and shows it
cv2.putText(Frame, "Entrances: {}".format(str(EntranceCounter)), (10, 50),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (250, 0, 1), 2)
cv2.putText(Frame, "Exits: {}".format(str(ExitCounter)), (10, 70),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.imshow("Original Frame", Frame)
cv2.waitKey(1)
# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()