NumPy slice into a variable?

Question:

DISCLAIMER: I’m a total noob at programming

Currently extracting frames from a video to be processed later on. I have different areas of the video frames that I want to process so I need to be able to pass a numpy slice into a variable to be used as the function’s argument. What’s the syntax for that?

frame[5:49, 879:938] is the slice that I would like to use in a variable to be passed as the 3rd argument of the extractFrames function.

Here’s my code:

def extractFrames(video_file, folder):
    try:
        os.mkdir(folder)
    except:
        shutil.rmtree(folder)
        os.mkdir(folder)
    capture = cv2.VideoCapture(video_file)
    count = 0
    while (capture.isOpened()):
        # Capture frame-by-frame
        ret, frame = capture.read()
        if ret == True:
            print('Read %d frame: ' % count, ret)
            cv2.imwrite(os.path.join(folder, "{:d}.jpg".format(count)), frame[5:49, 879:938])  # save frame as JPEG file
            count += 1
        else:
            break
    # When everything done, release the capture
    capture.release()
    cv2.destroyAllWindows()

Thank you so much for your time and consideration.

Asked By: c0nfluks

||

Answers:

When you say frame[5:49, 879:938] you are indexing into frame using a pair of slices. The slice type is built in to Python, and you can pass two of them to your function like this:

extractFrames("filename", "folder", x=slice(5, 49), y=slice(879, 938))

Defining your function like this:

def extractFrames(video_file, folder, x=slice(None), y=slice(None)):
    ...frame[x_slice, y_slice]...

The default arguments will take the whole frame…you can omit them if you want the slicing to be mandatory.

Answered By: John Zwinck

You don’t need to construct slice objects and pass those around.

You can just pass the bounds around:

def extractFrames(..., bounds):
    (y0, y1, x0, x1) = bounds
    ...
    subregion = frame[y0:y1, x0:x1]
    ....

extractFrames(..., (5, 49, 879, 938))

This also allows you to pass None for any bounds, so the slice becomes an "all-slice".

Or pass (x, y, w, h)-style numbers, if you have those anyway, and then slice [y:y+h, x:x+w].

Answered By: Christoph Rackwitz