1. 程式人生 > >Opencv目標跟蹤—CamShift和meanshift演算法

Opencv目標跟蹤—CamShift和meanshift演算法

meanshift原理: meanshift演算法思想其實很簡單:利用概率密度的梯度爬升來尋找區域性最優。它要做的就是輸入一個在影象的範圍,然後一直迭代(朝著重心迭代)直到滿足你的要求為止。但是他是怎麼用於做影象跟蹤的呢?這是我自從學習meanshift以來,一直的困惑。而且網上也沒有合理的解釋。經過這幾天的思考,和對反向投影的理解使得我對它的原理有了大致的認識。     在opencv中,進行meanshift其實很簡單,輸入一張影象(imgProb),再輸入一個開始迭代的方框(windowIn)和一個迭代條件(criteria),輸出的是迭代完成的位置(comp )。     這是函式原型:
    int cvMeanShift( const void* imgProb, CvRect windowIn,                       CvTermCriteria criteria, CvConnectedComp* comp )     但是當它用於跟蹤時,這張輸入的影象就必須是反向投影圖了。     為什麼必須是反向投影圖呢?首先我們要理解什麼是反向投影圖。     簡單理解它其實實際上是一張概率密度圖。經過反向投影時的輸入是一個目標影象的直方圖(也可以認為是目標影象),還一個輸入是當前影象就是你要跟蹤的全圖,輸出大小與全圖一樣大,它上畫素點表徵著一種概率,就是全圖上這個點是目標影象一部分的概率。如果這個點越亮,就說明這個點屬於物體的概率越大。現在我們明白了這原來是一張概率圖了。當用meanshift跟蹤時,輸入的原來是這樣一幅影象,那也不難怪它可以進行跟蹤了。
  半自動跟蹤思路:輸入視訊,用畫筆圈出要跟蹤的目標,然後對物體跟蹤。   用過opencv的都知道,這其實是camshiftdemo的工作過程。     第一步:選中物體,記錄你輸入的方框和物體。     第二步:求出視訊中有關物體的反向投影圖。     第三步:根據反向投影圖和輸入的方框進行meanshift迭代,由於它是向重心移動,即向反向投影圖中概率大的地方移動,所以始終會移動到目標上。     第四步:然後下一幀影象時用上一幀輸出的方框來迭代即可。   全自動跟蹤思路:輸入視訊,對運動物體進行跟蹤。     第一步:運用運動檢測演算法將運動的物體與背景分割開來。     第二步:提取運動物體的輪廓,並從原圖中獲取運動影象的資訊。
    第三步:對這個資訊進行反向投影,獲取反向投影圖。     第四步:根據反向投影圖和物體的輪廓(也就是輸入的方框)進行meanshift迭代,由於它是向重心移 動,即向反向投影圖中概率大的地方移動,所以始終會移動到物體上。     第五步:然後下一幀影象時用上一幀輸出的方框來迭代即可。     總結:用meanshift進行跟蹤最重要的一點是輸入影象的把握,也就是要讓它的迭代能越來越迭代到目標上。這種影象也不一定就是反向投影圖,只要是一幅反映當前影象中每個畫素點含有目標概率圖就可以了,其實反向投影圖就是這樣的一幅圖而已。 轉載:http://www.cnblogs.com/cfantaisie/archive/2011/06/10/2077190.html

Camshift原理

CamShift演算法的全稱是"Continuously Adaptive Mean-SHIFT",即:連續自適應的MeanShift演算法。其基本思想是對視訊序列的所有影象幀都作MeanShift運算,並將上一幀的結果(即搜尋視窗的中心位置和視窗大小)作為下一幀MeanShift演算法的搜尋視窗的初始值,如此迭代下去。簡單點說,meanShift是針對單張圖片尋找最優迭代結果,而camShift則是針對視訊序列來處理,並對該序列中的每一幀圖片都呼叫meanShift來尋找最優迭代結果。正是由於camShift針對一個視訊序列進行處理,從而保證其可以不斷調整視窗的大小,如此一來,當目標的大小發生變化的時候,該演算法就可以自適應地調整目標區域繼續跟蹤。

自帶的camShift的例子當中,是通過計算目標在HSV空間下的H分量直方圖,通過直方圖反向投影得到目標畫素的概率分佈,然後通過呼叫OpenCVCAMSHIFT演算法,自動跟蹤並調整目標視窗的中心位置與大小。該演算法對於簡單背景下的單目標跟蹤效果較好,但如果被跟蹤目標與背景顏色或周圍其它目標顏色比較接近,則跟蹤效果較差。另外,由於採用顏色特徵,所以它對被跟蹤目標的形狀變化有一定的抵抗能力。

http://blog.csdn.net/carson2005/article/details/7439125

 分為三個部分:
1--色彩投影圖(反向投影):
(1).RGB顏色空間對光照亮度變化較為敏感,為了減少此變化對跟蹤效果的影響,首先將影象從RGB空間轉換到HSV空間。(2).然後對其中的H分量(色調)作直方圖,在直方圖中代表了不同H分量值出現的概率或者畫素個數,就是說可以查找出H分量大小為h的概率或者畫素個數,即得到了顏色概率查詢表。(3).將影象中每個畫素的值用其顏色出現的概率對替換,就得到了顏色概率分佈圖。這個過程就叫反向投影,顏色概率分佈圖是一個灰度影象。


2--meanshift
meanshift演算法是一種密度函式梯度估計的非引數方法,通過迭代尋優找到概率分佈的極值來定位目標。
演算法過程為:
(1).在顏色概率分佈圖中選取搜尋窗W
(2).計算零階距:

計算一階距:

計算搜尋窗的質心:

(3).調整搜尋窗大小
寬度為;長度為1.2s;
(4).移動搜尋窗的中心到質心,如果移動距離大於預設的固定閾值,則重複2)3)4),直到搜尋窗的中心與質心間的移動距離小於預設的固定閾值,或者迴圈運算的次數達到某一最大值,停止計算。關於meanshift的收斂性證明可以google相關文獻。

3--camshift
將meanshift演算法擴充套件到連續影象序列,就是camshift演算法。它將視訊的所有幀做meanshift運算,並將上一幀的結果,即搜尋窗的大小和中心,作為下一幀meanshift演算法搜尋窗的初始值。如此迭代下去,就可以實現對目標的跟蹤。
演算法過程為:
(1).初始化搜尋窗
(2).計算搜尋窗的顏色概率分佈(反向投影)
(3).執行meanshift演算法,獲得搜尋窗新的大小和位置。
(4).在下一幀視訊影象中用(3)中的值重新初始化搜尋窗的大小和位置,再跳轉到(2)繼續進行。

camshift能有效解決目標變形和遮擋的問題,對系統資源要求不高,時間複雜度低,在簡單背景下能夠取得良好的跟蹤效果。但當背景較為複雜,或者有許多與目標顏色相似畫素干擾的情況下,會導致跟蹤失敗。因為它單純的考慮顏色直方圖,忽略了目標的空間分佈特性,所以這種情況下需加入對跟蹤目標的預測演算法。

__________________________________________________________________________________________________________________________________________

半自動跟蹤思路:輸入視訊,用畫筆圈出要跟蹤的目標,然後對物體跟蹤。

  用過opencv的都知道,這其實是camshiftdemo的工作過程。

    第一步:選中物體,記錄你輸入的方框和物體。

    第二步:求出視訊中有關物體的反向投影圖。

    第三步:根據反向投影圖和輸入的方框進行meanshift迭代,由於它是向重心移動,即向反向投影圖中概率大的地方移動,所以始終會移動到目標上。

    第四步:然後下一幀影象時用上一幀輸出的方框來迭代即可。

  全自動跟蹤思路:輸入視訊,對運動物體進行跟蹤。

    第一步:運用運動檢測演算法將運動的物體與背景分割開來。

    第二步:提取運動物體的輪廓,並從原圖中獲取運動影象的資訊。

    第三步:對這個資訊進行反向投影,獲取反向投影圖。

    第四步:根據反向投影圖和物體的輪廓(也就是輸入的方框)進行meanshift迭代,由於它是向重心移動,即向反向投影圖中概率大的地方移動,所以始終會移動到物體上。

    第五步:然後下一幀影象時用上一幀輸出的方框來迭代即可。

下面是一個全自動跟蹤的例子

程式碼是copy來的,從哪來的忘了……

  1. #include <iostream>
  2. #include <opencv2/opencv.hpp>
  3. usingnamespace std;  
  4. usingnamespace cv;  
  5. //對輪廓按面積降序排列
  6. bool biggerSort(vector<Point> v1, vector<Point> v2)  
  7. {  
  8.     return contourArea(v1)>contourArea(v2);  
  9. }  
  10. int main()  
  11. {  
  12.     //視訊不存在,就返回
  13.     VideoCapture cap("3.AVI");  
  14.     if(cap.isOpened()==false)  
  15.         return 0;  
  16.     //定義變數
  17.     int i;  
  18.     Mat frame;          //當前幀
  19.     Mat foreground;     //前景
  20.     Mat bw;             //中間二值變數
  21.     Mat se;             //形態學結構元素
  22.     //用混合高斯模型訓練背景影象
  23.     BackgroundSubtractorMOG mog;      
  24.     for(i=0;i<10;++i)  
  25.     {  
  26.         cout<<"正在訓練背景:"<<i<<endl;  
  27.         cap>>frame;  
  28.         if(frame.empty()==true)  
  29.         {  
  30.             cout<<"視訊幀太少,無法訓練背景"<<endl;  
  31.             getchar();  
  32.             return 0;  
  33.         }  
  34.         mog(frame,foreground,0.01);   
  35.     }  
  36.     //目標外接框、生成結構元素(用於連線斷開的小目標)
  37.     Rect rt;  
  38.     se=getStructuringElement(MORPH_RECT,Size(5,5));  
  39.     //統計目標直方圖時使用到的變數
  40.     vector<Mat> vecImg;  
  41.     vector<int> vecChannel;  
  42.     vector<int> vecHistSize;  
  43.     vector<float> vecRange;  
  44.     Mat mask(frame.rows,frame.cols,DataType<uchar>::type);  
  45.     //變數初始化
  46.     vecChannel.push_back(0);  
  47.     vecHistSize.push_back(32);  
  48.     vecRange.push_back(0);  
  49.     vecRange.push_back(180);  
  50.     Mat hsv;        //HSV顏色空間,在色調H上跟蹤目標(camshift是基於顏色直方圖的演算法)
  51.     MatND hist;     //直方圖陣列
  52.     double maxVal;      //直方圖最大值,為了便於投影圖顯示,需要將直方圖規一化到[0 255]區間上
  53.     Mat backP;      //反射投影圖
  54.     Mat result;     //跟蹤結果
  55.     //視訊處理流程
  56.     while(1)  
  57.     {  
  58.         //讀視訊
  59.         cap>>frame;  
  60.         if(frame.empty()==true)  
  61.             break;        
  62.         //生成結果圖
  63.         frame.copyTo(result);  
  64.         //檢測目標(其實是邊訓練邊檢測)
  65.         mog(frame,foreground,0.01);  
  66.         imshow("混合高斯檢測前景",foreground);  
  67.         moveWindow("混合高斯檢測前景",400,0);  
  68.         //對前景進行中值濾波、形態學膨脹操作,以去除偽目標和接連斷開的小目標     
  69.         medianBlur(foreground,foreground,5);  
  70.         imshow("中值濾波",foreground);  
  71.         moveWindow("中值濾波",800,0);  
  72.         morphologyEx(foreground,foreground,MORPH_DILATE,se);  
  73.         //檢索前景中各個連通分量的輪廓
  74.         foreground.copyTo(bw);  
  75.         vector<vector<Point>> contours;  
  76.         findContours(bw,contours,RETR_EXTERNAL,CHAIN_APPROX_NONE);  
  77.         if(contours.size()<1)  
  78.             continue;  
  79.         //對連通分量進行排序
  80.         std::sort(contours.begin(),contours.end(),biggerSort);  
  81.         //結合camshift更新跟蹤位置(由於camshift演算法在單一背景下,跟蹤效果非常好;
  82.         //但是在監控視訊中,由於解析度太低、視訊質量太差、目標太大、目標顏色不夠顯著
  83.         //等各種因素,導致跟蹤效果非常差。  因此,需要邊跟蹤、邊檢測,如果跟蹤不夠好,
  84.         //就用檢測位置修改
  85.         cvtColor(frame,hsv,COLOR_BGR2HSV);  
  86.         vecImg.clear();  
  87.         vecImg.push_back(hsv);  
  88.         for(int k=0;k<contours.size();++k)  
  89.         {  
  90.             //第k個連通分量的外接矩形框
  91.             if(contourArea(contours[k])<contourArea(contours[0])/5)  
  92.                 break;  
  93.             rt=boundingRect(contours[k]);                 
  94.             mask=0;  
  95.             mask(rt)=255;  
  96.             //統計直方圖
  97.             calcHist(vecImg,vecChannel,mask,hist,vecHistSize,vecRange);               
  98.             minMaxLoc(hist,0,&maxVal);  
  99.             hist=hist*255/maxVal;  
  100.             //計算反向投影圖
  101.             calcBackProject(vecImg,vecChannel,hist,backP,vecRange,1);  
  102.             //camshift跟蹤位置
  103.             Rect search=rt;  
  104.             RotatedRect rrt=CamShift(backP,search,TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,10,1));  
  105.             Rect rt2=rrt.boundingRect();  
  106.             rt&=rt2;  
  107.             //跟蹤框畫到視訊上
  108.             rectangle(result,rt,Scalar(0,255,0),2);           
  109.         }  
  110.         //結果顯示
  111.         imshow("原圖",frame);  
  112.         moveWindow("原圖",0,0);  
  113.         imshow("膨脹運算",foreground);  
  114.         moveWindow("膨脹運算",0,350);  
  115.         imshow("反向投影",backP);  
  116.         moveWindow("反向投影",400,350);  
  117.         imshow("跟蹤效果",result);  
  118.         moveWindow("跟蹤效果",800,350);  
  119.         waitKey(30);      
  120. 相關推薦

    Opencv目標跟蹤CamShiftmeanshift演算法

    meanshift原理: meanshift演算法思想其實很簡單:利用概率密度的梯度爬升來尋找區域性最優。它要做的就是輸入一個在影象的範圍,然後一直迭代(朝著重心迭代)直到滿足你的要求為止。但是他是怎麼用於做影象跟蹤的呢?這是我自從學習meanshift以來,一直的困惑。

    opencv視覺跟蹤——CAMshiftmeanshift均值漂移)

    關於CAMshift的資料很多,如下連結寫的都很不錯,我就說說自己對CAMshift的理解 https://blog.csdn.net/li_dongxuan/article/details/70667170 https://blog.csdn.net/leixiaohua1020/arti

    opencv目標跟蹤概述人臉跟蹤

    概述 opencv內部實現了一些單目標跟蹤演算法,可以很方便的使用。 這裡說的目標跟蹤不是多目標跟蹤,往往是需要人工或程式給定初始目標位置。 資源及跟蹤演算法介紹 這個頁面介紹了幾個常用的跟蹤演算法: BOOSTING Tracker:基於線

    OpenCV學習筆記十九---運動跟蹤 CamShift以及meanShift詳解

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

    目標跟蹤--CamShift

    矩形 顏色 hsv顏色空間 方法 邊界 攝像頭 stream i++ 可選 轉載請註明出處!!!http://blog.csdn.net/zhonghuan1992 目標跟蹤--CamShift CamShift

    OpenCV目標跟蹤(四)-運動模板

    OpenCV中運動與跟蹤這一章節中,在前面的介紹中,主要給出了LK光流法,以及基於概率統計,視窗搜尋的meanshif演算法以及meanshif演算法的改進版-camshift演算法,這兩天主要在看運動模板的跟蹤運動方法,下面就簡要的介紹下。 運動模板的方法是

    OpenCV目標跟蹤-LK光流法

    這幾天主要看了光流的有關內容,下面就關於光流的有關內容進行個簡單的總結。  所謂的光流是一種運動模式,這種運動模式即是指一個物體、表面、邊緣在一個視角下由一個觀察者和背景之間形成的明顯移動。在如下的圖中給出了光流的直觀解釋。  這裡的每個畫素都與速度相關聯,這樣得到的

    影象處理之其他雜項(一)之MeanShift目標跟蹤演算法opencv c++程式碼 VS2015+opencv3.2

    //#include "stdafx.h" //#include "cv.h" //#include "highgui.h" #include<opencv.hpp> #define u_char unsigned char #define DIST 0.5 #define

    [opencv]模板匹配演算法(單影象模板匹配基於模板匹配的目標跟蹤

    1.模板匹配opencv函式 matchTemplate(InputArray image, InputArray temp, OutputArray result, int method) Parameters: image – Image where the search is runn

    opencv學習筆記四十三:CamShift目標跟蹤

    CamShift演算法,全稱是 Continuously AdaptiveMeanShift,顧名思義,它是對Mean Shift 演算法的改進,能夠自動調節搜尋視窗大小來適應目標的大小,可以跟蹤視訊中尺寸變化的目標。基本思想是以視訊影象中運動物體的顏色資訊作為特徵,對輸入影

    OpenCV學習筆記(二十六)——小試SVM演算法ml OpenCV學習筆記(二十七)——基於級聯分類器的目標檢測objdect OpenCV學習筆記(二十八)——光流法對運動目標跟蹤Video Ope

    OpenCV學習筆記(二十六)——小試SVM演算法ml  總感覺自己停留在碼農的初級階段,要想更上一層,就得靜下心來,好好研究一下演算法的東西。OpenCV作為一個計算機視覺的開源庫,肯定不會只停留在數字影象處理的初級階段,我也得加油,深入研究它的演算法庫。就從ml入手

    opencvCamshift目標跟蹤

    Camshift原理 CamShift演算法的全稱是"Continuously Adaptive Mean-SHIFT",即:連續自適應的MeanShift演算法。其基本思想是對視訊序列的所有影象幀都作MeanShift運算,並將上一幀的結果(即搜尋視窗的中心位置和視窗大小

    OpenCV學習筆記 019】SIFTSURF演算法實現目標檢測

    一、SIFT和SURF運算元實現特徵點檢測 概述 在OpenCV的features2d中實現了SIFT和SURF演算法,可以用於影象特徵點的自動檢測。具體實現是採用SiftFeatureDetector/SurfFeatureDetector類的detect函式檢測SIFT

    目標跟蹤CamShift演算法

    1.前言 camshift利用目標的顏色直方圖模型將影象轉換為顏色概率分佈圖,初始化一個搜尋窗的大小和位置,並根據上一幀得到的結果自適應調整搜尋視窗的位置和大小,從而定位出當前影象中目標的中心位置

    CamShift 目標跟蹤演算法研究(轉)

    CamShift演算法:    CamShift演算法,即"Continuously Apative Mean-Shift"演算法,是一種運動跟蹤演算法。它主要通過視訊影象中運動物體的顏色資訊來達到跟蹤的目的。    我把這個演算法分解成三個部分,便於理解:    1)

    opencv入門跟蹤演算法(3)之camshift

    二.演算法原理 1、camshift利用目標的顏色直方圖模型將影象轉換為顏色概率分佈圖,初始化一個搜尋窗的大小和位置,並根據上一幀得到的結果自適應調整搜尋視窗的位置和大小,從而定位出當前影象中目標的中心位置。camshift的核心步驟仍然是Meanshift,只是在距離相似性

    Python+OpenCV學習(13)---meanshift目標跟蹤

    利用python學習OpenCV,個人感覺比較方便。函式的形式與C++基本相同,所以切換過來還是比較好的,對於像我這種對python不太熟練的人,使用python的整合開發環境PyCharm進行學習,可以設定斷點除錯,有助於我這類初學者理解掌握。 下面是利用python

    python,OpenCVcamShift目標跟蹤

    之前一直都是用的網上c++版本的程式碼,最近想做一些拓展,要用python來實現。在網上找 了一下,感覺不是很好用。於是參照官方文件和c++版本的程式碼改寫了一些。引數也沒怎麼調整就直接用了。import cv2 import numpy as np xs,ys,ws,h

    程式碼實現:基於opencv庫的單目標跟蹤演算法

    import cv2 ############################################################################## # 載入視訊 camera = cv2.VideoCapture('tracking.avi'

    OpenCV學習總結(4)- 目標跟蹤

    opened 背景 key font sin mic 目標 mil cap 視覺算法原理:背景提取  1. 打開視頻(文件或攝像頭)  2. 從視頻中提取當前幀  3. 計算背景:以前多幀求取平均  4. 根據背景得到運動目標(當前幀 - 背景)  5. 返回2,程序不斷循