opencv3.2——小试牛刀(1):使用鼠标选择ROI进行SURF匹配
来源:互联网 发布:康耐视视觉软件下载 编辑:程序博客网 时间:2024/06/09 02:35
1.目的
匹配图片的时候,总有其他物体干扰着匹配成功率。所以选择需要的物体进行匹配就现得很重要。所以,本文尝试选择了使用鼠标交互的方法选择物体,并进行运算速度快而且匹配率高的SURF算法进行匹配。本程序优点:鼠标交互,重复选择物体框直到选择到最佳物体框。
2.代码实现
#include<opencv2/opencv.hpp>#include<iostream>#include"opencv2/xfeatures2d.hpp"#include<opencv2/highgui/highgui.hpp>using namespace cv;using namespace std;using namespace cv::xfeatures2d;using namespace cv::ml;#define WINDOW_NAME "【程序窗口】"void on_MouseHandle(int event, int x, int y, int flags, void*param);void DrawRectangle(cv::Mat& img, cv::Rect box);Rect g_rectangle;bool g_bDrawingBox = false;//是否进行绘制RNG g_rng(12345);int main(int argc, char **argv){//【1】准备参数Mat srcImage = imread("1.jpg");g_rectangle = Rect(-1, -1, 0, 0);//【2】设置鼠标操作回调函数namedWindow(WINDOW_NAME);setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);while (1){if (waitKey(10) == 27) { break; }//esc键,程序退出imshow(WINDOW_NAME, srcImage);}//ROIMat imageROI = srcImage(g_rectangle);Mat imageROIG;//预备 cvtColor ( imageROI ,imageROIG, CV_RGB2GRAY);//SURFMat a = imageROIG; //读取灰度图像Mat b = imread("2.jpg", 0);Ptr<SURF> surf; //创建方式和opencv2中的不一样 //Ptr<SIFT> sift;surf = SURF::create(900, 5, 4); //阈值BFMatcher matcher; //匹配器Mat c, d;vector<KeyPoint> key1, key2;vector<DMatch> matches;//结果为一个Mat矩阵,它的行数与特征点向量中元素个数是一致的。每行都是一个N维描述子的向量surf->detectAndCompute(a, Mat(), key1, c); //检测关键点和匹配描述子surf->detectAndCompute(b, Mat(), key2, d);matcher.match(c, d, matches); // 匹配,得到匹配向量sort(matches.begin(), matches.end()); // 匹配点排序vector< DMatch > good_matches; // 匹配两幅图像的描述子int ptsPairs = min(50, (int)(matches.size() * 0.15));cout << ptsPairs << endl;for (int i = 0; i < ptsPairs; i++) // 将匹配较好的特征点存入good_matches中{good_matches.push_back(matches[i]);}Mat outimg;drawMatches( // 绘制匹配点a, // 原图像1key1, // 原图像1的特征点b, // 原图像2key2, // 原图像2的特征点good_matches, // 原图像1的特征点匹配原图像2的特征点[matches[i]]outimg, // 输出图像具体由flags决定Scalar::all(-1), // 匹配的颜色(特征点和连线),若matchColor==Scalar::all(-1),颜色随机Scalar::all(-1), // 单个点的颜色,即未配对的特征点,若matchColor==Scalar::all(-1),颜色随机vector<char>(), // Mask决定哪些点将被画出,若为空,则画出所有匹配点DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); //Fdefined by DrawMatchesFlagsvector<Point2f> obj;vector<Point2f> scene;for (size_t i = 0; i < good_matches.size(); i++){////good_matches[i].queryIdx保存着第一张图片匹配点的序号,keypoints_1[good_matches[i].queryIdx].pt.x 为该序号对应的点的x坐标obj.push_back(key1[good_matches[i].queryIdx].pt);scene.push_back(key2[good_matches[i].trainIdx].pt);}vector<Point2f> scene_corners(4);vector<Point2f> obj_corners(4);obj_corners[0] = Point(0, 0);obj_corners[1] = Point(a.cols, 0);obj_corners[2] = Point(a.cols, a.rows);obj_corners[3] = Point(0, a.rows);Mat H = findHomography( // 在两个平面之间寻找单映射变换矩阵obj, // 在原平面上点的坐标scene, // 在目标平面上点的坐标4); // 用于计算单映射矩阵的方法perspectiveTransform( // 向量组的透视变换obj_corners, // 输入两通道或三通道的浮点数组,每一个元素是一个2D/3D 的矢量转换scene_corners, // 输出和src同样的size和typeH); // 3x3 或者4x4浮点转换矩阵// 绘制line(outimg, scene_corners[0] + Point2f((float)a.cols, 0), scene_corners[1] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);line(outimg, scene_corners[1] + Point2f((float)a.cols, 0), scene_corners[2] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);line(outimg, scene_corners[2] + Point2f((float)a.cols, 0), scene_corners[3] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);line(outimg, scene_corners[3] + Point2f((float)a.cols, 0), scene_corners[0] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);namedWindow("匹配图", 0);imshow("匹配图", outimg);waitKey(-1);return 0;}void on_MouseHandle(int event, int x, int y, int falgs, void* param){Mat& image = *(cv::Mat*)param;switch (event){//鼠标移动消息case EVENT_MOUSEMOVE:{if (g_bDrawingBox) //标识符为真,则记录下长和宽到Rect型变量中{g_rectangle.width = x - g_rectangle.x;g_rectangle.height = y - g_rectangle.y;}}break;//左键按下信号case EVENT_LBUTTONDOWN:{cout << " EVENT_LBUTTONDOWN" << endl;g_bDrawingBox = true;g_rectangle = Rect(x, y, 0, 0);//记录起点}break;//左键抬起信号case EVENT_LBUTTONUP:{cout << " EVENT_LBUTTONUP" << endl;g_bDrawingBox = false;//对宽高小于0的处理if (g_rectangle.width < 0){g_rectangle.x += g_rectangle.width;g_rectangle.width *= -1;}if (g_rectangle.height < 0){g_rectangle.y += g_rectangle.height;g_rectangle.height *= -1;}//调用绘制函数DrawRectangle(image, g_rectangle);}break;}}void DrawRectangle(cv::Mat& img, cv::Rect box){rectangle(img, box.tl(), box.br(), Scalar(0, 0, 225));}
效果图
(1)不同的物体匹配的效果图:
匹配结果显示不是同一物体,无识别框形成,识别线凌乱。
(2)同一物体,旋转拍摄得不同画面,两个画面进行匹配的效果图:
匹配成功,识别框明显,识别线整齐。
注意事项
1.图片的像素要较高。(电脑摄像头以上,电脑摄像头拍摄的图片要靠近摄像头,或者匹配的物体特征明显如文字。)
2.没有xfreatures2d模块的访客可以借鉴博主以前的博客,opencv3.2的xfeatures2d模块(nofree模块)现放置到第三方库。
3.鼠标交互可以重复选择所需识别物体框,取最后一次物体框为最终物体框。按esc键退出选择物体框,并进行识别,识别窗口按任意键退出,程序结束。
心得体会
opencv的函数库比较强大,大大减少了编写程序的复杂程度。对于初学者而言是不错的机器视觉入门的途径。
0 0
- opencv3.2——小试牛刀(1):使用鼠标选择ROI进行SURF匹配
- opencv3.1 surf特征匹配
- opencv3.2 SURF实现特征点匹配
- opencv 鼠标选择ROI
- OpenCV247 鼠标选择ROI区域
- opencv3中FLANN结合SURF进行关键点的描述和匹配
- python3.5 opencv3.1 不能使用sift, surf。
- OpneCV_ImageMatching with SURF and SIFT(使用SURF和 SIFT进行图像匹配 对比)
- OpenCV目标追踪鼠标选择ROI区域
- OpenCV利用鼠标进行矩形ROI选取
- opencv3.0 无法使用FeatureDetector.SURF
- opencv3中使用FLANN进行特征点匹配
- OpenCV3中的SURF特征点的寻找和匹配
- 【OpenCV】OpenCV3中的SURF特征点的寻找和匹配
- opencv 图片上进行ROI选择
- openCV3.1中的sift和surf编译
- 【OpenCV3】将图像指定区域使用另一图像(或ROI)覆盖
- opencv3 实现模版匹配-鼠标事件
- Dojo 学习--ADM
- 蓝桥杯 历届试题 神奇算式
- leetcode 367. Valid Perfect Square(golang解题)
- Less学习心得
- 数据链路层相关概念
- opencv3.2——小试牛刀(1):使用鼠标选择ROI进行SURF匹配
- Lua UserData
- java web目录结构的理解
- Python中super()函数简介及用法分享
- Android Studio快捷键大全
- Android在子线程更新UI方式总结
- 计算机组成原理
- 4059: [Cerc2012]Non-boring sequences
- C语言寻找BUG