Search code examples
pythonimageopencvimage-processingpython-imaging-library

Removing Borders/Margins from Video Frames


I am working with videos, that have borders (margins) around them. Some have it along all 4 sides, some along left&right only and some along top&bottom only. Length of these margins is also not fixed. I am extracting frames from these videos, as for example,

enter image description here

and

enter image description here

Both of these contain borders on the top and bottom.

Can anyone please suggest some methods to remove these borders from these images (in Python, preferably). I came across some methods, like this on Stackoverflow, but this deals with an ideal situation where borders are perfectly black (0,0,0). But in my case, they may not be pitch black, and also may contain jittery noises too. Any help/suggestions would be highly appreciated.


Solution

  • Here is one way to do that in Python/OpenCV.

    • Read the image
    • Convert to grayscale and invert
    • Threshold
    • Apply morphology to remove small black or white regions then invert again
    • Get the contour of the one region
    • Get the bounding box of that contour
    • Use numpy slicing to crop that area of the image to form the resulting image
    • Save the resulting image


    import cv2
    import numpy as np
    
    # read image
    img = cv2.imread('gymnast.png')
    
    # convert to grayscale
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    
    # invert gray image
    gray = 255 - gray
    
    # gaussian blur
    blur = cv2.GaussianBlur(gray, (3,3), 0)
    
    # threshold
    thresh = cv2.threshold(blur,236,255,cv2.THRESH_BINARY)[1]
    
    # apply close and open morphology to fill tiny black and white holes
    kernel = np.ones((5,5), np.uint8)
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
    
    # invert thresh
    thresh = 255 -thresh
    
    # get contours (presumably just one around the nonzero pixels) 
    # then crop it to bounding rectangle
    contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    cntr = contours[0]
    x,y,w,h = cv2.boundingRect(cntr)
    crop = img[y:y+h, x:x+w]
    
    cv2.imshow("IMAGE", img)
    cv2.imshow("THRESH", thresh)
    cv2.imshow("CROP", crop)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    # save cropped image
    cv2.imwrite('gymnast_crop.png',crop)
    cv2.imwrite('gymnast_crop.png',crop)
    


    Input:

    enter image description here


    Thresholded and cleaned image:

    enter image description here

    Cropped Result:

    enter image description here