OpenCV C++開發 第二節:圖像處理(十一、圖片的模板匹配、輪廓發現)

一、圖片的模板匹配

代碼:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace std;
using namespace cv;


Mat src, temp, dst;
int match_method = TM_SQDIFF;
int max_track = 5;
const char* INPUT_T = "input image";
const char* OUTPUT_T = "result image";
const char* match_t = "template match-demo";
void Match_Demo(int, void*);
int main(int argc, char** argv) {
	// 待檢測圖像
	src = imread("C:\\Users\\Administrator\\Desktop\\test1.png");
	// 模板圖像
	temp = imread("C:\\Users\\Administrator\\Desktop\\1.jpg");
	if (src.empty() || temp.empty()) {
		printf("could not load image...\n");
		return -1;
	}
	namedWindow(INPUT_T, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_T, CV_WINDOW_NORMAL);
	namedWindow(match_t, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_T, temp);
	const char* trackbar_title = "Match Algo Type:";
	createTrackbar(trackbar_title, OUTPUT_T, &match_method, max_track, Match_Demo);
	Match_Demo(0, 0);

	waitKey(0);
	return 0;
}

void Match_Demo(int, void*) {
	int width = src.cols - temp.cols + 1;
	int height = src.rows - temp.rows + 1;
	Mat result(width, height, CV_32FC1);

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

	Point minLoc;
	Point maxLoc;
	double min, max;
	src.copyTo(dst);
	Point temLoc;
	minMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat());
	if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED) {
		temLoc = minLoc;
	}
	else {
		temLoc = maxLoc;
	}

	// 繪製矩形
	rectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);
	rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);

	imshow(OUTPUT_T, result);
	imshow(match_t, dst);
}

以上代碼中主要的幾個知識點解釋下:

1.matchTemplate(src, temp, result, match_method, Mat());

模板匹配的主要方法

matchTemplate(

InputArray image,// 源圖像,必須是8-bit或者32-bit浮點數圖像

InputArray templ,// 模板圖像,類型與輸入圖像一致

OutputArray result,// 輸出結果,必須是單通道32位浮點數,假設源圖像WxH,模板圖像wxh,則結果必須爲W-w+1, H-h+1的大小

int method,//使用的匹配方法

InputArray mask=noArray()//(optional))

2.minMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat());

獲取模板匹配後的匹配圖片位置,minLoc是開始點的座標,maxLoc是結束點的座標。

3.rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);

繪製匹配圖片的位置框框。

二、輪廓發現

輪廓發現是基於圖像邊緣提取的基礎尋找對象輪廓的方法。所以邊緣提取的閾值選定會影響最終輪廓發現結果

代碼:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>


using namespace std;
using namespace cv;

Mat src, dst;
const char* output_win = "findcontours-demo";
int threshold_value = 100;
int threshold_max = 255;
RNG rng;
void Demo_Contours(int, void*);
int main(int argc, char** argv) {
	// 待檢測圖像
	src = imread("C:\\Users\\Administrator\\Desktop\\test.png");
	if (src.empty()) {
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input-image", CV_WINDOW_AUTOSIZE);
	namedWindow(output_win, CV_WINDOW_AUTOSIZE);
	imshow("input-image", src);
	cvtColor(src, src, CV_BGR2GRAY);

	const char* trackbar_title = "Threshold Value:";
	createTrackbar(trackbar_title, output_win, &threshold_value, threshold_max, Demo_Contours);
	Demo_Contours(0, 0);

	waitKey(0);
	return 0;
}

void Demo_Contours(int, void*) {
	Mat canny_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hierachy;
	Canny(src, canny_output, threshold_value, threshold_value * 2, 3, false);
	findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

	dst = Mat::zeros(src.size(), CV_8UC3);
	RNG rng(12345);
	for (size_t i = 0; i < contours.size(); i++) {
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(dst, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));
	}
	imshow(output_win, dst);
}

以上代碼中主要的幾個知識點解釋下:

1.findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

發現輪廓

findContours(

InputOutputArray  binImg, // 輸入圖像,非0的像素被看成1,0的像素值保持不變,8-bit

 OutputArrayOfArrays  contours,//  全部發現的輪廓對象

OutputArrayhierachy// 圖該的拓撲結構,可選,該輪廓發現算法正是基於圖像拓撲結構實現。

int mode, //  輪廓返回的模式

int method,// 發現方法

Point offset=Point()//  輪廓像素的位移,默認(0, 0)沒有位移

)

2.drawContours(dst, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));

繪製輪廓

drawContours(

InputOutputArray  binImg, // 輸出圖像

 OutputArrayOfArrays  contours,//  全部發現的輪廓對象

Int contourIdx// 輪廓索引號

const Scalar & color,// 繪製時候顏色

int  thickness,// 繪製線寬

int  lineType ,// 線的類型LINE_8

InputArray hierarchy,// 拓撲結構圖

int maxlevel,// 最大層數, 0只繪製當前的,1表示繪製繪製當前及其內嵌的輪廓

Point offset=Point()// 輪廓位移,可選

效果如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章