1. 程式人生 > >模板匹配_從圖片到視訊流

模板匹配_從圖片到視訊流

還是先上我的程式吧,實現了對視訊流的匹配,在視訊中標出目標物體的位置並計算出物體所在的中心座標:

#include <opencv2/core/core.hpp>      
#include <opencv2/highgui/highgui.hpp>     
#include <opencv2\opencv.hpp>    
#include<opencv2\imgproc\imgproc.hpp>  
#include <iostream>    
#include<string>    
#include <sstream>    
using namespace cv;    
using namespace std;  

int main()  
{  
	///呼叫攝像頭
	VideoCapture cap(0);  
	if(!cap.isOpened())  
	{  
		return -1;  
	}  
	Mat src;  
	Mat templ;  
	Mat result;
	int match_method=0;
	templ=imread("img.jpg",1);
	bool stop = false;  
	///迴圈處理影象
	while(!stop)  
	{  
		cap>>src;  
		/// 建立輸出結果的矩陣
		int result_cols =  src.cols - templ.cols + 1;
		int result_rows = src.rows - templ.rows + 1;

		result.create( result_cols, result_rows, CV_32FC1 );

		matchTemplate( src, templ, result, match_method );
		normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );


		/// 通過函式 minMaxLoc 定位最匹配的位置
		double minVal; double maxVal; Point minLoc; Point maxLoc;
		Point matchLoc;

		minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

		/// 對於方法 SQDIFF 和 SQDIFF_NORMED, 越小的數值代表更高的匹配結果. 而對於其他方法, 數值越大匹配越好
		if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
		{ matchLoc = minLoc; }
		else
		{ matchLoc = maxLoc; }

		/// 最終結果
		rectangle( src, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
		rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
		cout<<"目標的中心座標 ( "<<matchLoc.x + templ.cols/2<<" , ("<<matchLoc.y + templ.rows<<" )"<<endl;
		imshow("當前視訊",src);  
		if(waitKey(30) >=0)  
			stop = true;  
	}  
	return 0;  
}


關於模板匹配的原理:

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/template_matching/template_matching.html#template-matching

模板匹配

目標

  • 使用OpenCV函式 matchTemplate 在模板塊和輸入影象之間尋找匹配,獲得匹配結果影象
  • 使用OpenCV函式 minMaxLoc 在給定的矩陣中尋找最大和最小值(包括它們的位置).

原理

什麼是模板匹配?

模板匹配是一項在一幅影象中尋找與另一幅模板影象最匹配(相似)部分的技術.

它是怎麼實現的?

  • 我們需要2幅影象:

    1. 原影象 (I): 在這幅影象裡,我們希望找到一塊和模板匹配的區域
    2. 模板 (T): 將和原影象比照的影象塊

    我們的目標是檢測最匹配的區域:

    ../../../../../_images/Template_Matching_Template_Theory_Summary.jpg
  • 為了確定匹配區域, 我們不得不滑動模板影象和原影象進行 比較 :

    ../../../../../_images/Template_Matching_Template_Theory_Sliding.jpg
  • 通過 滑動, 我們的意思是影象塊一次移動一個畫素 (從左往右,從上往下). 在每一個位置, 都進行一次度量計算來表明它是 “好” 或 “壞” 地與那個位置匹配 (或者說塊影象和原影象的特定區域有多麼相似).

  • 對於 T 覆蓋在 I 上的每個位置,你把度量值 儲存 到 結果影象矩陣 (R) 中. 在 R 中的每個位置 (x,y) 都包含匹配度量值:

    ../../../../../_images/Template_Matching_Template_Theory_Result.jpg

    上圖就是 TM_CCORR_NORMED

     方法處理後的結果影象 R . 最白的位置代表最高的匹配. 正如您所見, 紅色橢圓框住的位置很可能是結果影象矩陣中的最大數值, 所以這個區域 (以這個點為頂點,長寬和模板影象一樣大小的矩陣) 被認為是匹配的.

  • 實際上, 我們使用函式 minMaxLoc 來定位在矩陣 R 中的最大值點 (或者最小值, 根據函式輸入的匹配引數) .

OpenCV中支援哪些匹配演算法?

問得好. OpenCV通過函式 matchTemplate 實現了模板匹配演算法. 可用的方法有6個:

  1. 平方差匹配 method=CV_TM_SQDIFF

這類方法利用平方差來進行匹配,最好匹配為0.匹配越差,匹配值越大.

R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2

  1. 標準平方差匹配 method=CV_TM_SQDIFF_NORMED

    R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}

  2. 相關匹配 method=CV_TM_CCORR

這類方法採用模板和影象間的乘法操作,所以較大的數表示匹配程度較高,0標識最壞的匹配效果.

R(x,y)= \sum _{x',y'} (T(x',y')  \cdot I(x+x',y+y'))

  1. 標準相關匹配 method=CV_TM_CCORR_NORMED

    R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I'(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}

  2. 相關匹配 method=CV_TM_CCOEFF

這類方法將模版對其均值的相對值與影象對其均值的相關值進行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示沒有任何相關性(隨機序列).

R(x,y)= \sum _{x',y'} (T'(x',y')  \cdot I(x+x',y+y'))

在這裡

\begin{array}{l} T'(x',y')=T(x',y') - 1/(w  \cdot h)  \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w  \cdot h)  \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}

  1. 標準相關匹配 method=CV_TM_CCOEFF_NORMED

    R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }

通常,隨著從簡單的測量(平方差)到更復雜的測量(相關係數),我們可獲得越來越準確的匹配(同時也意味著越來越大的計算代價). 最好的辦法是對所有這些設定多做一些測試實驗,以便為自己的應用選擇同時兼顧速度和精度的最佳方案.

程式碼

  • 在這程式實現了什麼?

    • 載入一幅輸入影象和一幅模板影象塊 (template)
    • 通過使用函式 matchTemplate 實現之前所述的6種匹配方法的任一個. 使用者可以通過滑動條選取任何一種方法.
    • 歸一化匹配後的輸出結果
    • 定位最匹配的區域
    • 用矩形標註最匹配的區域
  • 下載程式碼: 單擊 這裡

  • 看一下程式碼:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

/// 全域性變數
Mat img; Mat templ; Mat result;
char* image_window = "Source Image";
char* result_window = "Result window";

int match_method;
int max_Trackbar = 5;

/// 函式宣告
void MatchingMethod( int, void* );

/** @主函式 */
int main( int argc, char** argv )
{
  /// 載入原影象和模板塊
  img = imread( argv[1], 1 );
  templ = imread( argv[2], 1 );

  /// 建立視窗
  namedWindow( image_window, CV_WINDOW_AUTOSIZE );
  namedWindow( result_window, CV_WINDOW_AUTOSIZE );

  /// 建立滑動條
  char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
  createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );

  MatchingMethod( 0, 0 );

  waitKey(0);
  return 0;
}

/**
 * @函式 MatchingMethod
 * @簡單的滑動條回撥函式
 */
void MatchingMethod( int, void* )
{
  /// 將被顯示的原影象
  Mat img_display;
  img.copyTo( img_display );

  /// 建立輸出結果的矩陣
  int result_cols =  img.cols - templ.cols + 1;
  int result_rows = img.rows - templ.rows + 1;

  result.create( result_cols, result_rows, CV_32FC1 );

  /// 進行匹配和標準化
  matchTemplate( img, templ, result, match_method );
  normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

  /// 通過函式 minMaxLoc 定位最匹配的位置
  double minVal; double maxVal; Point minLoc; Point maxLoc;
  Point matchLoc;

  minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

  /// 對於方法 SQDIFF 和 SQDIFF_NORMED, 越小的數值代表更高的匹配結果. 而對於其他方法, 數值越大匹配越好
  if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
    { matchLoc = minLoc; }
  else
    { matchLoc = maxLoc; }

  /// 讓我看看您的最終結果
  rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
  rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );

  imshow( image_window, img_display );
  imshow( result_window, result );

  return;
}

程式碼說明

  1. 定義一些全域性變數, 例如原影象(img), 模板影象(templ) 和結果影象(result) , 還有匹配方法以及視窗名稱:

    Mat img; Mat templ; Mat result;
    char* image_window = "Source Image";
    char* result_window = "Result window";
    
    int match_method;
    int max_Trackbar = 5;
    
  2. 載入原影象和匹配塊:

    img = imread( argv[1], 1 );
    templ = imread( argv[2], 1 );
    
  3. 建立視窗,顯示原影象和結果影象:

    namedWindow( image_window, CV_WINDOW_AUTOSIZE );
    namedWindow( result_window, CV_WINDOW_AUTOSIZE );
    
  4. 建立滑動條並輸入將被使用的匹配方法. 一旦滑動條發生改變,回撥函式 MatchingMethod 就會被呼叫.

    char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
    createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
    
  5. 一直等待,直到使用者退出這個程式.

    waitKey(0);
    return 0;
    
  6. 讓我們先看看回調函式. 首先, 它對原影象進行了一份複製:

    Mat img_display;
    img.copyTo( img_display );
    
  7. 然後, 它建立了一幅用來存放匹配結果的輸出影象矩陣. 仔細看看輸出矩陣的大小(它包含了所有可能的匹配位置)

    int result_cols =  img.cols - templ.cols + 1;
    int result_rows = img.rows - templ.rows + 1;
    
    result.create( result_cols, result_rows, CV_32FC1 );
    
  8. 執行模板匹配操作:

    matchTemplate( img, templ, result, match_method );
    

    很自然地,引數是輸入影象 I, 模板影象 T, 結果影象 R 還有匹配方法 (通過滑動條給出)

  9. 我們對結果進行歸一化:

    normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
    
  10. 通過使用函式 minMaxLoc ,我們確定結果矩陣 R 的最大值和最小值的位置.

    double minVal; double maxVal; Point minLoc; Point maxLoc;
    Point matchLoc;
    
    minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
    

    函式中的引數有:

    • result: 匹配結果矩陣
    • &minVal 和 &maxVal: 在矩陣 result 中儲存的最小值和最大值
    • &minLoc 和 &maxLoc: 在結果矩陣中最小值和最大值的座標.
    • Mat(): 可選的掩模
  11. 對於前二種方法 ( CV_SQDIFF 和 CV_SQDIFF_NORMED ) 最低的數值標識最好的匹配. 對於其他的, 越大的數值代表越好的匹配. 所以, 我們在 matchLoc 中存放相符的變數值:

    if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
      { matchLoc = minLoc; }
    else
      { matchLoc = maxLoc; }
    
  12. 顯示原影象和結果影象. 再用矩形框標註最符合的區域:

    rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
    rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
    
    imshow( image_window, img_display );
    imshow( result_window, result );
    

結果

  1. 開始測試我們的程式,一幅輸入影象:

    ../../../../../_images/Template_Matching_Original_Image.jpg

    還有一幅模版影象:

    ../../../../../_images/Template_Matching_Template_Image.jpg
  2. 產生了一下結果影象矩陣 (第一行是標準的方法 SQDIFF, CCORR 和 CCOEFF, 第二行是相同的方法在進行標準化後的影象). 在第1列, 最黑的部分代表最好的匹配, 對於其它2列, 越白的區域代表越好的匹配.

    Result_0

    Result_2

    Result_4

    Result_1

    Result_3

    Result_5

  3. 正確的匹配在下面顯示 (右側被矩形標註的人臉). 需要注意的是方法 CCORR 和 CCOEFF 給出了錯誤的匹配結果, 但是它們的歸一化版本給出了正確的結果, 這或許是由於我們實際上僅僅考慮 “最匹配” 而沒考慮其他可能的高匹配位置.

    ../../../../../_images/Template_Matching_Image_Result.jpg

相關推薦

模板匹配_圖片視訊流

還是先上我的程式吧,實現了對視訊流的匹配,在視訊中標出目標物體的位置並計算出物體所在的中心座標: #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp&g

圖片相似度計算-模板匹配

什麼是模板匹配?   所謂模板匹配就是給出一個模板圖片和一個搜尋圖片,在搜尋圖片中找到與模板圖片最為相似的部分。 怎麼實現?   簡單來說,就是讓模板圖片在搜尋圖片上滑動,以畫素點為單位,計算每一個位置上的相似度,最終得到相似度最高的畫素點的位置,以該畫素點為原定,模板圖片為大小,對應在搜尋

NLP系列(1)_破譯外星人文字淺談自然語言處理的基礎

應用 展現 發現 func 文本 詞幹 pos 中文分詞 漢語 作者:龍心塵 &&寒小陽 時間:2016年1月。 出處: http://blog.csdn.net/longxinchen_ml/article/details/505

C#_DataTable中檢索信息

int 說明 () [] font blog where 所有 字符 C#_從DataTable中檢索信息 存在於內存中的虛擬表DataTable,綁定在數據顯示控件後,如果想在再檢索其中某些信息,可以利用DataTable.Select方法進行檢索,避免了重復

頁面模板_微信頁面模板功能_微信頁面模板怎麽用?

頁面模板 微信頁面模板功能 微信頁面模板怎麽用 眾所周知,微信公眾平臺在前一段推出了一個功能,稱其名為“頁面模板”;那麽有些朋友就要問我了?這是個什麽鬼東西呀,可以做什麽呀!現在呢,我就跟大家一一道來。 頁面模板:是一個幫助公眾號建立網頁閱讀功能,幫助公

Spring Boot使用模板freemarker【零開始學Spring Boot(轉)

dep demo attach macro 使用 doctype com 地址 2016年 視頻&交流平臺:à SpringBoot網易雲課堂視頻http://study.163.com/course/introduction.htm?courseId=10

『Python CoolBook』C擴展庫_其六_C語言中調用Python代碼

callable 什麽 跟著 來講 cpp iat mst 轉化 gcc 一、C語言運行pyfun的PyObject對象 思路是在C語言中提供實參,傳給python函數: 獲取py函數對象(PyObject),函數參數(C類型) 獲取GIL(PyGILState_

使用Python+OpenCV進行圖像模板匹配(Match Template)

more 查看 AR 簡單 highlight 以及 face ims import 2017年9月22日 BY 藍鯨 LEAVE A COMMENT 本篇文章介紹使用Python和OpenCV對圖像進行模板匹配和識別。模板匹配是在圖像中尋找和識別模板的一種簡單的方法。

用友UAP NC 單據節點_打開參照字段的問題_打不開參照放大鏡_到成功打開了但是取不到值_到修復成功

位置 重新 工作日 color 參數 efm 也有 開心 文檔   項目的這個功能是17年開發的,但是當時沒有測試通過,今年拿出來測試(通過後會上線).   有兩個表數據一開始只打算用來計算時查詢,沒打算放到目標單據中做表體參照字段.後來改細節問題後放到目標單據中做參照字段

OpenCV——模板匹配

.com 分享圖片 pen alt open mage png inf enc OpenCV——模板匹配

React總結篇之三_Flux到Redux

一、FluxRedux是Flux思想的另一種實現方式,Flux一族框架(包括Redux)貫徹的最重要的觀點是單向資料流; 1.MVC框架的缺陷MVC是業界廣泛接受的一種前端應用框架型別,這種框架把應用分為3個部分: Model(模型)負責管理資料,大部分業務邏輯也應該放在Model中; View

一套基於模板匹配的語音識別技術。提取語音的特徵,並建立模板庫,可以將語音識別技術應用於機器人

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

第十天模板匹配,卷積基本概念

卷積具體介紹這篇文章是我看的最好的:https://blog.csdn.net/qq_39521554/article/details/79083864                    

影象處理--模板匹配

模板匹配   首先模板不是用來 精確定位的,只能用來粗定位。先粗定位,然後在你的當前圖中扣取 和模板一樣大小的區域,然後再進行精確定位。 問題1   對於有縮放和旋轉的目標你們是怎麼定位的呢?   輪廓;匹配;模板匹配 問題2   用ORB特徵匹配,怎麼確定匹配到的就是我

模板匹配-TPS

【1】matlab程式碼https://www.mathworks.com/matlabcentral/fileexchange/24315-warping-using-thin-plate-splines 【2】 url:https://blog.csdn.net/victoriaw/ar

jxl實現寫入excel模板及匯出(帶圖片)

在上一片部落格中我用的是freemarker(操作簡單),試了很多種方法就是沒有把帶圖片的excel匯出來,沒辦法就換jxl來實現。好了下面就開始進入正題: 第一步:pom.xml中新增jxl的依賴如下: <!-- jxl通用excel匯入匯出--> <dependen

[python-opencv]模板匹配

模板匹配最適用於工業場合(在一張圖片中識別特定的工件圖) 模板匹配是一種最原始、最基本的模式識別方法,研究某一特定物件物的圖案位於影象(target)的什麼地方,進而識別物件物,這就是一個匹配問題。 它是影象處理中最基本、最常用的匹配方法。模板匹配具有自身的侷限性,主要表現在它只能進行平行移動,若原影象中

圖片中完整切除圓形物體 opencv+python

面臨一個任務就是要圖片中的圓形物體切出來,然後做異常點檢測(就是看那些圓形物體是異常點),因為異常點檢測的方法還在摸索,現在就先把從圖片中把圓形物體完整切出的方法寫出來。 1.首先圖片是這樣的(圓形物體非常多) 2.接下來就是程式碼部分: import os import c

OpenCV 模板匹配 cv::matchTemplate

轉:http://blog.sina.com.cn/s/blog_b0935ba90102wy93.html 今天使用到opencv的matchTemplate運算元,查詢資料,學習了一下。 對官方資料進行翻譯註釋,加深理解,詳情可見:matchTemplate英文資料。 模板匹配

VS2010+Opencv2.3.1,例程實現 筆記之模板匹配

2011-10-04 10:22 VS2010+Opencv2.3.1,例程實現   020 Template Matching   成功程式: