目錄
- 【day1】8.20號實驗記錄(初步使用模板匹配)
- 模板匹配
- 單張圖的代碼
- 利用多個模板去匹配多張圖的代碼
- 寫代碼過程中遇到的問題
【day1】8.20號實驗記錄(初步使用模板匹配)
模板匹配
利用模板匹配可以框定出瓶子,但是卻不能分辨哪種瓶子是哪種瓶子。
對同一張圖片用不同的模板去進行匹配,選擇匹配度最高的作為最終的結果。
而且這種匹配受到模板大小的限制。若是攝像頭固定,視角固定,那這個問題可以解決。
單張圖的代碼
#include <opencv2/opencv.hpp>
#include "opencv2/features2d.hpp"
#include <vector>
#include <algorithm>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include <time.h>
#include <math.h>
#define WINDOW_NAME "【程序窗口】"
using namespace cv;
using namespace std;
int main()
{//改變控制臺字體顏色system("color 02");Mat srcImage=imread("D:\\opencv_picture_test\\視覺項目\\圓1.png"); //測試圖Mat tempMat = imread("D:\\opencv_picture_test\\視覺項目\\方template.png"); //模板圖//Mat srcImage=imread("D:\\opencv_picture_test\\img.png"); //測試圖//Mat tempMat = imread("D:\\opencv_picture_test\\template.png"); //模板圖cout << tempMat.cols << endl;cout << tempMat.rows << endl;Mat refMat;Mat resultMat;Mat dispMat;tempMat.copyTo(refMat);int match_method = TM_CCOEFF_NORMED;//采用模板與目標圖像像素與各自圖像的平均值計算dot product,正值越大匹配度越高,負值越大圖像的區別越大,但如果圖像沒有明顯的特征(即圖像中的像素值與平均值接近)則返回值越接近0;matchTemplate(srcImage, refMat, resultMat, match_method);normalize(resultMat, resultMat, 0, 1, NORM_MINMAX, -1, Mat()); //歸一化double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc; //定義最大值最小值以及它們的位置變量minMaxLoc(resultMat, &minVal, &maxVal, &minLoc, &maxLoc, Mat()); //從結果矩陣中找到匹配度最大以及最小的值并且確定其位置//對于方法SQDIFF和SQDIFF_NORMED兩種方法來講,越小的值就有著更高的匹配結果//而其余的方法則是數值越大匹配效果越好if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED)matchLoc = minLoc;elsematchLoc = maxLoc;srcImage.copyTo(dispMat);//circle(dispMat, matchLoc, 5, Scalar(0, 0, 255), 2, 8, 0);//以最佳匹配點為中心繪制與模板相同大小的框rectangle(dispMat, matchLoc, Point(matchLoc.x + refMat.cols, matchLoc.y + refMat.rows), Scalar::all(0), 2, 8, 0);namedWindow("template", WINDOW_NORMAL);//WINDOW_NORMAL允許用戶自由伸縮imshow("template", refMat);namedWindow("srcImage", WINDOW_NORMAL);//WINDOW_NORMAL允許用戶自由伸縮imshow("srcImage", dispMat);waitKey(0);return 0;
}
利用多個模板去匹配多張圖的代碼
寫代碼過程中遇到的問題
1、要理解好result矩陣的含義
2、match_method 要多試幾種
3、不同模板對同一張測試圖匹配后得到的result數組中,不需要對其歸一化,不然會發現,每個模板的最佳值都是1(使用TM_CCORR_NORMED時),這樣就比較不了了。
#include <opencv2/opencv.hpp>
#include "opencv2/features2d.hpp"
#include <vector>
#include <algorithm>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include <time.h>
#include <math.h>
#define WINDOW_NAME "【程序窗口】"
using namespace cv;
using namespace std;void show_text(int nums)
{if (nums == 0){cout << "方" << endl;}else if (nums == 1){cout << "v圓" << endl;}else if (nums == 2){cout << "圓" << endl;}else if (nums == 3){cout << "小" << endl;}else if (nums == 4){cout << "中" << endl;}else{cout << "無" << endl;}
}
int main()
{//改變控制臺字體顏色system("color 02");//創建模板vectorvector<Mat>tempMat;//插入模板元素Mat temp = imread("D:\\opencv_picture_test\\視覺項目\\方template.png");tempMat.push_back(temp);temp = imread("D:\\opencv_picture_test\\視覺項目\\v圓template.png");tempMat.push_back(temp);temp = imread("D:\\opencv_picture_test\\視覺項目\\圓template.png");tempMat.push_back(temp);temp = imread("D:\\opencv_picture_test\\視覺項目\\小template.png");tempMat.push_back(temp);temp= imread("D:\\opencv_picture_test\\視覺項目\\中template.png");tempMat.push_back(temp);Mat tempMat1 = tempMat[0];Mat tempMat2 = tempMat[1];Mat tempMat3 = tempMat[2];Mat tempMat4 = tempMat[3];Mat tempMat5 = tempMat[4];//獲取模板數目int tempMat_Nums = tempMat.size();//獲取測試圖像Mat srcImage=imread("D:\\opencv_picture_test\\視覺項目\\v圓1.png"); //測試圖Mat resultMat;Mat dispMat;int match_method = TM_CCORR_NORMED; //經過試錯發現此參數較好。//用每個模板去匹配測試圖,并且找出每次結果的最佳匹配值,將值存入vector中vector<double>goodval;vector<Point>goodlock;int matchnum = 0;Point matchLoc;for (int i = 0;i < tempMat_Nums;i++){//采用模板與目標圖像像素與各自圖像的平均值計算dot product,正值越大匹配度越高,負值越大圖像的區別越大,但如果圖像沒有明顯的特征(即圖像中的像素值與平均值接近)則返回值越接近0;matchTemplate(srcImage, tempMat[i], resultMat, match_method);//不歸一化,因為不同模板歸一化后的最佳值皆為1,無法比較//normalize(resultMat, resultMat, 0, 1, NORM_MINMAX, -1, Mat()); //歸一化double minVal; double maxVal; Point minLoc; Point maxLoc; //定義最大值最小值以及它們的位置變量minMaxLoc(resultMat, &minVal, &maxVal, &minLoc, &maxLoc, Mat()); //從結果矩陣中找到匹配度最大以及最小的值并且確定其位置//對于方法SQDIFF和SQDIFF_NORMED兩種方法來講,越小的值就有著更高的匹配結果//而其余的方法則是數值越大匹配效果越好if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED){goodlock.push_back(minLoc);goodval.push_back(minVal);}else{goodlock.push_back(maxLoc);goodval.push_back(maxVal);}cout << i << " "<<maxVal << endl;}//找到goodval中最佳的一組if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED){auto goodPosition = min_element(goodval.begin(), goodval.end());matchnum = distance(begin(goodval), goodPosition);}else{auto goodPosition = max_element(goodval.begin(), goodval.end());matchnum = distance(begin(goodval), goodPosition);}show_text(matchnum);matchLoc = goodlock[matchnum];srcImage.copyTo(dispMat);//circle(dispMat, matchLoc, 5, Scalar(0, 0, 255), 2, 8, 0);//以最佳匹配點為中心繪制與模板相同大小的框rectangle(dispMat, matchLoc, Point(matchLoc.x + tempMat[matchnum].cols, matchLoc.y + tempMat[matchnum].rows), Scalar::all(0), 2, 8, 0);//namedWindow("template", WINDOW_NORMAL);//WINDOW_NORMAL允許用戶自由伸縮//imshow("template", tempMat);namedWindow("srcImage", WINDOW_NORMAL);//WINDOW_NORMAL允許用戶自由伸縮imshow("srcImage", dispMat);waitKey(0);return 0;
}