Opencv Rstp Frame Very Slow When I start recording - python

Before the rstp ip camera I didnt faced with this problem.
Firstly I show downcounting(3-2-1-GO!) to user and than I start recording in only 10 seconds. After that record fnished and show the Fnished. But when I start using RSTP camera, I have time lag in record moments how can I solve this ? But in the webcam I dont have this problem.
Process:
DownCount 3-2-1-GO!
Start Recording in 10 second --I have problem this step, video record have time lag.
Show Fnished Text
This is source code
class MainRecord():
def __init__(self, rfidCode):
TIMER = int(3)
TIMER_RECORD = int(10)
self.rfidCode = rfidCode
print(self.rfidCode)
user_id = str(self.rfidCode) # this id will get from RFID
# user_id = "a1"
# test = 'fourth'q
# cap = cv2.VideoCapture(0)
# cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
# cap.set(cv2.CAP_PROP_POS_AVI_RATIO, 1)
cap = cv2.VideoCapture('rtsp://private:private#192.168.1.64/1')
# segmentor = SelfiSegmentation()
filename = user_id +'.avi' #.avi .mp4
frames_per_seconds = 24 #this is the standart for the movie or films
config = CFEVideoConf(cap, filepath = filename, res='1080p')
out = cv2.VideoWriter(filename, config.video_type, frames_per_seconds,config.dims)
img_path = 'ap_logo.png'
logo = cv2.imread(img_path,-1)
watermark = image_resize(logo, height=60)
watermark = cv2.cvtColor(watermark, cv2.COLOR_BGR2BGRA)
#grayscale watermark
# cv2.imshow('watermark',watermark)
# time.sleep(2)
font = cv2.FONT_HERSHEY_SIMPLEX
ret, readBefore = cap.read()
cv2.imshow('Start', readBefore)
while(True):
prev = time.time()
while TIMER >= 0:
ret, img = cap.read()
print("showing")
# Display countdown on each frame
# specify the font and draw the
# countdown using puttext
if TIMER != 0:
cv2.putText(img, str(TIMER),
(560, 250), font,
7, (0, 255, 255),
4, cv2.LINE_AA)
cv2.imshow('Start', img)
else:
cv2.putText(img, str("GO!"),
(580, 250), font,
7, (0, 255, 255),
4, cv2.LINE_AA)
cv2.imshow('Start', img)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
# current time
cur = time.time()
# Update and keep track of Countdown
# if time elapsed is one second
# than decrease the counter
if cur - prev >= 1:
prev = cur
TIMER = TIMER - 1
if TIMER == -1:
cv2.destroyAllWindows()
while TIMER_RECORD >= 0: #problem occurs here !!
ret, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
frame_h,frame_w, frame_c = frame.shape
#overlay with 4 channel BGR and Alpha
overlay = np.zeros((frame_h, frame_w,4), dtype='uint8')
# overlay[100:250, 100:125] = (255,255,0,1) #B,G,R,A
# overlay[100:250, 150:255] = (0,255,0,1)
watermark_h, watermark_w, watermark_c = watermark.shape
for i in range(0, watermark_h):
for j in range(0, watermark_w):
if watermark[i,j][3] != 0:
h_offset = frame_h - watermark_h
w_offset = frame_w - watermark_w
overlay[h_offset+i,w_offset+j] = watermark[i,j]
cv2.addWeighted(overlay, 0.25, frame, 1.0, 0, frame)
#Display the resulting frame
frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
cv2.imshow('Frame', frame)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
out.write(frame) #file a ilgili frame yazılıyor
cur = time.time()
# Update and keep track of Countdown
# if time elapsed is one second
# than decrease the counter
if cur - prev >= 1:
prev = cur
TIMER_RECORD = TIMER_RECORD - 1
print(TIMER_RECORD)
if TIMER_RECORD == -1:
cv2.destroyAllWindows()
# if cv2.waitKey(20) & 0xFF == ord('q'):
# break
else:
ret, finishImg = cap.read()
cv2.putText(finishImg, str("FINISH !"),
(150, 250), font,
7, (0, 255, 255),
4, cv2.LINE_AA)
cv2.imshow('Finished', finishImg)
# cv2.destroyAllWindows()
if cv2.waitKey(20) & 0xFF == ord('q'):
break
# break
# if cv2.waitKey(20) & 0xFF == ord('q'):
# break
#When everything done, relase the capture
cap.release()
out.release()
# saved
cv2.destroyAllWindows()
# self.ui.show()
In the while TIMER_RECORD >= 0: loop showing video is very slow but before and after everything is perfect. How can I solve this problem ?

Related

cv2 module capturing frame from video every 5 seconds

I have been trying to capture a frame(screenshot) after every 5 seconds from a live .webm video stream which is constantly increasing in duration.
import cv2
import time
TIMER = int(5)
k=0
cap = cv2.VideoCapture('video.webm')
capture=int(1)
while True:
ret, img = cap.read()
cv2.imshow('a', img)
if ret:
prev = time.time()
while TIMER >= 0:
ret, img = cap.read()
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, str(TIMER),
(200, 250), font,
7, (0, 255, 255),
4, cv2.LINE_AA)
cv2.imshow('a', img)
cv2.waitKey(125)
cur = time.time()
if cur-prev >= 1:
prev = cur
TIMER = TIMER-1
if TIMER == 0:
ret, img = cap.read()
cv2.imshow('a', img)
cv2.waitKey(2000)
cv2.imwrite('camera' + str(capture) + '.jpg', img)
capture=capture+1
TIMER = int(5)
else:
break
cap.release()
cv2.destroyAllWindows()
Here my code captures the frame after every 5 frames, I'm not able to figure out the framerate calculation and making it work to capture frames after every 5 seconds rather than 5 frames.
If you want to utilize the fps information of the video an approach might be:
import cv2
cap = cv2.VideoCapture(r'path/to/vid')
fps = int(cap.get(cv2.CAP_PROP_FPS))
save_interval = 5
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if ret:
frame_count += 1
if frame_count % (fps * save_interval) == 0:
cv2.imwrite(r'path/to/save/to')
# optional
frame_count = 0
# Break the loop
else:
break
cap.release()
cv2.destroyAllWindows()

OpenCV object detecting and save videofile

I want to object detect and save the video, but the video saved only 6kb or 0kb and it can't be play
If there is no this line
x, y, width, height, area = stats[index]
it will be saved
Do you know why And is there a solution?
import cv2
import time
import numpy as np
cap = cv2.VideoCapture("rtsp://admin:admin#128.1.1.110:554")
width = int(cap.get(3))
height = int(cap.get(4))
fcc = cv2.VideoWriter_fourcc(*'XVID')
recording = False
fgbg = cv2.createBackgroundSubtractorMOG2(varThreshold=200, detectShadows=0)
while(1):
ret, frame = cap.read()
hms = time.strftime('%H_%M_%S', time.localtime())
fgmask = fgbg.apply(frame)
nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(fgmask)
for index, centroid in enumerate(centroids):
if stats[index][0] == 0 and stats[index][1] == 0:
continue
if np.any(np.isnan(centroid)):
continue
x, y, width, height, area = stats[index]
centerX, centerY = int(centroid[0]), int(centroid[1])
if area > 200:
cv2.circle(frame, (centerX, centerY), 1, (0, 255, 0), 2)
cv2.rectangle(frame, (x, y), (x + width, y + height), (0, 0, 255))
cv2.putText(frame, str(area), (centerX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255))
cv2.imshow('frame', frame)
k = cv2.waitKey(1) & 0xff
if k == ord('r') and recording is False:
path = 'test_' + str(hms) + '.avi'
print('recording start')
writer = cv2.VideoWriter(path, fcc, 30.0, (width, height))
recording = True
if recording:
writer.write(frame)
if k == ord('e'):
print('recording end')
recording = False
writer.release()
cap.release()
cv2.destroyAllWindows()
I think this will solve your problem
# importing the module
import cv2
import numpy as np
# reading the vedio
source = cv2.VideoCapture(0) // add your URL insed of "0"
# We need to set resolutions.
# so, convert them from float to integer.
frame_width = int(source.get(3))
frame_height = int(source.get(4))
recording = False
fcc = cv2.VideoWriter_fourcc(*'XVID')
size = (frame_width, frame_height)
fgbg = cv2.createBackgroundSubtractorMOG2(varThreshold=200, detectShadows=0)
result = cv2.VideoWriter('output.avi', fcc, 30, size)
# running the loop
while True:
# extracting the frames
ret, frame = source.read()
fgmask = fgbg.apply(frame)
nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(fgmask)
for index, centroid in enumerate(centroids):
if stats[index][0] == 0 and stats[index][1] == 0:
continue
if np.any(np.isnan(centroid)):
continue
x, y, width, height, area = stats[index]
centerX, centerY = int(centroid[0]), int(centroid[1])
if area > 200:
cv2.circle(frame, (centerX, centerY), 1, (0, 255, 0), 2)
cv2.rectangle(frame, (x, y), (x + width, y + height), (0, 0, 255))
cv2.putText(frame, str(area), (centerX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255))
# displaying the video
cv2.imshow("Live", frame)
k = cv2.waitKey(1) & 0xff
if k == ord('r') and recording is False:
print('recording start')
recording = True
if recording:
result.write(frame)
if k == ord('e'):
print('recording end')
recording = False
result.release()
# closing the window
cv2.destroyAllWindows()
source.release()
But unfortunately, I can not hms with the output file name.
That can try your self
If helpful this for you give 👍
Actually, you need to delete some codes.
cv2.imshow('MultiTracker', frame)
# quit on ESC button
if cv2.waitKey(1) & 0xFF == 27: # Esc pressed
break
# k = cv2.waitKey(1) & 0xff
#if k == ord('r') and recording is False:
# print('recording start')
# recording = True
#if recording:
result.write(frame)
#if k == ord('e'):
# print('recording end')
# recording = False
# result.release()
result.release()
cv2.destroyAllWindows()
cap.release()
it works for me, the reason why it is 6kb is you start write but not append frame to output avi file.

How to get last processed frame from video using opencv?

I want to extract last frame of video that have been processed before with Motion History Image (MHI) and I want to save last image processed by MHI.
Here is my code:
import numpy as np
import cv2
MHI_DURATION = 35
DEFAULT_THRESHOLD = 30
def main():
live_video = False
video_src = 1
if not live_video:
video_src = "data/vid1.mp4"
cv2.namedWindow('motion-history')
cv2.namedWindow('raw')
cv2.moveWindow('raw', 200, 0)
cam = cv2.VideoCapture(video_src)
ret, frame = cam.read()
h, w = frame.shape[:2]
prev_frame = frame.copy()
motion_history = np.zeros((h, w), np.float32)
timestamp = 0
while True:
ret, frame = cam.read()
if not ret:
break
frame_diff = cv2.absdiff(frame, prev_frame)
gray_diff = cv2.cvtColor(frame_diff, cv2.COLOR_BGR2GRAY)
ret, fgmask = cv2.threshold(gray_diff, DEFAULT_THRESHOLD, 1, cv2.THRESH_BINARY)
timestamp += 1
# update motion history
cv2.motempl.updateMotionHistory(fgmask, motion_history, timestamp, MHI_DURATION)
# normalize motion history
mh = np.uint8(np.clip((motion_history - (timestamp - MHI_DURATION)) / MHI_DURATION, 0, 1) * 255)
cv2.imshow('motion-history', mh)
# cv2.imshow('raw', frame)
prev_frame = frame.copy()
if 0xFF & cv2.waitKey(5) == 27:
break
cv2.destroyAllWindows()
And, can we process faster without loop through all frame in the video?

Using timer to capture webcam images

How do I get breaks during the image capture? In fact, I need 5sec in between the image.
This code captures around 15-20 images per sec, But I need to take a picture at an interval of 5sec in between images
import cv2
import time
import numpy
capture = cv2.VideoCapture(0)
capture.set(3,640)
capture.set(4,480)
img_counter = 0
frame_set = []
start_time = time.time()
while(True):
ret , frame = capture.read()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
frame_set.append(gray)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
end_time = time.time()
elapsed = end_time - start_time
img_name = "opencv_frame_{}.png".format(img_counter)
cv2.imwrite(img_name,frame)
print("{} written!".format(img_counter))
img_counter +=1
if elapsed > 1:
capture.release()
cv2.destroyAllWindows()
time.sleep(3)
You need an if statement to check if the desired time has passed. Using the already imported time package you can do this:
import cv2
import time
capture = cv2.VideoCapture(0)
capture.set(3, 640)
capture.set(4, 480)
img_counter = 0
frame_set = []
start_time = time.time()
while True:
ret, frame = capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if time.time() - start_time >= 5: #<---- Check if 5 sec passed
img_name = "opencv_frame_{}.png".format(img_counter)
cv2.imwrite(img_name, frame)
print("{} written!".format(img_counter))
start_time = time.time()
img_counter += 1
The above script will save the frame in RGB every 5 seconds to the working directory.

(cv2,capture) object is not callable

Basically, this code will detect object's motion in the scene. When the motion is detected, a red rectangle frame will track the object's motion. But, I added a new function into the code which is frame differencing. In general it is thresholding. When i run the code it says:"cv2.capture" object is not callable.
import cv2.cv as cv
class Target:
def __init__(self):
self.capture = cv.CaptureFromCAM(0)
cv.NamedWindow("Target", 1)
def run(self):
# Capture first frame to get size
ret, current_frame = self.capture()
previous_frame = current_frame
frame = cv.QueryFrame(self.capture)
frame_size = cv.GetSize(frame)
color_image = cv.CreateImage(cv.GetSize(frame), 8, 3)
grey_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1)
moving_average = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_32F, 3)
first = True
while True:
current_frame_gray = cv2.cvtColor(current_frame,cv2.COLOR_BGR2GRAY)
previous_frame_gray = cv2.cvtColor(previous_frame, cv2.COLOR_BGR2GRAY)
frame_diff = cv2.absdiff(current_frame_gray,previous_frame_gray)
closest_to_left = cv.GetSize(frame)[0]
closest_to_right = cv.GetSize(frame)[1]
color_image = cv.QueryFrame(self.capture)
# Smooth to get rid of false positives
cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 3, 0)
if first:
difference = cv.CloneImage(color_image)
temp = cv.CloneImage(color_image)
cv.ConvertScale(color_image, moving_average, 1.0, 0.0)
first = False
else:
cv.RunningAvg(color_image, moving_average, 0.020, None)
# Convert the scale of the moving average.
cv.ConvertScale(moving_average, temp, 1.0, 0.0)
# Minus the current frame from the moving average.
cv.AbsDiff(color_image, temp, difference)
# Convert the image to grayscale.
cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY)
# Convert the image to black and white.
cv.Threshold(grey_image, grey_image, 70, 255, cv.CV_THRESH_BINARY)
# Dilate and erode to get people blobs
cv.Dilate(grey_image, grey_image, None, 18)
cv.Erode(grey_image, grey_image, None, 10)
storage = cv.CreateMemStorage(0)
contour = cv.FindContours(grey_image, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE)
points = []
while contour:
bound_rect = cv.BoundingRect(list(contour))
contour = contour.h_next()
pt1 = (bound_rect[0], bound_rect[1])
pt2 = (bound_rect[0] + bound_rect[2], bound_rect[1] + bound_rect[3])
points.append(pt1)
points.append(pt2)
cv.Rectangle(color_image, pt1, pt2, cv.CV_RGB(255,0,0), 1)
cv.ShowImage("Target", color_image)
cv.ShowImage("frame_diff", frame_diff)
# Listen for ESC key
c = cv.WaitKey(7) % 0x100
if c == 27:
break
if __name__=="__main__":
t = Target()
t.run()
This is the original frame differencing code that I wanted transfer from:
import cv2
cap = cv2.VideoCapture(0)
ret, current_frame = cap.read()
previous_frame = current_frame
while(cap.isOpened()):
current_frame_gray = cv2.cvtColor(current_frame, cv2.COLOR_BGR2GRAY)
previous_frame_gray = cv2.cvtColor(previous_frame, cv2.COLOR_BGR2GRAY)
frame_diff = cv2.absdiff(current_frame_gray,previous_frame_gray)
cv2.imshow('frame diff ',frame_diff)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
previous_frame = current_frame.copy()
ret, current_frame = cap.read()
cap.release()
cv2.destroyAllWindows()
You can't call the capture object, but you can read from it by calling its read method. Changing your frame return code to:
ret, current_frame = self.capture.read()
Should fix this.
Edit:
The two lines:
ret, current_frame = self.capture.read()
previous_frame = current_frame
Will work for VideoCapture but not CaptureFromCAM. You apparently don't need them since you can take a frame by doing:
frame = cv.QueryFrame(self.capture)

Categories