Shishir
Shishir

Reputation: 11

Extracting particular Images from Video (using openCV etc)

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?

enter image description here

# 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

Answers (1)

Mark Setchell
Mark Setchell

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:

enter image description here

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:

enter image description here

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

enter image description here

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

Related Questions