影醉阏轩窗

衣带渐宽终不悔,为伊消得人憔悴。
扩大
缩小

《opencv学习》 之 特征检测与匹配

这几天学习SURF特征检测,直接看的视频和书本有点吃不消,现在是基本看懂了,如果写博客记录没有必要,因为网上都差不多,笔记都在书上了,以下是个人认为比较浅显易懂的文章,当然海有很多好文章我没看到。

看第一篇入门就可以,后面讲的不是很好: http://blog.csdn.net/jwh_bupt/article/details/7621681

harris:                  http://www.cnblogs.com/ronny/p/4009425.html

Harr:                 http://blog.csdn.net/zouxy09/article/details/7929570/

Box Filters:              http://blog.csdn.net/lanbing510/article/details/28696833

SIFT:                 http://blog.csdn.net/abcjennifer/article/details/7639681/                                             http://blog.csdn.net/pi9nc/article/details/23302075

Harr小波特征:             场合不同这个表示也不同,比如在SURF中表示dx、dy,当然也可以表示成其它样子,得看Harr的内核

SURF:                 看一下毛星云的那本书,其实网上说的差不多。

ORB:                 http://www.aiuxian.com/article/p-1728722.html,里面包括FAST特征点、BRIEF描述子

HOG:                 这个算法相对比较上面容易理解。

LBP:                  http://blog.csdn.net/quincuntial/article/details/50541815这个算法可以手写实现,上面基本自己都实现不了(难度很大)

双线性插值:             百度百科有(先有三角函数计算坐标位置,然后用双线性插值计算像素值)

LBP算子

 经典LBP算法:
1
int main(int argc, char**argv) 2 { 3 Mat input_image, Middle_image,threshold_image; 4 input_image = imread("1.jpg"); 5 if (input_image.data == NULL) { 6 return -1; cout << "can't open image.../"; 7 } 8 cvtColor(input_image, input_image, CV_BGR2GRAY); 9 Mat output_image; 10 output_image.create(Size(input_image.rows - 2, input_image.cols - 2), input_image.type()); 11 output_image.setTo(0, Mat()); 12 int width = input_image.cols * input_image.channels(); 13 int heigth = input_image.rows; 14 for (size_t i = 1; i < heigth - 1; i++) 15 { 16 //uchar *ptr = input_image.ptr<uchar>(i); 17 for (size_t j = 1; j < width - 1; j++) 18 { 19 uchar code = 0; 20 uchar center = input_image.at<uchar>(i, j); 21 code |= (input_image.at<uchar>(i - 1, j - 1) >= center) << 7; 22 code |= (input_image.at<uchar>(i - 1, j ) >= center) << 6; 23 code |= (input_image.at<uchar>(i - 1, j + 1) >= center) << 5; 24 code |= (input_image.at<uchar>(i , j - 1) >= center) << 4; 25 code |= (input_image.at<uchar>(i , j + 1) >= center) << 3; 26 code |= (input_image.at<uchar>(i + 1, j - 1) >= center) << 2; 27 code |= (input_image.at<uchar>(i + 1, j ) >= center) << 1; 28 code |= (input_image.at<uchar>(i + 1, j + 1) >= center) << 0; 29 output_image.at<uchar>(i - 1, j - 1) = code; 30 } 31 } 32 imshow("LineImage", input_image); 33 imshow("output_image", output_image); 34 35 waitKey(0); 36 return 0; 37 }

 

 

 CLBP:
1
#include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 const int neighbor = 8;//圆周上共几个像素 8 const int radius = 3; 9 10 int main(int argc, char**argv) 11 { 12 Mat input_image, output_image; 13 input_image = imread("1.jpg"); 14 15 if (input_image.data == NULL) { 16 return -1; cout << "can't open image.../"; 17 } 18 cvtColor(input_image, input_image, CV_BGR2GRAY); 19 //Mat output_image = Mat::zeros(Size(input_image.cols - 2 * 30, input_image.rows - 2 * 30), CV_8UC1); 20 output_image.create(Size(input_image.cols - 2* radius, input_image.rows - 2*radius), CV_8UC1); 21 output_image.setTo(0); 22 int width = input_image.cols; 23 int height = input_image.rows; 24 25 26 for (size_t n = 0; n < neighbor; n++) 27 { 28 //-----计算圆边长点的坐标(这里x、y具体谁用cos和sin的结果一样,看后来计算双线性插值自己怎么理解了) 29 float x = static_cast<float>(radius) * cos(2.0 * CV_PI*n / static_cast<float>(neighbor)); 30 float y = static_cast<float>(-radius) * sin(2.0 * CV_PI*n / static_cast<float>(neighbor));//这里加不加负号效果一样,因为是点的顺序而已。 31 //-----计算圆边上点的像素值,用双线性插值方法 32 int fx = static_cast<int>(floor(x)); 33 int fy = static_cast<int>(floor(y));//上采样 34 int cx = static_cast<int>(ceil(x)); 35 int cy = static_cast<int>(ceil(y));//下采样 36 37 float dx = x - fx; 38 float dy = y - fy; 39 40 float w1 = (1 - dx)*(1 - dy); 41 float w2 = dx*(1 - dy); 42 float w3 = (1 - dx)*dy; 43 float w4 = dx*dy; 44 45 for (size_t i = radius; i < height - radius; i++) 46 { 47 for (size_t j = radius; j < width - radius; j++) 48 { 49 float p1 = input_image.at<uchar>(i + fy, j + fx); 50 float p2 = input_image.at<uchar>(i + fy, j + cx); 51 float p3 = input_image.at<uchar>(i + cy, j + fx); 52 float p4 = input_image.at<uchar>(i + cy, j + cx); 53 54 float Angle_data = p1*w1 + p2*w2 + p3*w3 + p4*w4; 55 output_image.at<uchar>(i - radius, j - radius) |= (((input_image.at<uchar>(i, j) >= Angle_data) && (std::abs(Angle_data-input_image.at<uchar>(i,j)) > numeric_limits<float>::epsilon())) << n); 56 } 57 58 } 59 } 60 61 imshow("LineImage", input_image); 62 imshow("output_image", output_image); 63 64 waitKey(0); 65 return 0; 66 }

 LBP后面还有很多知识,现在不学习那么深,只是了解一下,以后用到再继续深入。

SIFT算子

 1 #if 1
 2 #include <opencv2/opencv.hpp>
 3 #include <opencv2/xfeatures2d.hpp>
 4 #include <iostream>
 5 #include "math.h"
 6 
 7 using namespace cv::xfeatures2d;
 8 using namespace cv;
 9 using namespace std;
10 
11 void calSIFTFeatureAndCompare(Mat& src1, Mat& src2);
12 
13 int main(int argc, char**argv)
14 {
15     Mat input_image1, input_image2;
16     input_image1 = imread("hand1.jpg");
17     input_image2 = imread("hand2.jpg");
18 
19     if (!input_image1.data && !input_image2.data) {
20         return -1; cout << "can't open image.../";
21     }
22     calSIFTFeatureAndCompare(input_image1, input_image2);
23     /*imshow("input_image1", input_image1);
24     imshow("input_image2", input_image2);*/
25 
26     waitKey(0);
27     return 0;
28 }
29 //-------------特征点:如同harris等检测的点一样(当然加了更多的约束)--------------//
30 //-------------描述子:点形成组织性,有方向和区域等,更能代表整副图像(也就是在特征点上加了更多的约束) --------------//
31 void calSIFTFeatureAndCompare(Mat& src1,Mat& src2)
32 {
33     Mat grayMat1, grayMat2;
34     cvtColor(src1, grayMat1, CV_BGR2GRAY);
35     cvtColor(src2, grayMat2, CV_BGR2GRAY);
36     normalize(grayMat1, grayMat1, 0, 255, CV_MINMAX);
37     normalize(grayMat2, grayMat2, 0, 255, CV_MINMAX);
38     /*//---定义SIFT描述子
39     SiftFeatureDetector        detector; //计算特征点
40     SiftDescriptorExtractor extractor;//计算描述子
41     //---特征点检测
42     vector<KeyPoint> keypoints1;
43     vector<KeyPoint> keypoints2;
44     detector.detect(grayMat1, keypoints1, Mat());
45     detector.detect(grayMat2, keypoints2, Mat());
46     //---计算特征点描述子
47     Mat descriptors1, descriptors2;
48     extractor.compute(grayMat1, keypoints1, descriptors1);
49     extractor.compute(grayMat2, keypoints2, descriptors2);*/
50     //SURF* detector = SURF::create(100);//那道理说是可以的,但是奔溃,不知道原因
51     Ptr<SURF> detector = SURF::create(500);//这个参数hessianThreshold为海深矩阵的阈值T,看SIFT原理就可
52     vector<KeyPoint> keypoints1;
53     vector<KeyPoint> keypoints2;
54     Mat descriptors1, descriptors2;
55     //---特征点和描述子一起检测了
56     detector->detectAndCompute(grayMat1, Mat(), keypoints1, descriptors1);
57     detector->detectAndCompute(grayMat2, Mat(), keypoints2, descriptors2);
58     //---特征点匹配
59     vector<DMatch> matches;//存储匹配结果的类,和keypoint类似
60     BFMatcher matcher(NORM_L1); //NORM_L1:代表SIFT,NORM_L2:代表SURF,默认SURF
61     matcher.match(descriptors1, descriptors2, matches);
62     Mat resultMatch;
63     drawMatches(grayMat1, keypoints1, grayMat2, keypoints2, matches, resultMatch);
64 }
65 
66 #endif

 

实际图片的匹配与寻找

 

 

 在原图上截取的一个小图片进行测试---->>>>

                     本文利用SURF算子进行检测,利用FLANN进行匹配!

 

 

 

 上代码:

 1 #if 1
 2 #include <opencv2/opencv.hpp>
 3 #include <opencv2/xfeatures2d.hpp>
 4 #include <iostream>
 5 #include "math.h"
 6 
 7 using namespace cv::xfeatures2d;
 8 using namespace cv;
 9 using namespace std;
10 
11 
12 int main(int argc, char**argv)
13 {
14     Mat input_image1, input_image2;
15     input_image1 = imread("2.jpg");
16     input_image2 = imread("1.jpg");
17 
18     if (!input_image1.data && !input_image2.data) {
19         return -1; cout << "can't open image.../";
20     }
21     //-------------keypoints and descriptor detection
22     const int minHessian = 400;
23     Ptr<SURF> detector = SURF::create(minHessian);
24     vector<KeyPoint> srcKeyPoint, dstKeyPoint;
25     Mat srcDescriptor, dstDescriptor;
26     detector->detectAndCompute(input_image1, Mat(), srcKeyPoint, srcDescriptor);
27     detector->detectAndCompute(input_image2, Mat(), dstKeyPoint, dstDescriptor);
28     //------------FLANN algorithm match
29     FlannBasedMatcher matcher;
30     vector<DMatch> matches;
31     matcher.match(srcDescriptor, dstDescriptor, matches);
32     Mat matchImage;
33     drawMatches(input_image1, srcKeyPoint, input_image2, dstKeyPoint, matches, matchImage);
34     //------------calculate best keypoint
35     double maxDistance = 0, minDistance = 10000;
36     for (size_t i = 0; i < matches.size(); i++)
37     {
38         maxDistance = maxDistance < matches[i].distance ? matches[i].distance : maxDistance;
39         minDistance = minDistance < matches[i].distance ? minDistance : matches[i].distance;
40     }
41     vector<DMatch> bestMatches;
42     for (size_t i = 0; i < matches.size(); i++)
43     {
44         if (matches[i].distance < 3 * minDistance)
45         {
46             bestMatches.push_back(matches[i]);
47         }
48     }
49     Mat bestMatchImage;
50     drawMatches(input_image1, srcKeyPoint, input_image2, dstKeyPoint, bestMatches, bestMatchImage);
51     //-----------Find four corner points from bestMatches
52     vector<Point2f> srcPoint;
53     vector<Point2f> dstPoint;
54     for (size_t i = 0; i < bestMatches.size(); i++)//save coordinate to srcPoint/dstPoint from bestMatches
55     {
56         srcPoint.push_back(srcKeyPoint[bestMatches[i].queryIdx].pt);
57         dstPoint.push_back(dstKeyPoint[bestMatches[i].trainIdx].pt);
58     }
59     Mat H = findHomography(srcPoint, dstPoint,CV_RANSAC);//detection perspective Mapping(H映射)
60     vector<Point2f> srcCorners(4);
61     vector<Point2f> dstCorners(4);
62     srcCorners[0] = Point(0, 0);
63     srcCorners[1] = Point(input_image1.cols, 0);
64     srcCorners[2] = Point(0, input_image1.rows);
65     srcCorners[3] = Point(input_image1.cols, input_image1.rows);
66     perspectiveTransform(srcCorners, dstCorners, H);//detection destination Corners
67     line(input_image2, dstCorners[0], dstCorners[1], Scalar(255, 255, 0), 2);
68     line(input_image2, dstCorners[0], dstCorners[2], Scalar(255, 255, 0), 2);
69     line(input_image2, dstCorners[1], dstCorners[3], Scalar(255, 255, 0), 2);
70     line(input_image2, dstCorners[2], dstCorners[3], Scalar(255, 255, 0), 2);
71     waitKey(0);
72     return 0;
73 }
74 
75 
76 #endif

 

posted on 2017-05-09 08:57  影醉阏轩窗  阅读(870)  评论(0编辑  收藏  举报

导航

/* 线条鼠标集合 */ /* 鼠标点击求赞文字特效 */ //带头像评论