pythonopencvgmm

Erase white pixels from an object moving at the border of the videoframe (GMM algorithm)


I am using the GMM-algorithm (BackgroundSubtractorMOG2) to find moving objects in a video. The output of this GMM-algorithm is a binary image with white pixels as the pixels that moved, and black pixels as background. I am looking for a way to ignore novel objects entering the field-of-view as long as they are not fully in the field-of-view. Here is an example picture I created: enter image description here

Here, all the white pixels represent moving pixels. The circles are fully in the field-of-view, while the 2 triangles are just about to enter the field-of-view.The left bottom triangle has nearly completely entered the field-of-view, but is still not 100% in the field-of-view. Therefore I still want the left bottom triangle to be completely erased from the frame. Does anyone know a method to deal with this problem?

Thank you


Solution

  • Try this one:

    import numpy as np
    import cv2
    
    
    def edge_filter(image):
        stats = cv2.connectedComponentsWithStats(image, connectivity=8)[2][1:]
        s_x, s_y, s_w, s_h = stats[:, 0], stats[:, 1], stats[:, 2], stats[:, 3]
        res_y, res_x = image.shape
        to_erase = stats[((res_x - s_w - s_x) * (res_y - s_h - s_y) * s_x * s_y) == 0]
        for stat in to_erase:
            x, y, w, h = stat[:4]
            image[y:y+h, x:x+w] = np.zeros((h, w)).astype(np.uint8)
    
    
    img_in = cv2.imread('bubbles.png',0)
    img_out = np.copy(img_in)
    
    edge_filter(img_out)
    
    cv2.imshow('input_image', img_in)
    cv2.imshow('output_image', img_out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    It works if the other polygons are not overlap the rectangle around the triangles.

    But, if you only need to keep the coordinate of the objects, what are not touching the edge, then the code is more simple.

    import numpy as np
    import cv2
    
    
    def edge_filter(stats):
        s_x, s_y, s_w, s_h = stats[:, 0], stats[:, 1], stats[:, 2], stats[:, 3]
        res_y, res_x = img.shape
        return stats[((res_x - s_w - s_x) * (res_y - s_h - s_y) * s_x * s_y) != 0]
    
    img = cv2.imread('bubbles.png',0)
    stats = cv2.connectedComponentsWithStats(img, connectivity=8)[2][1:]
    filtered_stats = edge_filter(stats)
    
    print('stats:\n', stats)
    print('filtered stats:\n', filtered_stats)
    

    output:

    stats:
    [[  627    61   169    61  8145]
     [  171   159    85    91  6053]
     [  309   385    41    25   807]
     [  585   385   221   129 22380]
     [    0   457    80   139  6488]
     [  482   599   225   121 13785]]
    filtered stats:
    [[  627    61   169    61  8145]
     [  171   159    85    91  6053]
     [  309   385    41    25   807]
     [  585   385   221   129 22380]]