天天看點

基于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,在我和她認識兩個月左右後,感情逐漸升溫,希望自己最終能赢得她的芳心。開心

繼續閱讀