又是选修课,今天讲自动配准和半自动配准。

自动配准就是我们一个点也不选,程序自动进行角点检测和匹配;

而半自动配准,以仿射变换六参数为例,我们需要先选3个点,确定最初的参数,然后在角点匹配中 检查一个点 经过该六参数变换后 得到的点 与 检测出来的点的误差 是否合格(误差限制是主观确定的)。接下来我们看实现:

1.安装OpenCVSharp

C#很方便,我们在Nuget中搜索安装以下三个包即可,这里就不教大家安装了,网上很多教程。

2.Bitmap to Mat

首先我们知道,OpenCV中进行运算的类是 Mat (Matrix的缩写),那我们要使用OpenCV进行角点检测,就需要将图片转为Mat。

我们知道,在Gdal导入图片时,一般是将图片转为Bitmap进行显示。那么,在保持高宽比的情况下,使用仅放大缩小后的图片求出来的仿射变换参数,也可以使用在原始大小的图片上(不知道大家能不能理解)。

知道了这一点,那么我们就可以使用保持高宽比的显示出来的Bitmap图来进行OpenCV上的操作。

3.代码

贴代码的方式沿袭Part9,会将每一句的作用,当然,仅供参考。大家知道了各个函数的作用可以更灵活的放到自己的代码中。

首先,我们讲半自动配准。

        半自动配准是在参数已经求出来的情况下进行配准。

注意,以下的代码中有这么几种我的命名习惯:

TsF:Transform的缩写,代表仿射变换六参数,值为 double[6]{a, b, c, d, e, f}

Cor:前后缀,代表Corrected,待矫正的,用来指待矫正的图像,或者待矫正的图像上的点

Ref:前后缀,代表Reference,参考,用来指参考图像,或者待参考图像上的点

接下来,看一下Bitmap转为Mat的代码:

            OpenCvSharp.Mat Cor_mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(待矫正影像Bitmap变量名);OpenCvSharp.Mat Ref_mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(参考影像Bitmap变量名);

然后,我们需要一个容器存储找出的对应点,这个容器中每一个元素应该是 一对 对应点,那我们就来创造这个容器:

var points = new System.Collections.Generic.List<System.Drawing.Point[]>();

我们可以看到创造了一个容器,容器里每一个元素都是Point[ ],所以我们就可以将 每一对 对应点 组成一个 Point数组,它的长度应该是2,一个待矫正点,一个参考点。

创造完了装载结果的容器,我们接下来创造特征提取的模型,这里用的是SIFT算法:

var model = OpenCvSharp.Features2D.SIFT.Create();

这样,我们就实例化了一个SIFT模型。接下来我们看一下这个模型检测特征点和提取特征点描述符的函数,源代码里是这样的:

public virtual void DetectAndCompute(

InputArray image, //需要检测的图像

InputArray? mask, //掩膜,一般为null

out KeyPoint[] keypoints, //存储关键点的数组

OutputArray descriptors, //存储描述符的Mat对象

bool useProvidedKeypoints = false); //一般不选

接下来就是引用:

            Mat Desc_Cor = new Mat();//接收特征描述符的MatMat Desc_Ref = new Mat();//接收特征描述符的MatKeyPoint[] KP_Cor, KP_Ref;//接收keypoints的对象//进行检测与特征描述符提取model.DetectAndCompute(Cor_mat, null, out KP_Cor, Desc_Cor);model.DetectAndCompute(Ref_mat, null, out KP_Ref, Desc_Ref);

到此,我们拥有了两幅图片的特征点(KP_Cor,KP_Ref),

及其特征描述(Descriptor)符(Desc_Cor,Desc_Ref)。

于是就可以进行匹配:

            var FBmatcher = new OpenCvSharp.FlannBasedMatcher();//实例化匹配器var matches = FBmatcher.Match(Desc_Cor, Desc_Ref);//对特征描述符进行匹配

这下,匹配结果就全都放在了matches这一变量中。

要如何访问 matches 里某一对点的信息呢?我们假设需要访问 第i对点 的信息:

通过以下属性获得 第i个点对中的 待矫正点在待矫正点集的位置 与 参考点在参考集的位置

matches[i].QueryIdx //第i个点对的待矫正点在待矫正点集的索引

matches[i].TrainIdx //第i个点对的参考点在参考点集的索引

我们知道,待矫正点集的变量名为KP_Cor,参考点集的变量名为KP_Ref,那么我们就可以用下面的代码访问 第i对点的 待矫正点的XY坐标 与 参考点的XY坐标:

KP_Cor[matches[i].QueryIdx].Pt.X

KP_Cor[matches[i].QueryIdx].Pt.Y //第i对点的 待矫正点的XY坐标

KP_Ref[matches[i].TrainIdx].Pt.X

KP_Ref[matches[i].TrainIdx].Pt.Y //第i对点的 参考点的XY坐标

获得了这对点的坐标,我们假设为Xc,Yc,Xr,Yr(c代表待矫正,r代表参考)。

那么就可以使用我们的仿射变换六参数来验证啦~

假设仿射变换后:

计算点(X,Y)与点(Xr,Yr)的距离(一般使用欧氏距离)是否符合条件(如:5,8,10),若符合条件的就把这一对match中的两个XY坐标放入我们定义的接受结果的容器中即可。

假设 matches 中 第i个点对 符合条件:

        System.Drawing.Point[] p = new System.Drawing.Point[2];p[0].X = (int)Math.Round(KP_Cor[matches[i].QueryIdx].Pt.X);p[0].Y = (int)Math.Round(KP_Cor[matches[i].QueryIdx].Pt.Y);p[1].X = (int)Math.Round(KP_Ref[matches[i].TrainIdx].Pt.X);p[1].Y = (int)Math.Round(KP_Ref[matches[i].TrainIdx].Pt.Y);points.Add(p);

如此,最后 return points 即可得到符合条件的点对,自动配准的任务也就完成了,返回了一个装载着点对的数组。数组中的元素访问方式如下:

points[1]  //第2个点对

points[50][0] //第51个点对的待矫正点

points[32][1].X //第33个点对的参考点的X坐标

接下来就是全自动配准,其实全自动配准的结果往往很难说,不过我在这儿也给大家讲一讲。

全自动配准呢,到上边的获得matches,以及往上的部分,都是一样的。

            var FBmatcher = new OpenCvSharp.FlannBasedMatcher();//实例化匹配器var matches = FBmatcher.Match(Desc_Cor, Desc_Ref);//对特征描述符进行匹配

我们获得了matches,在半自动配准中我们有 TsF 这个参考的系数,依据已知的参数来定夺点的取舍;而全自动配准中没有。

我们的想法是,在 matches 中找到差异最小的点对,点对的差异可以通过以下函数访问:

        double dist = matches[i].Distance;

我们把 最小差异值的 n(人为定义,可以是2,3...) 倍 作为阈值,差异小于这个值的我们称之为好的匹配点,再将这些好的匹配点像上面的代码一样放到points里即可。

                double max_dist = 0, min_dist = 1000;for (int i = 1; i < matches.Length; ++i){double dist = matches[i].Distance;if (dist > max_dist)max_dist = dist;if (dist < min_dist)min_dist = dist;}

获取了 最小差异值:min_dist,接下来就是for遍历matches,当点对的差异值小于阈值,就像上面的代码一样,将这个点对纳入其中:

        System.Drawing.Point[] p = new System.Drawing.Point[2];p[0].X = (int)Math.Round(KP_Cor[matches[i].QueryIdx].Pt.X);p[0].Y = (int)Math.Round(KP_Cor[matches[i].QueryIdx].Pt.Y);p[1].X = (int)Math.Round(KP_Ref[matches[i].TrainIdx].Pt.X);p[1].Y = (int)Math.Round(KP_Ref[matches[i].TrainIdx].Pt.Y);points.Add(p);

好!自动配准的内容就到此。

PS:大家也可以选择不同的检测模型,如:Surf,可以试试它们的效果,我也没试过不知道怎么样。

C# GDAL 数字图像处理Part10 自动配准/半自动配准相关推荐

  1. C# GDAL 数字图像处理Part2 Band合成BMP

    在成功读取dataset之后,我们应该进行图像的显示,究竟如何把三个Band读取出来合成为标准的BMP图像呢?(读取dataset见:C# GDAL 数字图像处理Part1 安装以及读取Dataset ...

  2. C# GDAL 数字图像处理Part7 仿射变换图像配准

    大家注意,采点采的是Bitmap的像素坐标,不用转换到地理坐标!大家一定注意!舍友de了一天bug刚刚de出来快哭晕了~                                        ...

  3. matlab相位相关图像配准,数字图像处理,相位相关图像配准

    前言 图像配准是图像处理的基本任务之一,用于将不同时间.不同传感器.不同视角及不同拍摄条件下获取的关于同一目标或场景的两幅或多幅图像进行主要是几何意义上的匹配套和的过程.在对图像配准的研究过程中,大量 ...

  4. C# GDAL 数字图像处理Part9 辐射定标与输出Dataset

    这篇文章比较好写,先写这篇,自动配准应该应该会在周四之后更新. 辐射定标应该是一个比较简单的内容,本章我们主要介绍如何输出Dataset.由于辐射定标后我们应该输出一个TIFF或IMG之类格式的文件, ...

  5. C# GDAL 数字图像处理Part6 大气辐射矫正

    最近作业是真的多. 应不愿意透露姓名的GUI同学的呼吁,今天我们来讲一下我自己使用的.和老师讨论过了但是并不太严谨的.还算过得去的大气辐射矫正方法. 为什么要进行大气辐射校正?说实话我自己也是一知半解 ...

  6. 数字图像处理第五章——几何变换与图像配准

    数字图像处理第五章 数字图像处理---几何变换与图像配准 (一)点变换 (二)仿射变换 (三)投影变换 (四)应用于图像的几何变换 (五)MATLAB 中的图像坐标系统 5.1 输出图像位置 5.2 ...

  7. 数字图像处理与机器视觉_简单自动智能识别物体程序(机器视觉+数字图像处理)...

    非常好的识别物体的机器视觉程序.附有完整的说明文档和代码.代码由matlab写成,并附有测试图片.图片中含有各种物体,通过数字图像处理的知识,自动识别出图片中的各类物体. 文件:n459.com/f/ ...

  8. 简单自动智能识别物体程序(机器视觉+数字图像处理)

    非常好的识别物体的机器视觉程序.附有完整的说明文档和代码.代码由matlab写成,并附有测试图片.图片中含有各种物体,通过数字图像处理的知识,自动识别出图片中的各类物体. 文件:n459.com/f/ ...

  9. 数字图像处理知识点总结

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达本文转自|新机器视觉 数字图像处理知识点总结 第一章 导论 1.   ...

最新文章

  1. android开发环境搭建教程
  2. 扔掉 Postman,Apifox 才是 YYDS!
  3. python从事哪些职业好玩_Python就业可选方向有哪些?带你了解Python主流职业选择!...
  4. 对弈程序基本技术---最小-最大搜索
  5. 十年 | 我花了十年,才弄明白了Node.js
  6. 二维特征分类的基础_3D 分割分类总结
  7. CSDN前200名博主
  8. 服务器:CPU虚拟化_服务器虚拟化技术
  9. springmvc转换器converter的使用
  10. 硬盘格式化工具 标记坏扇区_硬盘格式化后是否还记得坏扇区?
  11. redis+Python实现小型动态IP池的搭建,仅需90行代码
  12. aliyun-freeSSL证书生成、下载、配置到apache httpd
  13. ctags中−−−kinds=[+|−]kinds的使用
  14. ADASISv3简述,自动驾驶怎么进行地图数据传输?
  15. 如何使用petri网建模工具pipe4.3.0
  16. 【好记性不如烂笔头】快速排序(三)非递归实现随机快排
  17. 推特大裁员后,马斯克与白宫发生冲突!META 大批裁员正在路上
  18. 计算机单词正确的打开方式是怎样的?
  19. win10电脑内存莫名过高问题解决
  20. Windows程序设计_Chap02_Unicode_学习笔记

热门文章

  1. 去哪儿网2015校园招聘前端笔试题
  2. 亿级流量电商详情页系统实战-31.应用层nginx缓存实现
  3. 嵌入式工程师的日常是啥样的?就业现状如何?
  4. 7.MATLAB参数统计与假设检验-常用非参数检验
  5. Excel-vba打开word文件读取内容处理并保存至word中
  6. 【毕业设计】15-基于单片机的交通灯系统设计(原理图+仿真+论文)
  7. python做马尔科夫模型预测法_通过Python的Networkx和Sklearn来介绍隐性马尔科夫模型...
  8. Python IDEL查询和修改当前目录
  9. SpringSecurity+Mybatis实现用户自助注册登录(含角色),打造简单安全的注册登录页面。
  10. ARMv8-a架构简介