Reputation: 11
I have multiple conference video (.mp4) wherein the speakers are presenting a slide show and slides are changing randomly (depending on how much speaker wants to comment on it). I want to extract only the slides from the video.
EDIT: Able to extract the slides, now there are lot of redundant frames being captured, example in the image. How to avoid them?
# Importing all necessary libraries
import cv2
import os
# Read the video from specified path
cam = cv2.VideoCapture("C:\\Users\\zoomrx\\Desktop\\Video\\1.mp4")
try:
# creating a folder named data
if not os.path.exists('data_org'):
os.makedirs('data_org')
# if not created then raise error
except OSError:
print ('Error: Creating directory of data')
# frame
currentframe = 0
while(True):
# reading from frame
ret,frame = cam.read()
roi = frame[166:959,24:1433]
if ret:
# if video is still left continue creating images
name = './data/frame' + str(currentframe) + '.jpg'
print ('Creating...' + name)
# writing the extracted images
cv2.imwrite(name, roi)
# increasing counter so that it will
# show how many frames are created
currentframe += 1
else:
break
if cv2.waitKey(1) & 0xFF==27:
break
# Release all space and windows once done
cam.release()
cv2.destroyAllWindows()
Upvotes: 0
Views: 599
Reputation: 207455
I think it is much simpler to do cropping and scene change detection with ffmpeg
, so I made a test video like this:
ffmpeg -hide_banner -y -f lavfi -i testsrc=duration=10:size=640x480:rate=25 -pix_fmt yuv420p video.mov
That is too big to upload to StackOverflow, so it looks like this as an animated GIF with reduced size, quality and frame rate:
Then, I crop out the counter and do scene-change detection within the cropped area:
ffmpeg -y -i video.mov -vf "crop=80:120:500:180, select=gt(scene\,0.001)" -vsync 0 -pix_fmt yuv420p cropped.mov
That looks like this, again as a reduced size/quality animated GIF:
Note that the format of the crop
filter is:
crop=WIDTH:HEIGHT:X-COORDINATE:Y-COORDINATE
Then I can do more or less exactly what you want and output PNG images of each slide:
ffmpeg -y -i video.mov -vf "crop=80:120:500:180, select=gt(scene\,0.001)" -vsync 0 slides-%03d.png
Which gives me this:
-rw-r--r--@ 1 mark staff 455 7 Oct 11:59 slides-001.png
-rw-r--r--@ 1 mark staff 466 7 Oct 11:59 slides-002.png
-rw-r--r--@ 1 mark staff 487 7 Oct 11:59 slides-003.png
-rw-r--r--@ 1 mark staff 434 7 Oct 11:59 slides-004.png
-rw-r--r--@ 1 mark staff 473 7 Oct 11:59 slides-005.png
-rw-r--r--@ 1 mark staff 456 7 Oct 11:59 slides-006.png
-rw-r--r--@ 1 mark staff 459 7 Oct 11:59 slides-007.png
-rw-r--r--@ 1 mark staff 441 7 Oct 11:59 slides-008.png
-rw-r--r--@ 1 mark staff 464 7 Oct 11:59 slides-009.png
If you wanted to only look at one slide per second, to avoid transition frames, you could use:
ffmpeg -r 1 ...
Additionally, you could increase the 0.001 threshold so the frames need to be more different before a transition is detected.
Upvotes: 1