图像匹配-中北android实验室计算机视觉第二讲笔记

图像匹配:颜色、纹理、大小、形状
鲁棒性(Robust):是指控制系统在一定(结构,大小)的参数摄动下,维持其它某些性能的特性。
角点: 某点与周围的点的梯度。角点是纹理的最好反映
位置发生变化 纹理几乎不变。
角点检测
FAST:
取16个点 16个里有12是白的,其他为黑的,那么这个点为角点。(计算量大)
取四个点,只要其中有三个点和其中一个点不一样那么这个点为角点
缺点:初步提取,有很多是边缘点

#include <opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
bool isdif(uchar a, uchar b) {
    if (abs(a - b) < 30) //可通过改变值调整判断条件
    {
        return false;
    }
    else 
        return true;
}
void main() {
    VideoCapture cap(0);
    while (true)
    {
        Mat frame;
        cap >> frame;
        /*
        fast 
        */
        Mat frame_rgb;
        frame.copyTo(frame_rgb);
        cvtColor(frame, frame, CV_64FC1);
    //  cout << frame.at(uchar)(0.0);
        int pos[4][2];//存储相对中心角点的位置
        pos[0][0] = 0;
        pos[0][1] = -3;
        pos[1][0] = 3;
        pos[1][1] = 0;
        pos[2][0] = 0;
        pos[2][1] = 3;
        pos[3][0] = -3;
        pos[3][1] = 0;
        for (int i = 3; i < frame.rows-3; i++)//保证内存不会溢出
        {
            for (int j = 3; j < frame.cols-3; j++) 
            {
                int num=0;//有几个角点和中-心角点不一样
                uchar cen = frame.at<uchar>(i, j);
                for (int k = 0; k < 4; k++) {
                    uchar temp = frame.at<uchar>(i + pos[k][0], j + pos[k][1]);
                    //判断temp和中心角点有没有变化
                    if (isdif(cen, temp)) {
                        num++;
                    }
                }
                if (num == 1 || num == 3 || num == 4) {
                    circle(frame_rgb,cvPoint(j, i), 2, CV_RGB(255, 0, 0), 2);
                }
            }
        }
        imshow("frame", frame_rgb);
        waitKey(10);
    }
}

HARRIS:
二维泰勒级数

        /*
        HARRIS:更多也是检测出来的边缘
        */
        for (int i = 1; i < frame.rows-1; i++) {
            for (int j = 1; j < frame.cols-1; j++) {
                double IX, IY;//当前点的导数值
                IX = frame.at<uchar>(i, j - 1) - frame.at<uchar>(i, j + 1);//x方向导数值
                IY = frame.at<uchar>(i - 1, j) - frame.at<uchar>(i + 1, j);//y方向导数值

                double R = IX*IX*IY*IY - 0.1*(IX*IX*IY*IY);//0.1可调 0.1-0.25
            //  cout << R << endl;
                if (R > 10000) 
                {
                    circle(frame_rgb, cvPoint(j, i), 1, CV_RGB(255, 0, 0), 2);
                }
            }
        }

角点检测后的二值效果图

        Mat con;
        Mat cornerStrength;
        Mat frame_gray;

        cvtColor(frame, frame_gray, CV_RGB2GRAY);
        cornerHarris(frame_gray, cornerStrength, 2, 3, 0.2);
        Mat harrisCorner;
        threshold(cornerStrength, harrisCorner, 0.00001, 255, THRESH_BINARY);
        imshow("角点检测后的二值效果图", harrisCorner);
        waitKey(10);

怎么将两个点匹配在一起?
高维向量 梯度:一阶导
按主方向截取向量 //每个角点都有主方向
欧式空间距离
二维空间的公式
0ρ = sqrt( (x1-x2)^2+(y1-y2)^2 ) |x| = √( x2 + y2 )
三维空间的公式
0ρ = √( (x1-x2)^2+(y1-y2)^2+(z1-z2)^2 ) |x| = √( x2 + y2 + z2 )
n维空间的公式
|x| = √( x[1]^2 + x[2]^2 + … + x[n]^2 )
引入ratio比率
Ratio=次大点/最大点
图像金字塔:解决尺度问题

#include <opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void FeatureMatch(Mat FrameROI1, Mat FrameROI2, vector <Point2f> &kp1, vector <Point2f> &kp2, int Flag, float ratio);
void DrawFeature(Mat &rematch, Mat Frame1, Mat Frame2, vector <Point2f> &kp1, vector <Point2f> &kp2);
void main() {
    Mat img = imread("pipei.png", 1);
    resize(img, img, cvSize(640,480));
    Mat img_gray;
    cvtColor(img, img_gray, CV_RGB2GRAY);
    VideoCapture cap(0);
    while (true)
    {
        Mat frame;
        Mat frame_gray;
        cap >> frame;
        cvtColor(frame, frame_gray, CV_RGB2GRAY);
        vector<Point2f>kp1;
        vector<Point2f>kp2;
        FeatureMatch(img_gray, frame_gray, kp1, kp2, 0, 0.8);
        Mat rematch;
        DrawFeature(rematch,img, frame, kp1, kp2);
    //  imshow("pipei",img );
//      imshow("frame", frame);
        imshow("rematch", rematch);
        waitKey(10);
    }
}

void FeatureMatch(Mat FrameROI1, Mat FrameROI2, vector <Point2f> &kp1, vector <Point2f> &kp2, int Flag, float ratio)
{
    Mat des1;
    Mat des2;
    vector <KeyPoint> keypoint1;
    vector <KeyPoint> keypoint2;


    Ptr <FeatureDetector> dector = ORB::create(500, 1.2f, 8, 31, 0, 2, ORB::FAST_SCORE, 31, 30);
    dector->detect(FrameROI1, keypoint1, Mat());
    dector->detect(FrameROI2, keypoint2, Mat());


    //Ptr <FeatureDetector> dector2 =ORB::create(50, 1.2f, 1, 31, 0, 2, ORB::FAST_SCORE, 31, 30);
    if (Flag == 0)
    {
        Ptr<DescriptorExtractor> pd0 = ORB::create(500, 1.2f, 8, 31, 0, 2, ORB::FAST_SCORE, 31, 30);
        pd0->compute(FrameROI1, keypoint1, des1);
        pd0->compute(FrameROI2, keypoint2, des2);
    }
    if (Flag == 1)
    {
        Ptr<DescriptorExtractor> pd1 = BRISK::create();
        pd1->compute(FrameROI1, keypoint1, des1);
        pd1->compute(FrameROI2, keypoint2, des2);
    }


    if ((keypoint1.size()>1) && (keypoint2.size()>1))
    {

        vector <vector<DMatch> > Vmatch;
        Ptr <DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
        matcher->knnMatch(des1, des2, Vmatch, 2);

        vector <DMatch> KNmatch;
        for (int i = 0; i < Vmatch.size(); i++)
        {
            double rat;
            if (Vmatch.at(i).at(1).distance<0.05) {
                rat = 1;
            }
            else {
                rat = Vmatch.at(i).at(0).distance / Vmatch.at(i).at(1).distance;
            }

            if (rat < ratio) {
                KNmatch.push_back(Vmatch.at(i).at(0));
            }

        }

        kp1.clear();
        kp2.clear();

        if (KNmatch.size()>0)
        {
            for (int i = 0; i<KNmatch.size(); i++)
            {
                int quaryx = KNmatch.at(i).queryIdx;
                int trainx = KNmatch.at(i).trainIdx;
                float mx = keypoint1.at(quaryx).pt.x;
                float my = keypoint1.at(quaryx).pt.y;
                float kx = keypoint2.at(trainx).pt.x;
                float ky = keypoint2.at(trainx).pt.y;
                Point2f p1;
                Point2f p2;
                p1.x = mx;
                p1.y = my;
                p2.x = kx;
                p2.y = ky;

                if (abs(ky - my)<5)
                {
                    kp1.push_back(p1);
                    kp2.push_back(p2);
                }

            }

        }

    }
    else
    {
        kp1.clear();
        kp2.clear();
    }

}
//画出来
void DrawFeature(Mat &rematch, Mat Frame1, Mat Frame2, vector <Point2f> &kp1, vector <Point2f> &kp2)
{
    rematch = Mat((Frame1.rows >= Frame2.rows) ? Frame1.rows : Frame2.rows, Frame1.cols + Frame2.cols, CV_8UC3);
    Rect rectleft(0, 0, Frame1.cols, Frame1.rows);
    Rect rectright(Frame1.cols, 0, Frame2.cols, Frame2.rows);
    Frame1.copyTo(rematch(rectleft));
    Frame2.copyTo(rematch(rectright));

    for (int i = 0; i<kp1.size(); i++)
    {
        line(rematch, cvPoint(kp1[i].x, kp1[i].y), cvPoint(Frame1.cols + kp2[i].x, kp2[i].y), CV_RGB(255, 0, 0), 2);
    }

}

测距//需两个摄像头
RANSAC算法

发布了22 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Joki233/article/details/53365844