I want to put a horizontal line in the centre of the screen and make counter of the people that are going up and going down. And how can i find out which side of the screen is the object coming from to make the right counter.
import cv2
import numpy as np
video = cv2.VideoCapture('videos/video.mp4')
bgsg = cv2.bgsegm.createBackgroundSubtractorMOG()
_,frame = video.read()
r = cv2.selectROI(frame)
lower_black = np.array([0, 0, 0], np.uint8)
upper_black = np.array([179, 100, 130], np.uint8)
while True:
_,frame = video.read()
im_cropped = frame[int(r[1]):int(r[1]+r[3]),
int(r[0]):int(r[0]+r[2])]
fgmask = bgsg.apply(im_cropped)
image = cv2.cvtColor(im_cropped,cv2.COLOR_BGR2HSV)
mask = cv2.inRange(image,lower_black,upper_black)
contours,hierarchy = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
if len(contours) != 0:
for contour in contours:
if cv2.contourArea(contour) > 400:
x,y,w,h = cv2.boundingRect(contour)
cv2.rectangle(im_cropped,(x,y),(x+w,y+h),(0,0,255),3)
cv2.imshow('frame',im_cropped)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video.release()
cv2.destroyAllWindows()
I couldnt find any method except for put a dot in the center of the detected objects and calculate the distance of the object from the line.
Related
I am trying to stack a individual frame to a video file using Opencv. I want to combine two different code together to make the individual frame.
Following code help me extract the individual frame,
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('file_data.mp4',fourcc,20 (1920,1080),False)
while True:
ret, frame=cap.read()
mask = object_detector.apply(frame)
_, mask = cv2.threshold(mask,254,255,cv2.THRESH_BINARY)
contours,_ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
res = cv2.bitwise_and(frame,frame,mask=mask)
for cnt in contours:
area = cv2.contourArea(cnt)
if area>1000:
#print("Area of contour:", area)
cv2.drawContours(frame, [cnt], -1, (0,255,0),2)
cv2.imwrite("file%d.jpg"%count, frame)
out.write(frame)
if cv2.waitKey(1) and 0xFF == ord('q'):
break
I tried storing the individual frame in array, but it didn't work. It doesn't show any error, but pc crash.
fps = 20,
,width = 1920
,height = 1080
Thanks to Rotem.
The issue has been solved using the VideoWriter from Opencv. The working code is given below.
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('file_data.mp4',fourcc,20,(1920,1080), True)
while True:
ret, frame=cap.read()
if ret == True:
# frame[frame<=thresholds]=0
mask = object_detector.apply(frame)
_, mask = cv2.threshold(mask,254,255,cv2.THRESH_BINARY)
contours,_ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
res = cv2.bitwise_and(frame,frame,mask=mask)
for cnt in contours:
area = cv2.contourArea(cnt)
if area>1000:
cv2.drawContours(frame, [cnt], -1, (0,255,0),2)
out.write(frame)
break
if cv2.waitKey(20) == ord('q'):
break
I have written a code to detect motion through a webcam but whenever I start the code, it works but it detects the entire full screen instead of objects moving in the screen. I noticed that if I close the camera it seems to remove the detection; Here is the code:
import cv2
first_frame = None
video = cv2.VideoCapture(0)
while True:
check, frame = video.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21,21),0)
if first_frame is None:
first_frame=gray
continue
delta_frame = cv2.absdiff(first_frame,gray)
thresh_frame = cv2.threshold(delta_frame, 30, 255, cv2.THRESH_BINARY)[1]
thresh_frame = cv2.dilate(thresh_frame,None, iterations=2)
(cnts,_) = cv2.findContours(thresh_frame.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in cnts:
if cv2.contourArea(contour) < 4000:
continue
(x,y, w, h)= cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h),(0,225,0),3)
cv2.imshow("Delta Frame",delta_frame)
cv2.imshow("Capturing",gray)
cv2.imshow("Threshold Frame",thresh_frame)
cv2.imshow("Color Frame",frame)
key = cv2.waitKey(5)
if key==ord('q'):
break
video.release()
cv2.destroyAllWindows()
The code should be able to detect only moving object in the screen.
I had similar issue a while back when I started with opencv; the problem with the program is the first frame, the first frame captured a dark screen. The difference detected by cv2.absdiff of the first frame(first_frame) vs the next frames(gray) was big enough that the cv2.findContours was indicated on the whole screen. This may be caused by camera delay
It can be solved by incorporating a slight delay between when the camera load to when the program records the first frame(first_frame) with time.sleep(). Try this:
import cv2, time
first_frame = None
video = cv2.VideoCapture(0)
# the camera has some lag time hence the starting of video.read outside loop and sleep
video.read()
time.sleep(2)
while True:
check, frame = video.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21,21),0)
if first_frame is None:
first_frame=gray
continue
delta_frame = cv2.absdiff(first_frame,gray)
thresh_frame = cv2.threshold(delta_frame, 30, 255, cv2.THRESH_BINARY)[1]
thresh_frame = cv2.dilate(thresh_frame,None, iterations=2)
(cnts,_) = cv2.findContours(thresh_frame.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in cnts:
if cv2.contourArea(contour) < 4000:
continue
(x,y, w, h)= cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h),(0,225,0),3)
cv2.imshow("Delta Frame",delta_frame)
cv2.imshow("Capturing",gray)
cv2.imshow("Threshold Frame",thresh_frame)
cv2.imshow("Color Frame",frame)
key = cv2.waitKey(5)
if key==ord('q'):
break
video.release()
cv2.destroyAllWindows()
time.sleep takes care of the lag time of the camera starting.
Try the code, it worked here
I have a code that gets a video from a folder and does some calculations using contours and background subtraction. After that I am going to save that edited video into the folder. The code is shown below:
import numpy as np
import cv2
import time
# Capture video from file
cap = cv2.VideoCapture('test_video.mp4')
time.sleep(1)
fgbg = cv2.createBackgroundSubtractorMOG2()
j = 0
fourcc = cv2.VideoWriter_fourcc(*'MPEG')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while (cap.isOpened()):
ret, frame = cap.read()
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
fgmask = fgbg.apply(gray)
_, contours, _ = cv2.findContours(fgmask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if contours:
areas = []
for contour in contours:
ar = cv2.contourArea(contour)
areas.append(ar)
max_area = max(areas or [0])
max_area_index = areas.index(max_area)
cnt = contours[max_area_index]
M = cv2.moments(cnt)
x, y, w, h = cv2.boundingRect(cnt)
cv2.drawContours(fgmask, [cnt], 0, (255,255,255), 3, maxLevel = 0)
if h < w:
j += 1
if j>10:
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)
if h > w:
j = 0
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('video',frame)
out.write(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
This opens up a window and plays a video, then output.avi is created, but it doesn't contain any content.
cmd produces nothing. I just can't able to save a file in a proper way.
Please recommend a solution to this issue
The error is telling you that frame does not have 3 or 4 channels.
Can you check that your camera is initialized properly
if not cap.isOpened():
print("Camera not initialized")
return
It is returning you a valid frame
if not ret:
print("Problem reading frame")
return
else:
# Convert your frame to gray and find contours etc.
I've been trying to store cropped images from as single frame to a list but i keep getting errors. Here's a snippet of my code
import cv2
import numpy as np
cap = cv2.VideoCapture('/home/wael-karkoub/Desktop/Research/Videos/test.mp4')
ret = True
cropped_images = []
while ret == True:
ret, frame = cap.read()
height, width, channels = frame.shape
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)
_ ,thresh = cv2.threshold(blur[0:height//2],10,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
im2, contours, hierarchy = cv2.findContours(thresh,1,2)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
image = frame[y:y+h, x:x+w]
cv2.imshow('test',image)
time.sleep(2)
# cv2.imshow('Contours',frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
cap.release()
cv2.destroyAllWindows()
Is this the correct way of doing it?
Output = enter image description here
If you want to store your cropped images to a list, you need some assignment going on. Just add cropped_images.append(image) somewhere in your code, most likely after image = frame[y:y+h, x:x+w]
I am trying to understand how to work with ROI, but the following code is not working as expected.
I have a white ball walking through a black background, and I want to detect and keep tracking of this ball. Unfortunately, the square does not move.I think the problem is the color array, but after trying many values, I still haven't found the correct solution.
import numpy as np
import cv2
cap = cv2.VideoCapture('oieee.avi')
ret,frame = cap.read()
r,h,c,w = 485,50,890,50
track_window = (c,r,w,h)
roi = frame[r:r+h, c:c+w]
hsv_roi = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array((0., 0., 240.)), np.array((255.,15.,255.)))
roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
while(1):
ret ,frame = cap.read()
if ret == True:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)
ret, track_window = cv2.meanShift(dst, track_window, term_crit)
x,y,w,h = track_window
cv2.rectangle(frame, (x,y), (x+w,y+h), 255,2)
img2 = cv2.rectangle(frame, (x,y), (x+w,y+h), 255,2)
cv2.imshow('img2',frame)
k = cv2.waitKey(60) & 0xff
if k == 27:
break
else:
cv2.imwrite(chr(k)+".jpg",img2)
else:
break
cv2.destroyAllWindows()
cap.release()
A print screen of my video http://imgur.com/VG3TgFF