What I did when I couldn't find the feature point with the optical flow of opencv and when I lost it

What I did when I couldn't find the feature point with the optical flow of opencv and when I lost it

We will proceed with the following contents --When using optical flow ――Problems in using 1 I can't find the feature points where I want --Solution 1 --Problems in using 2 Lost if you move fast

Images etc. are included in it

On using optical flow

Optical flow is a technology that detects and tracks characteristic parts of an image. It's a very useful technology, but when you try it, you face various problems. Here I will write that it was a little troublesome for me to use. In particular, we will introduce how to find the feature points and what to do if you lose them.

Problems in using 1

I can't get a feature point where I want it

If there is a characteristic place because it is a method of finding a characteristic part in the image, the place you really want may not be characterized. One example is strong lighting.

solution

Let the person first specify the location of the feature point and follow it. For example, if you cut out a part of the image like the following source code and detect the feature points of the image, it will look good. An example algorithm is shown below.

  1. Display only the first frame of the video and specify the range where you want the feature points.
  2. Detect feature points within the specified range.
  3. Calculate the coordinates of the center of gravity of the detected feature point (the frame at this time is the nth frame)
  4. Find the feature point to be tracked within the radius of the center of gravity calculated in 3 in the n + 1th frame. If the n + 1 frame of 5.4 is the last frame of the video, it ends. If not, go to 3

When the feature points were detected like this, they tracked even if there was strong lighting in the video. The source is shown below, but since the code is only extracted, some error will occur if it is left as it is.

def extractFeatures(self, gray, rect, features):
    featureList = cv2.goodFeaturesToTrack(gray,100,0.01,10)
    for feature in featureList:
        if rect[0] <= feature[0][0] <= rect[2] and rect[1] <= feature[0][1] <= rect[3]:
            features = self.addList(features, feature[0][0], feature[0][1])
    return features

def featureMouseClicked(self, event, x, y, flags, param):
    if event != cv2.EVENT_LBUTTONDOWN and event != cv2.EVENT_LBUTTONUP:
        return
    if event == cv2.EVENT_LBUTTONDOWN:
        self.rect[0]=x
        self.rect[1]=y
    if event == cv2.EVENT_LBUTTONUP:
        self.rect[2]=x
        self.rect[3]=y
        self.featureRectSet=True

def addList(self,lis,x,y):
    if lis == None:
        lis = np.array([[[x,y]]], np.float32)
    else:
        lis = np.append(lis, [[[x, y]]], axis = 0).astype(np.float32)
    return lis

def cut(img,x,y,width,height):
    ux=0
    uy=0
    dx=0
    dy=0
    if img is None:
        return None,dy,uy,dx,ux
    img_height, img_width = img.shape[:2]
    

    if y+height/2 > img_height:
        uy = img_height
    else:
        uy = y+height/2
    if y-height/2 < 0:
        dy = 0
    else:
        dy = y-height/2

    if x+width/2 > img_width:
        ux = img_width
    else:
        ux = x+width/2
    if x-width/2 < 0:
        dx = 0
    else:
        dx = x-width/2

    if not(dx<ux and dy<uy):
        return None,dy,uy,dx,ux
    if not(0<=ux<=img_width or 0<=dx<=img_width or 0<=uy<=img_height or 0<=dy<=img_height):
        return None,dy,uy,dx,ux
    return img[dy:uy,dx:ux],dy,uy,dx,ux

def nextFrame(self):
    end_flag, Movieframe = self.Moviecap.read()
    #End judgment
    if( Movieframe is None):
        return None

    #Save current frame
    self.nowMovieFrame = Movieframe

    #Optical flow detection
    #Cut out a video with a rectangle with a width and height specified around the position of the previous feature point. Here, the height of the rectangle specified first. It is the same as the width
    mask = np.zeros_like(Movieframe)
    cutFrame,dy,uy,dx,ux= cut(Movieframe,
        int(self.points[len(self.points)-1 - i][0]),#x
        int(self.points[len(self.points)-1 - i][1]),#y
        2*abs(self.rect[1]-self.rect[3]),2*abs(self.rect[0]-self.rect[2]))#
    mask[dy:uy,dx:ux] = cutFrame

    self.grayNext = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
    self.featureNext, status, err = cv2.calcOpticalFlowPyrLK(self.grayPrev, self.grayNext, self.featurePrev, None,
             (dict( winSize  = (15,15),
              maxLevel = 2,
              criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))))
    
    #Select feature points for which optical flow was detected (0: not detected, 1: detected)
    if status != None:
        goodPrev = self.featurePrev[status == 1]
        goodNext = self.featureNext[status == 1]
        for i, (nextPoint, prevPoint) in enumerate(zip(goodNext, goodPrev)):
                prev_x, prev_y = prevPoint.ravel()
                next_x, next_y = nextPoint.ravel()

    if self.featureNext is None:
        return 0

    #Preparing for the next optical flow
    self.grayPrev = self.grayNext.copy()
    self.featurePrev = goodNext.reshape(-1, 1, 2)

    #Returns 1 on success
    return 1


Problems in using 2

If an object with a feature point moves quickly, the feature point will be lost.

If it moves slowly, optical flow will track it well, but if it moves even a little faster, it will lose sight of the feature points. By the way, there may be an opinion that "If you move fast because you specified the range in Solution 1, the place with the feature point will go out of the range and you will lose sight of the feature point", but the state where you do not specify the range However, the phenomenon of losing sight of the feature points has been seen.

solution

As a countermeasure, there is a way to raise the fps as much as possible when recording a video. However, there are often financially impossible things. This time, if I lost sight of the feature points, I had to stop the video and start over from the range specification. It calls the nextFrame function of the above source code, pauses the playback of the video when 0 is returned, calls featureMouseClicked and extractFeatures, specifies the range again, and plays the video. Perhaps I could do more by generating intermediate frames and increasing fps, but I didn't have the power to implement that much.

Development environment

opencv 2.4.13 python 2.7.11

Recommended Posts

What I did when I couldn't find the feature point with the optical flow of opencv and when I lost it
What I did when I was angry to put it in with the enable-shared option
What I did to keep track of the humidity and temperature of the archive
I vectorized the chord of the song with word2vec and visualized it with t-SNE
Read the graph image with OpenCV and get the coordinates of the final point of the graph
When I scraped the thumbnail of BOOTH and detected the face with OpenCV, the accuracy was too good and I was scared.
I tweeted the illuminance of the room with Raspberry Pi, Arduino and optical sensor
When I tried to change the root password with ansible, I couldn't access it.
What I did when I got stuck in the time limit with lambda python
Optical Flow, the dynamics of images captured by OpenCV
When I calculated the similar words of careful + brave with word2vec, it felt unexpectedly valid
I tried to find the entropy of the image with python
I tried "gamma correction" of the image with Python + OpenCV
I tried to find the average of the sequence with TensorFlow
What I did to welcome the Python2 EOL with confidence
Find the average / standard deviation of the brightness values in the image
Determine if the library is installed.
Use Pillow to make the image transparent and overlay only part of it
POST the image with json and receive it with flask
Return the image data with Flask of Python and draw it to the canvas element of HTML
I tried to find the entropy of the image with python
Hash with the standard library hashlib and compare login passwords
Find the white Christmas rate by prefecture with Python and map it to a map of Japan
What to do when a part of the background image becomes transparent when the transparent image is combined with Pillow
What I did when I couldn't find the feature point with the optical flow of opencv and when I lost it
What I did when I migrated to Linux 2 with EOL support for Amazon Linux (learning and failure stories)
I compared the speed of Hash with Topaz, Ruby and Python
I want to check the position of my face with OpenCV!
What happens when I change the hyperparameters of SVM (RBF kernel)?
H29.2.27 ~ 3.5 Summary of what I did
I replaced the numerical calculation of Python with Rust and compared the speed
[Docker] What to do when error Couldn't find the binary git appears
I set the environment variable with Docker and displayed it in Python
Find the general terms of the Tribonacci sequence with linear algebra and Python
A reminder of what I got stuck when starting Atcoder with python
Get and estimate the shape of the head using Dlib and OpenCV with python
I measured the speed of list comprehension, for and while with python2.7.
Try to separate the background and moving object of the video with OpenCV
How to save the feature point information of an image in a file and use it for matching
Try to find the probability that it is a multiple of 3 and not a multiple of 5 when one is removed from a card with natural numbers 1 to 100 using Ruby and Python.