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?
Related
I have a logo and I am trying to put this logo into my video. When I add the logo with below codes, logo couldnt be original color, it shows transparent. But I dont want to transparency I need to put original color format.
I get this output:
This is my code:
img_path = 'ap_logo.png'
logo = cv2.imread(img_path,cv2.IMREAD_UNCHANGED)
#
#
watermark = image_resize(logo, height=300)
watermark = cv2.cvtColor(watermark, cv2.COLOR_BGR2BGRA)
watermark_h, watermark_w, watermark_c = watermark.shape
ret, frame = cap.read()
frame = cv2.flip(frame, 1)
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
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')
for i in range(0, watermark_h):
print(i)
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]
while(True):
ret, frame = cap.read()
frame = cv2.flip(frame, 1)
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
cv2.addWeighted(overlay, 0.25, frame, 1.0, 0, frame)
# Display the resulting frame
frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
if ret:
cv2.imshow('Frame', frame)
out.write(frame) # file a ilgili frame yazılıyor
if cv2.waitKey(1) & 0xFF == ord('q'):
break
#When everything done, relase the capture
cap.release()
out.release() # saved
cv2.destroyAllWindows()
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()
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.
import numpy as np
import cv2
cap = cv2.VideoCapture('car.avi')
size = (int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)))
fourcc = cv2.cv.CV_FOURCC(*'AVID')
video = cv2.VideoWriter('6.avi', fourcc, 25, size)
while(1):
ret, frame = cap.read()
if not ret:
break
frame = cv2.convertScaleAbs(frame)
params = cv2.SimpleBlobDetector_Params()
params.blobColor = 0
params.filterByColor = True
params.minArea = 0
params.filterByArea = False
params.minThreshold = 120;
params.maxThreshold = 255;
detector = cv2.SimpleBlobDetector(params)
keypoints = detector.detect(frame)
im_with_keypoints = cv2.drawKeypoints(frame, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
if ret == True:
video.write(im_with_keypoints)
cv2.imshow('frame', im_with_keypoints)
else:
cap.release()
video.release()
break
k = cv2.waitKey(10) & 0xff
if k == 27:
break
I modified the code you have, and now it can run. I used python3.5.
import numpy as np
import cv2
cap = cv2.VideoCapture(r'E:/test.mp4')
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
video = cv2.VideoWriter(r'E:/6.avi', fourcc, 25, size)
while(1):
ret, frame = cap.read()
if not ret:
break
frame = cv2.convertScaleAbs(frame)
params = cv2.SimpleBlobDetector_Params()
params.blobColor = 0
params.filterByColor = True
params.minArea = 0
params.filterByArea = False
params.minThreshold = 120;
params.maxThreshold = 255;
ver = (cv2.__version__).split('.')
if int(ver[0]) < 3:
detector = cv2.SimpleBlobDetector(params)
else:
detector = cv2.SimpleBlobDetector_create(params)
keypoints = detector.detect(frame)
im_with_keypoints = cv2.drawKeypoints(frame, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
if ret == True:
video.write(im_with_keypoints)
cv2.imshow('frame', im_with_keypoints)
else:
cap.release()
break
k = cv2.waitKey(10) & 0xff
if k == 27:
break
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)