天天看点

基于emgucv和c#的书本特征匹配前言一、主要步骤总结题外话

文章目录

  • 前言
  • 一、主要步骤
    • 1.窗体设计
    • 2.引用命名空间
    • 3.主要算法
    • 3.结果
  • 总结
  • 题外话

前言

本blog是该系列文章的第一篇demo,主要功能是实现书本的目标检测,主要算法是用了sift特征匹配。

一、主要步骤

1.窗体设计

该窗体主要用到了两个imagebox,三个button,整体形状如图

基于emgucv和c#的书本特征匹配前言一、主要步骤总结题外话

2.引用命名空间

该功能需要引用

emgu.cv,

emgu.cv.contrib,

emgu.cv.ui,

emgu.cv.uti

四个dll库,相应的命名空间如下

using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.Features2D;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using Emgu.CV.XFeatures2D;
using System.Drawing;
using System;
           

3.主要算法

namespace cornors_detect
{
    public partial class Form1 : Form
    {
       
        public Form1()
        {
            InitializeComponent();
        }
        //定义所需的变量及实例化对象
        Mat scr = new Mat();
        Mat dst = new Mat();
        VectorOfKeyPoint scr_keypoints = new VectorOfKeyPoint();
        VectorOfKeyPoint dst_keypoints = new VectorOfKeyPoint();
        Mat scr_descriptor = new Mat();
        Mat dst_descriptor = new Mat();
        Mat result = new Mat();
        VectorOfVectorOfDMatch matchs = new VectorOfVectorOfDMatch();
        Mat transmat = new Mat();
        BFMatcher match = new BFMatcher(DistanceType.L2);

        //实例化sift和surf对象
        SIFT sift = new SIFT();
        SURF surf = new SURF(300);
        //实例化其他角点检测对象,可根据需要自行选择
        //GFTTDetector _gftt = new GFTTDetector();
        //AKAZE _akaze = new AKAZE();
        //Brisk _brisk = new Brisk();
        //SimpleBlobDetector blob = new SimpleBlobDetector();
        //ORBDetector orb = new ORBDetector();
        //BriefDescriptorExtractor brief = new BriefDescriptorExtractor();
        
       



        private void loadimgbtn_Click(object sender, EventArgs e)
        {
            OpenFileDialog op = new OpenFileDialog();
            if(op.ShowDialog()==DialogResult.OK)
            {
                scr = new Mat(op.FileName,LoadImageType.AnyColor);
               
            }
            //显示加载的模板图片
            imageBox1.Image = scr;
            
        }

        private void correcogbtn_Click(object sender, EventArgs e)
        {
            //用sift或者surf方法获得模板和匹配图像的关键点和描述子
            //surf.DetectAndCompute(scr, null, scr_keypoints, scr_descriptor, false);
            //surf.DetectAndCompute(dst, null, dst_keypoints, dst_descriptor, false);
            sift.DetectAndCompute(scr, null, scr_keypoints, scr_descriptor, false);
            sift.DetectAndCompute(dst, null, dst_keypoints, dst_descriptor, false);
            //在模板和匹配图像上分别绘制关键点
            Features2DToolbox.DrawKeypoints(scr, scr_keypoints, scr, new Bgr(0, 0, 255), Features2DToolbox.KeypointDrawType.Default);
            Features2DToolbox.DrawKeypoints(dst, dst_keypoints, dst, new Bgr(0, 0, 255), Features2DToolbox.KeypointDrawType.Default);
           
            //将模板描述子加入匹配方法中
            match.Add(scr_descriptor);
            //利用knn方法对模板和匹配图像进行关键点匹配
            match.KnnMatch(dst_descriptor, matchs,2,null);
            
            //过滤一些匹配不准确的点
            Mat mask = new Mat(matchs.Size, 1, DepthType.Cv8U, 1);
            mask.SetTo(new MCvScalar(1));
            //投票阈值筛选掉重复的点
            Features2DToolbox.VoteForUniqueness(matchs, 0.8, mask);
            //进行尺度旋转筛选
            Features2DToolbox.VoteForSizeAndOrientation(scr_keypoints, dst_keypoints, matchs, mask, 1.5, 20);
            //绘制匹配图像
            Features2DToolbox.DrawMatches(scr, scr_keypoints, dst, dst_keypoints, matchs, result, new MCvScalar(255, 255, 255), new MCvScalar(0, 0, 255), mask);
            
            //得到模板和匹配图片的仿射矩阵
            transmat = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(scr_keypoints, dst_keypoints, matchs, mask, 3);
            // 得到模板图像中书的矩形区域
            Rectangle rec = new Rectangle(Point.Empty, scr.Size);
            //提取矩形区域的四个顶点,为后面定位匹配图像中的书做准备
            PointF[] pts = new PointF[]
            {
                new PointF(rec.Left,rec.Bottom),
                new PointF(rec.Right,rec.Bottom),
                new PointF(rec.Right,rec.Top),
                new PointF(rec.Left,rec.Top)
                
            };
            //定位匹配图像中的书
            pts = CvInvoke.PerspectiveTransform(pts, transmat);
            //绘制出匹配图像中的书
            Point[] points = Array.ConvertAll<PointF, Point>(pts, Point.Round);
            using (VectorOfPoint vp = new VectorOfPoint(points))
            {
                CvInvoke.Polylines(result, vp, true, new MCvScalar(255, 0, 0), 4);
            }

            imageBox1.Image = scr;
            imageBox2.Image = result;

        }

        private void loadimg2btn_Click(object sender, EventArgs e)
        {
            OpenFileDialog op2 = new OpenFileDialog();
            if(op2.ShowDialog()==DialogResult.OK)
            {
                dst = new Mat(op2.FileName, LoadImageType.AnyColor);

            }
            //加载匹配图片
            imageBox2.Image = dst;

        }
    }
}
           

3.结果

本blog选取的模板图片是一本书,匹配效果较好,但后面将模板图片换成圆柱形的盒子,匹配效果很差,该算法还有待改进

基于emgucv和c#的书本特征匹配前言一、主要步骤总结题外话

总结

这是本人最近学习emgucv的一个demo,将过程总结下来,与各位分享。希望有小伙伴能积极提出算法改进意见,大家共同进步。

题外话

本人喜欢的女生,暂且叫她小q,在我和她认识两个月左右后,感情逐渐升温,希望自己最终能赢得她的芳心。开心

继续阅读