文章目錄
- 前言
- 一、主要步驟
-
- 1.窗體設計
- 2.引用命名空間
- 3.主要算法
- 3.結果
- 總結
- 題外話
前言
本blog是該系列文章的第一篇demo,主要功能是實作書本的目标檢測,主要算法是用了sift特征比對。
一、主要步驟
1.窗體設計
該窗體主要用到了兩個imagebox,三個button,整體形狀如圖

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的一個demo,将過程總結下來,與各位分享。希望有小夥伴能積極提出算法改進意見,大家共同進步。
題外話
本人喜歡的女生,暫且叫她小q,在我和她認識兩個月左右後,感情逐漸升溫,希望自己最終能赢得她的芳心。開心