1. 程式人生 > >目標檢測光流法(二):opencv下的光流L-K演算法

目標檢測光流法(二):opencv下的光流L-K演算法

後續將簡單介紹光流法的一些簡單實現包,包括opencv下的光流演算法與matlab下的光流演算法。該節主要介紹opencv下的光流實現。

Opencv的光流實現由好幾個方法可以(也就是說有好幾個函式可以用),每個函式當然也對應著不同的原理,那麼它的效果以及演算法的速度等等就會有一些差別。主要包括以下幾種:
calcOpticalFlowPyrLK
calcOpticalFlowFarneback
calcOpticalFlowBM
calcOpticalFlowHS
calcOpticalFlowSF

這裡先簡單介紹下calcOpticalFlowPyrLK函式
calcOpticalFlowPyrLK函式使用形式:
calcOpticalFlowPyrLK(prevImg,nextImg,prevPts,nextPts,status,err)
這個函式還有一些可選引數,一大堆,詳細的說明可以看

這裡只是貼出了主要的幾個輸入輸出:
prevImg:就是你需要輸入計算光流的前一幀影象

nextImg就是下一幀影象(可以看到一次光流就是在兩針影象之間找不同)。

prevPts是前一幀影象中的特徵點,這個特徵點必須自己去找,所以在使用calcOpticalFlowPyrLK函式的時候,前面需要有一個找特徵點的操作,那麼一般就是找影象的角點,就是一個畫素點與周圍畫素點都不同的那個點,這個角點特徵點的尋找,opencv也提供夜歌函式:goodFeatureToTrack()(後面再介紹這個函式)。那麼關於特徵點有沒有其他的方式呢?肯定是有的而且還很多吧。

nextPts引數就是計算特徵點在第二幅影象中的新的位置,然後輸出。特徵點的新位置可能變化了,也可能沒有變化,那麼這種狀態就存放在後一個引數status中。err就是新舊兩個特徵點位置的誤差了,也是一個輸出矩陣。
其他引數預設吧。

關於特徵角點檢測函式goodFeatureToTrack()
goodFeaturesToTrack(image,corners,maxCorners,qualityLevel,minDistance)
函式的引數:
image輸入影象;
corners輸出的特徵點系列,每一個元素就是一個特徵點的位置。
maxCorners規定的特徵點最大數目,比如一副影象你可以找到很多特徵點,但是隻是取前maxCorners個具有最大特徵的那些點作為最後的特徵點,至於怎麼判斷哪些點的特徵更好了,opencv自有一個機制,隨便一個方法,比如計算一下這個點與周圍一定領域的點的灰度相差求和,認為這個和越大的那些點是不是越屬於特徵點。
qualityLevel

是一個特徵點的取到水平,其實也是控制特徵點的選取的,看結果適當選取吧。
minDistance是特徵點與點之間的最小距離,一般我們如果想特徵點儘量分散一些,太密集了肯定不好,那麼我們可以通過這個引數。

比如說一個例子如下:

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;
int main()
{
    Mat I1;
    Mat I2;
    vector<Point2f> features;
    int maxCout = 50;//定義最大個數
    double minDis = 20;//定義最小距離
    double qLevel = 0.01;//定義質量水平

    I1 = imread("I1.jpg",0);//讀取為灰度影象
    goodFeaturesToTrack(I1,features,maxCout,qLevel,minDis);
    for(int i=0;i<features.size();i++)
    {
        //將特徵點畫一個小圓出來--粗細為2
        circle(I1,features[i],3,Scalar(255),2);
    }
    imshow("features",I1);
    waitKey(0);
    return 0;
}

這裡寫圖片描述

修改下 int maxCout = 100;//定義最大個數
double minDis = 10;//定義最小距離

這裡寫圖片描述

下面通過這種特徵點來以及L-K光流法來檢測兩幅相鄰幀影象之間的移動點。首先自己準備兩幅圖吧,圖中要有運動的目標才好,然後我們就這兩幅圖簡單的看下里面的運動目標的特徵點的運動吧,一個簡單程式如下:

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/types_c.h>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;
int main()
{
    Mat I1;
    Mat I2;
    vector<Point2f> features;
    vector<Point2f> features_after;
    vector<uchar> status;
    vector<float> err;
    int maxCout = 300;//定義最大個數
    double minDis = 10;//定義最小距離
    double qLevel = 0.01;//定義質量水平
    //讀取兩個影象---相鄰幀
    I1 = imread("I1.jpg",0);//讀取為灰度影象
    I2 = imread("I2.jpg",0);
    //檢測第一幀的特徵點
    goodFeaturesToTrack(I1,features,maxCout,qLevel,minDis);
    //計算出第二幀的特徵點
    calcOpticalFlowPyrLK(I1,I2,features,features_after,status,err);
    //判別哪些屬於運動的特徵點
    int k = 0;
    for(int i=0;i<features_after.size();i++)
    {
        //狀態要是1,並且座標要移動下的那些點
        if(status[i]&&((abs(features[i].x-features_after[i].x)+
            abs(features[i].y-features_after[i].y))>4))
        {
            features_after[k++] = features_after[i];
        }
    }
    features_after.resize(k);//擷取
    cout<<k<<endl;
    for(int i=0;i<features_after.size();i++)
    {
        //將特徵點畫一個小圓出來--粗細為2
        circle(I1,features_after[i],3,Scalar(255),2);
    }
    imshow("features",I1);
    waitKey(0);
    return 0;
}

這裡寫圖片描述

我的這兩幅樹葉圖是存在這一些變化的,尤其樹存在的地方,由於需要動態的來回切換著看才能看出變化,所以這裡不太好顯示這兩幅圖的變化,這裡吧他們相差的圖做出來如下:
這裡寫圖片描述

可以看到的是越白的地方就是存在著不一致,也就是存在著明顯運動的地方。和上面角點檢測的還是有點符合的。
當然,我這可能只是連續兩幀運動情況下的跟蹤的特徵點,如果是一個視訊(連續的很多幀),那麼把每兩幀之間的運動點連線起來,就可以發現運動的物體的整個軌跡了。像網上部落格有人做過的貼幾個:

相關推薦

目標檢測opencvL-K演算法

後續將簡單介紹光流法的一些簡單實現包,包括opencv下的光流演算法與matlab下的光流演算法。該節主要介紹opencv下的光流實現。 Opencv的光流實現由好幾個方法可以(也就是說有好幾個函式可以用),每個函式當然也對應著不同的原理,那麼它的效果以及演算

目標檢測opencvFarneback

上節說到過的calcOpticalFlowPyrLK光流演算法,可以看到它實際上是一種稀疏特徵點的光流演算法,也就是說我們先找到那些(特徵)點需要進行處理,然後再處理,該節介紹下一個全域性性的密集光流演算法,也就是對每一個點都進行光流計算,函式為calcOpti

顯著性目標檢測模型評價指標——PR曲線

顯著性目標檢測模型評價指標 之 PR曲線原理與實現程式碼 目錄 一、PR曲線原理 在顯著目標提取中(關於視覺顯著性的簡要介紹點此處連結),PR曲線是用來評估模型效能的重要指標之一,PR曲線中的P(Precision)和R(Recall)分

caffe目標檢測模型訓練全過程python載入caffemodel分類

繼上篇 caffe目標檢測模型訓練全過程(一)指令碼、資料準備與製作 之後,我們訓練出來了其模型,如圖所示: models2_iter_70000.caffemodel 就是需要呼叫的模型,70

[Swift]八大排序算快速排序

addition 每次 數據交換 uri 基本思想 技術分享 繼續 splay 休眠 排序分為內部排序和外部排序。 內部排序:是指待排序列完全存放在內存中所進行的排序過程,適合不太大的元素序列。 外部排序:指的是大文件的排序,即待排序的記錄存儲在外存儲器上,待排序的文件

星雲鏈智能合約開發Mac安裝星雲鏈

Mac下安裝星雲鏈 星雲鏈智能合約開發 Golang環境搭建 版本用最新版:1.10.2 安裝 brew install go 配置環境變量 vi ~/.bash_profile 打開.bash_profile文件,按"i"鍵可進行編輯,添加: export GOROOT=/u

影象拼接OpenCV同時開啟兩個攝像頭捕獲視訊

使用OpenCV實現同時開啟兩個USB攝像頭,並實時顯示視訊。如果未檢測有兩個攝像頭,程式會結束併發出“攝像頭未安裝好”的警告。這裡推薦一個小巧的攝像頭視訊捕捉軟體:amcap,使用它可以方便的檢查每個攝像頭是否能正常工作。  捕獲視訊:  #include "opencv

Python與機器學習Windows科學計算環境搭建

【注意:安裝numpy和scipy模組時注意與Python版本保持一致】 1.安裝numpy 測試: 沒有報錯,bingo~ 2.安裝scipy 在官網中下載scipy3.4版本:scipy-0

HMM學習筆記監督學習方法與Baum-Welch演算法

學習隱馬爾可夫模型(HMM),主要就是學習三個問題:概率計算問題,學習問題和預測問題。在前面講了概率計算問題:前後向演算法推導,這裡接著講學習問題,即求模型 λ

經典論文重讀---目標檢測Fast RCNN

核心思想 RCNN的缺點 R-CNN is slow because it performs a ConvNet forward pass for each object proposal, without sharing computation. SPPnet的缺

tensorflow利用預訓練模型進行目標檢測檢測結果存入mysql資料庫

mysql版本:5.7 ; 資料庫:rdshare;表captain_america3_sd用來記錄某幀是否被檢測。表captain_america3_d用來記錄檢測到的資料。 python模組,包部分內容參考http://www.runoob.com/python/python-modules.html&

CNN目標檢測YOLO

↑↑↑↑目錄在這裡↑↑↑↑ 縮排YOLO全稱You Only Look Once: Unified, Real-Time Object Detection,是在CVPR2016提出的一種目標檢測演算法,核心思想是將目標檢測轉化為迴歸問題求解,並基於一個單獨的end-to-e

象棋AI算

根節點 說明 過去 發現 oot set 位置 fun () 原文大神是用html5+js寫的關於象棋AI的博客,裏面重點講了棋子的著法,自己設計的評估函數和簡單的Minmax理論,沒有具體的講搜索算法,本文是對原文的學習和分析補充 一,棋子的著法com.bylaw

JVM高級特性與實踐對象存活判定算引用 與 回收

添加 引用計數器 程序計數器 正文 bmc 進入 block 結構 內存 關於垃圾回收器GC(Garbage Collection),多數人意味它是Java語言的伴生產物。事實上,GC的歷史遠比Java悠遠,於1960年誕生在MIT的Lisp是第一門真正使用內存動態分配和垃

分治算

分治思想 strong mage mooc str span org 合成 代碼實現 大家都知道選擇排序和冒泡排序,這兩個排序都是雙重for循環,時間復雜度為O(n^2),顯然效率都是比較低的,而運用分治思想的歸並排序和快速排序會更高效一些。 1、歸並排序 1)原理

簡單選擇排序

簡單選擇排序從左到右依次選取一個值作為默認最大值,依次與其它值比較,如果有值比該值大,那最大值指針改指向該值,一輪比較完成後,如果最大值指針沒有變化,則從下一個值繼續下一輪比較,如果指針有變動,則最新指針位置的數值與初始指針位置數值交換位置。代碼如下:lst1 = [ [1, 8, 9, 5, 6,

day40 數據結構-算

圍墻 dea maxsize 由於 image closed images 哈希函數 鏈表 什麽是數據結構? 簡單來說,數據結構就是設計數據以何種方式組織並存儲在計算機中。 比如:列表、集合與字典等都是一種數據結構。 N.Wirth: “程序=數據結構+算法” 列表

Java數據結構和算——數組

image 創建 函數 編程 局限性 總結 遍歷數組 ron 添加   上篇博客我們簡單介紹了數據結構和算法的概念,對此模糊很正常,後面會慢慢通過具體的實例來介紹。本篇博客我們介紹數據結構的鼻祖——數組,可以說數組幾乎能表示一切的數據結構,在每一門編

Java IO總結-示例

一行 spa ascii 路徑名 指向 每次 字節數 判斷 pri 1.使用文件操作的9大方法完成文件的判斷 判斷文件或目錄是否存在 : exits() 返回值boolean型 * 判斷是否是文件: isFile() boolean * 判斷是否是目錄: isDie

數據結構與算--棧與隊列

break col color 一個 大小 amp 頂上 const 試題 棧和隊列 棧和隊列都是比較常用的數據結構。棧的應用非常的廣泛,比如說,遞歸函數的實現就是借助於棧保存相關的數據。操作系統中每個線程也會使用棧來保存函數調用涉及到的一些參數和其他變量等。棧最大的一個特