Motion object detection is generally divided into two steps: background modeling and motion object analysis. That is, a background model without moving objects is constructed. Then new video frames are compared with the background model to find out the moving objects in them. There are two better background modeling algorithms: 1) Article (Zivkovic Z. (2004) Improved adaptive Gausianmixture model for backgroundsubtraction, Proceedings of ICPR 2004, August 23-26 , Cambridge, UK.) proposes a Gaussian mixture modeling method. In this algorithm, each pixel of the background is fitted to a Gaussian mixture model. For a new image, it is only necessary to determine whether each pixel obeys this Gaussian mixture model to determine whether the pixel is background or foreground. However, the disadvantages of the hybrid Gaussian algorithm are that it is relatively computationally intensive, slow and sensitive to light.2) The ViBe algorithm proposed in the article (ViBe: A universal backgroundsubtraction algorithm for video sequences.). The algorithm is very fast, the computation is relatively small, and it is robust to noise and has a good detection effect.
As I was doing some research on tracking checks recently, I used the ViBe algorithm, and wrote this python version of the algorithm based on the c++ version available on the web, which I'm sharing here.
class ViBe: ''''' classdocs ''' __defaultNbSamples = 20 # of samples per pixel point __defaultReqMatches = 2 #min index __defaultRadius = 20; #Sqthere radius __defaultSubsamplingFactor = 16# Sub-sampling probability __BG = 0 # background pixels __FG = 255 # foreground pixels __c_xoff=[-1,0,1,-1,1,-1,0,1,0] Neighborhood points of #x len=9 __c_yoff=[-1,0,1,-1,1,-1,0,1,0] Neighborhood points of #y len=9 __samples=[] # Save the sample value of each pixel point, len defaultNbSamples+1 __Height = 0 __Width = 0 def __init__(self, grayFrame): ''''' Constructor ''' self.__Height = [0] self.__Width = [1] for i in range(self.__defaultNbSamples+1): self.__samples.insert(i,(([0],[1]),dtype=)); self.__init_params(grayFrame) def __init_params(self,grayFrame): # Record randomly generated rows (r) and columns (c) rand=0 r=0 c=0 # Initialize each pixel sample for y in range(self.__Height): for x in range(self.__Width): for k in range(self.__defaultNbSamples): # Randomize pixel sample values rand=(0,8) r=y+self.__c_yoff[rand] if r<0: r=0 if r>=self.__Height: r=self.__Height-1 # rows c=x+self.__c_xoff[rand] if c<0: c=0 if c>=self.__Width: c=self.__Width-1 # columns # Store pixel sample values self.__samples[k][y,x] = grayFrame[r,c] self.__samples[self.__defaultNbSamples][y,x] = 0 def update(self,grayFrame,frameNo): foreground = ((self.__Height,self.__Width),dtype=np.uint8) for y in range(self.__Height): #Height for x in range(self.__Width): #Width # Used to determine whether a point is a background point, index records the number of samples that have been compared, count indicates the number of matching samples. count=0;index=0; dist=0.0; while (count<self.__defaultReqMatches) and (index<self.__defaultNbSamples): dist= float(grayFrame[y,x]) - float(self.__samples[index][y,x]); if dist<0: dist=-dist if dist<self.__defaultRadius: count = count+1 index = index+1 if count>=self.__defaultReqMatches: # Judged as background pixels, only background points can be used to propagate and update stored sample values self.__samples[self.__defaultNbSamples][y,x]=0 foreground[y,x] = self.__BG rand=(0,self.__defaultSubsamplingFactor) if rand==0: rand=(0,self.__defaultNbSamples) self.__samples[rand][y,x]=grayFrame[y,x] rand=(0,self.__defaultSubsamplingFactor) if rand==0: rand=(0,8) yN=y+self.__c_yoff[rand] if yN<0: yN=0 if yN>=self.__Height: yN=self.__Height-1 rand=(0,8) xN=x+self.__c_xoff[rand] if xN<0: xN=0 if xN>=self.__Width: xN=self.__Width-1 rand=(0,self.__defaultNbSamples) self.__samples[rand][yN,xN]=grayFrame[y,x] else: # Judged as foreground pixels foreground[y,x] = self.__FG; self.__samples[self.__defaultNbSamples][y,x] += 1 if self.__samples[self.__defaultNbSamples][y,x]>50: rand=(0,self.__defaultNbSamples) if rand==0: rand=(0,self.__defaultNbSamples) self.__samples[rand][y,x]=grayFrame[y,x] return foreground
A tracking effect of the fish I made
This is the whole content of this article.