OpenCV

您所在的位置:网站首页 pythonopencv模板匹配sifi OpenCV

OpenCV

2024-02-02 07:44| 来源: 网络整理| 查看: 265

针对不同分辨率的匹配操作 项目要求OpenCV模板匹配模板匹配的工作方式模板匹配的匹配方式模板匹配存在的问题 解决方法方法1:直方图+自适应模板匹配结果 方法二:SIFT效果 方法三:灰度匹配+模板匹配结果和结论

项目要求

有一个需要,在UI自动化中,我们需要匹配某个元素在app中的位置,如何获取该元素的位置呢?一般可以通过Automation ID或者XPath,但是,有些控件或者元素,它无法通过这种方法定位,所以,我们把问题抽象成在一张图片中,框出目标元素的位置。

OpenCV模板匹配 模板匹配的工作方式

模板匹配的工作方式跟直方图的反向投影基本一样,大致过程是这样的:通过在输入图像上滑动图像块对实际的图像块和输入图像进行匹配。 假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的: (1)从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像; (2)用临时图像和模板图像进行对比,对比结果记为c; (3)对比结果c,就是结果图像(0,0)处的像素值; (4)切割输入图像从(0,1)至(10,11)的临时图像,对比,并记录到结果图像; (5)重复(1)~(4)步直到输入图像的右下角。 大家可以看到,直方图反向投影对比的是直方图,而模板匹配对比的是图像的像素值;模板匹配比直方图反向投影速度要快一些,但是我个人认为直方图反向投影的鲁棒性会更好。

模板匹配的匹配方式 在OpenCv和EmguCv中支持以下6种对比方式: CV_TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。 CV_TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。 CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。 CV_TM_SQDIFF_NORMED 归一化平方差匹配法 CV_TM_CCORR_NORMED 归一化相关匹配法 CV_TM_CCOEFF_NORMED 归一化相关系数匹配法

根据我的测试结果来看,上述几种匹配方式需要的计算时间比较接近(跟《学习OpenCV》书上说的不同),我们可以选择一个能适应场景的匹配方式。

模板匹配存在的问题

1.对于分辨率不同的图片,它无法正常匹配。在实际的任务中,我们的模板图片可能发生分辨率的改变。 2.对于些许形变的图片,它也无法正常匹配。 3.截图内容无法匹配。

原图:原图 传统匹配结果: test

关于自适应屏幕显示:

#include #include using namespace cv; using namespace std; void Show_Picture() { Mat src = imread("C:/Users/wenhaofu/Desktop/Multi-Scale-Template-Matching-master/test3.png"); if (src.empty()) { printf("could not load image...\n"); return; } namedWindow("input", WINDOW_NORMAL); imshow("input", src); waitKey(0); return; } int main(int artc, char** argv) { Show_Picture(); return 0; }

但是为了完整得显示图片,多次尝试发现,flag参数为WINDOW_NORMAL时才可以在手动调整窗口的条件下显示完整的图片。

解决方法 方法1:直方图+自适应模板匹配 #include #include #include #include #include "histogram.h" #include "GrayMatching.h" struct Best_Rect { Point best_point; Mat best_mat; }; using namespace std; using namespace cv; int match_method = CV_TM_SQDIFF_NORMED; void template_match_demo(Mat& test1, Mat& test2); void histogram(string& s1,string& s2); //C:/Users/wenhaofu/Desktop/Multi-Scale-Template-Matching-master/test1.png //C:/Users/wenhaofu/Desktop/Multi-Scale-Template-Matching-master/button.png int main(int argc, char* argv) { string s1 = "C:/Users/wenhaofu/Desktop/Multi-Scale-Template-Matching-master/test3.png"; string s2 = "C:/Users/wenhaofu/Desktop/Multi-Scale-Template-Matching-master/button.png"; //histogram(s1,s2); clock_t start_time = clock(); graymatching(s1, s2); clock_t end_time = clock(); cout cout Mat test = test1.clone(); int new_rows = test1.rows - i * 0.05 * test1.rows; int new_cols = test1.cols - i * 0.05 * test1.cols; resize(test, test, Size(new_cols, new_rows)); int result_rows = test.rows - temp.rows + 1; int result_cols = test.cols - temp.cols + 1; Mat result(result_rows, result_cols, CV_32FC1); //模板匹配 matchTemplate(test, temp, result, match_method); //归一化 normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat()); //寻找模板匹配的最大最小匹配值 Point minLoc; Point maxLoc; Point match_loc; double min_value, max_value; minMaxLoc(result, &min_value, &max_value, &minLoc, &maxLoc, Mat()); if (match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED) { match_loc = minLoc; } else { match_loc = maxLoc; } Rect rect(match_loc.x, match_loc.y, temp.cols, temp.rows); Mat result_img = test.clone(); Mat result_img_roi = result_img(rect); double his_temp = histogram(temp, result_img_roi); Best_Rect best_rect = { match_loc,test }; record.insert(make_pair(his_temp, best_rect)); } //将待检测图中与模板匹配出框起来 auto it = record.rbegin(); /*for (it; it != record.end(); it++) { cout first second.best_mat, Rect(it->second.best_point.x, it->second.best_point.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, CV_AA); namedWindow("result", WINDOW_NORMAL); imshow("result", it->second.best_mat); return; }

histogram.h

//直方图比较 #include #include #include #include using namespace cv; using namespace std; double histogram(Mat &test1,Mat &test2){ Mat hsvtest1, hsvtest2; if (!test1.data || !test2.data) { printf("could not load image...\n"); return -1; } //步骤一:从RGB空间转换到HSV空间 cvtColor(test1, hsvtest1, CV_BGR2HSV); cvtColor(test2, hsvtest2, CV_BGR2HSV); //步骤二:计算直方图与归一化 int h_bins = 50; int s_bins = 60; int histsize[] = { h_bins,s_bins }; //hue varies from 0 to 179,saturation from 0 to 255 float h_ranges[] = { 0,180 }; float s_ranges[] = { 0,256 }; const float* histRanges[] = { h_ranges,s_ranges }; //use the 0-th and 1-st channels int channels[] = { 0,1 }; MatND hist_test1; MatND hist_test2; //计算直方图 calcHist(&hsvtest1, 1, channels, Mat(), hist_test1, 2, histsize, histRanges, true, false); calcHist(&hsvtest2, 1, channels, Mat(), hist_test2, 2, histsize, histRanges, true, false); //归一化 normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat()); normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat()); //步骤三:比较直方图,并返回值 double basetest2 = compareHist(hist_test1, hist_test2, CV_COMP_CORREL); return basetest2; }

大致思路: 给定的模板,它已经是分辨率比较低的了,我们只能改变截图,根据,每次缩放截图,我们把结果用map存起来,map的key为直方图相似度,value为Point和Rect(该点坐标和对比的图),通过,map自动排序。

结果

result

方法二:SIFT #!/usr/bin/env python # Python 2/3 compatibility from __future__ import print_function import numpy as np import cv2 def init_feature(): # SIFT匹配 detector = cv2.SIFT_create(700) # BRISK匹配 #cv2.BRISK_create() # 归一化 norm = cv2.NORM_L2 #cv2.NORM_L2 # 特征值全匹配 matcher = cv2.BFMatcher(norm) return detector, matcher def filter_matches(kp1, kp2, matches, ratio = 0.75): mkp1, mkp2 = [], [] for m in matches: if len(m) == 2 and m[0].distance = 4: H, status = cv2.findHomography(p1, p2, cv2.RANSAC, 5.0) print('%d / %d inliers/matched' % (np.sum(status), len(status))) vis = explore_match('find_obj', smaller_img1, smaller_img2, kp_pairs, status, H) cv2.waitKey() cv2.destroyAllWindows() else: print('%d matches found, not enough for homography estimation' % len(p1))

通过,缩放和SIFT。其实际效果,有时候并不好。

效果

1 2

方法三:灰度匹配+模板匹配

GrayMatching.h

#include #include #include #include using namespace cv; using namespace std; extern int match_method; struct Best_Mat { Rect best_rect; Mat best_mat; }; //相似度匹配算法之灰度值方差匹配法: double get_variance(Mat& a, Mat& b) { if (a.rows != b.rows || a.cols != b.cols || a.channels() != b.channels()) { printf("not the same size!\n"); return 0; } //处理图像相似度 //1.求出每一行到灰度值均值,加入容器,作为特征值; //2.求出灰度值总平均值与每行平均值的方差; //3.行行比较与模版方差的接近程度 vector variance_a; vector variance_b; double var_a = 0; double var_b = 0; double sum_a = 0; double sum_b = 0; double mean_a; double mean_b; double sum_variance = 0.0; //将每行灰度值均值存入容器 for (int i = 0; i mean_a += a.at(i, j); mean_b += b.at(i, j); } mean_a /= (double)(a.rows * a.cols); mean_b /= (double)(a.rows * a.cols); sum_a += mean_a; sum_b += mean_b; variance_a.push_back(mean_a); variance_b.push_back(mean_b); } //全图灰度值均值 mean_a = sum_a / (double)variance_a.size(); mean_b = sum_b / (double)variance_b.size(); //灰度值方差之差累加 for (int i = 0; i //加载图像 Mat org = imread(s1); Mat my_template = imread(s2); if (org.empty() || my_template.empty()) { cout rect ,temp_template }; arr.insert(make_pair(variance_diff, best_mat)); } auto it = arr.begin(); rectangle(it->second.best_mat, it->second.best_rect, Scalar(255, 0, 0), 3); namedWindow("result", WINDOW_NORMAL); imshow("result", it->second.best_mat); waitKey(0); return; } 结果和结论

gary button

on off

test1

2 1 直方图8.186s,灰度匹配2.212s,此方法速度快。而且,匹配精度高。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3