0

this code works great in order to substract moving objects. The input is an mp4 video and the output is the background without any moving object. The problem is, this code is calculating the MEDIAN of every pixel. Is there any way to calculate the mode?

import numpy as np
import cv2 as cv
file_path = 'videoprueba2.mp4' ## THIS IS THE INPUT VIDEO
video = cv.VideoCapture(file_path) 
FOI = video.get(cv.CAP_PROP_FRAME_COUNT) * np.random.uniform(size=30)
frames = []
for frameOI in FOI:
    video.set(cv.CAP_PROP_POS_FRAMES, frameOI)
    ret, frame = video.read()
    frames.append(frame)
result2 = np.median(frames, axis=0).astype(dtype=np.uint8) #HERE IT CALCULATES THE MEDIAN OF EVERY PIXEL IN THE FRAME
cv.imwrite('prueba3Metodo2.png',result2) #THIS IS THE FINAL PICTURE
JN1997
  • 119
  • 7
  • It doesn't exist out of the box in numpy (yet). Write a function to obtain the mode by referring to a thread like this one: https://stackoverflow.com/questions/16330831/most-efficient-way-to-find-mode-in-numpy-array – Hari Sep 20 '22 at 18:31
  • I tried to copy that but did not work. I can not understand how to change the argument if I use stats – JN1997 Sep 22 '22 at 16:15

1 Answers1

0

If your data contains only non-negative int numbers use np.bincount like this:

result2 = np.apply_along_axis(lambda x: np.bincount(x).argmax(), axis=0, arr=frames)

Also you can use scipy.stats.mode as it allows negative and float values but it is much slower. For example for a video with resolution 1280x720 and 30 frames:

scipy.stats.mode took 30.892 seconds
np.bincount took 5.950 seconds
u1234x1234
  • 2,062
  • 1
  • 1
  • 8
  • I tried using np.apply_along_axis(lambda x: np.bincount(x).argmax(), axis=0, arr=frames) but it did not work as expected :( . I tried it with many videos and the output image has many rare dots with colours on it. I am trying to use scipy.stats.mode but I can not understand how to write the code, the argument should change right? – JN1997 Sep 22 '22 at 15:41