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()// 轮廓位移,可选

效果如下:

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