C# OpenCvSharp 通过特征点匹配图片

SIFT匹配

SURF匹配

项目

代码

using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;namespace OpenCvSharp_Demo
{public partial class frmMain : Form{public frmMain(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){}private void button2_Click(object sender, EventArgs e){Mat matSrc = new Mat("1.jpg");Mat matTo = new Mat("2.jpg");var outMat = MatchPicBySift(matSrc, matTo);pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);}private void button1_Click(object sender, EventArgs e){Mat matSrc = new Mat("1.jpg");Mat matTo = new Mat("2.jpg");var outMat = MatchPicBySurf(matSrc, matTo, 10);pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);}public Point2d Point2fToPoint2d(Point2f point) => new Point2d((double)point.X, (double)point.Y);public Mat MatchPicBySift(Mat matSrc, Mat matTo){using (Mat matSrcRet = new Mat())using (Mat matToRet = new Mat()){KeyPoint[] keyPointsSrc, keyPointsTo;using (var sift = OpenCvSharp.Features2D.SIFT.Create()){sift.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);sift.DetectAndCompute(matTo, null, out keyPointsTo, matToRet);}using (var bfMatcher = new OpenCvSharp.BFMatcher()){var matches = bfMatcher.KnnMatch(matSrcRet, matToRet, k: 2);var pointsSrc = new List<Point2f>();var pointsDst = new List<Point2f>();var goodMatches = new List<DMatch>();foreach (DMatch[] items in matches.Where(x => x.Length > 1)){if (items[0].Distance < 0.5 * items[1].Distance){pointsSrc.Add(keyPointsSrc[items[0].QueryIdx].Pt);pointsDst.Add(keyPointsTo[items[0].TrainIdx].Pt);goodMatches.Add(items[0]);Console.WriteLine($"{keyPointsSrc[items[0].QueryIdx].Pt.X}, {keyPointsSrc[items[0].QueryIdx].Pt.Y}");}}var outMat = new Mat();// 算法RANSAC对匹配的结果做过滤var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d);var pDst = pointsDst.ConvertAll(Point2fToPoint2d);var outMask = new Mat();// 如果原始的匹配结果为空, 则跳过过滤步骤if (pSrc.Count > 0 && pDst.Count > 0)Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);// 如果通过RANSAC处理后的匹配点大于10个,才应用过滤. 否则使用原始的匹配点结果(匹配点过少的时候通过RANSAC处理后,可能会得到0个匹配点的结果).if (outMask.Rows > 10){byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];outMask.GetArray(out maskBytes);Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, matchesMask: maskBytes, flags: DrawMatchesFlags.NotDrawSinglePoints);}elseCv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, flags: DrawMatchesFlags.NotDrawSinglePoints);return outMat;}}}public Mat MatchPicBySurf(Mat matSrc, Mat matTo, double threshold = 400){using (Mat matSrcRet = new Mat())using (Mat matToRet = new Mat()){KeyPoint[] keyPointsSrc, keyPointsTo;using (var surf = OpenCvSharp.XFeatures2D.SURF.Create(threshold, 4, 3, true, true)){surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);surf.DetectAndCompute(matTo, null, out keyPointsTo, matToRet);}using (var flnMatcher = new OpenCvSharp.FlannBasedMatcher()){var matches = flnMatcher.Match(matSrcRet, matToRet);//求最小最大距离double minDistance = 1000;//反向逼近double maxDistance = 0;for (int i = 0; i < matSrcRet.Rows; i++){double distance = matches[i].Distance;if (distance > maxDistance){maxDistance = distance;}if (distance < minDistance){minDistance = distance;}}Console.WriteLine($"max distance : {maxDistance}");Console.WriteLine($"min distance : {minDistance}");var pointsSrc = new List<Point2f>();var pointsDst = new List<Point2f>();//筛选较好的匹配点var goodMatches = new List<DMatch>();for (int i = 0; i < matSrcRet.Rows; i++){double distance = matches[i].Distance;if (distance < Math.Max(minDistance * 2, 0.02)){pointsSrc.Add(keyPointsSrc[matches[i].QueryIdx].Pt);pointsDst.Add(keyPointsTo[matches[i].TrainIdx].Pt);//距离小于范围的压入新的DMatchgoodMatches.Add(matches[i]);}}var outMat = new Mat();// 算法RANSAC对匹配的结果做过滤var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d);var pDst = pointsDst.ConvertAll(Point2fToPoint2d);var outMask = new Mat();// 如果原始的匹配结果为空, 则跳过过滤步骤if (pSrc.Count > 0 && pDst.Count > 0)Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);// 如果通过RANSAC处理后的匹配点大于10个,才应用过滤. 否则使用原始的匹配点结果(匹配点过少的时候通过RANSAC处理后,可能会得到0个匹配点的结果).if (outMask.Rows > 10){byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];outMask.GetArray(out maskBytes);Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, matchesMask: maskBytes, flags: DrawMatchesFlags.NotDrawSinglePoints);}elseCv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, flags: DrawMatchesFlags.NotDrawSinglePoints);return outMat;}}}}
}

下载

Demo下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/187081.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot中配置多个数据源

配置数据源实际上就是配置多个数据库&#xff0c;在一个配置文件中配置多个数据库&#xff0c;这样做主要的好处有以下几点&#xff1a; 数据库隔离&#xff1a;通过配置多个数据源&#xff0c;可以将不同的业务数据存储在不同的数据库中&#xff0c;实现数据的隔离。这样可以…

Leetcode—637.二叉树的层平均值【简单】

2023每日刷题&#xff08;二十五&#xff09; Leetcode—637.二叉树的层平均值 BFS实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ /*** Note: The returned array mu…

vscode文件跳转(vue项目)

在 .vue 文件中&#xff0c;点击组件名打开 方式1&#xff1a; 在 vue 组件名上&#xff0c;桉住ctrl 鼠标左键 // 重新打开一个tab 方式2&#xff1a; 在 vue 组件名上&#xff0c;桉住ctrl shift 鼠标左键 // 在右侧拆分&#xff0c;并打开一个tab .vue文件的跳转 按住 …

漏刻有时百度地图API实战开发(1)华为手机无法使用addEventListener click 的兼容解决方案

漏刻有时百度地图API实战开发(1)华为手机无法使用addEventListener click 的兼容解决方案漏刻有时百度地图API实战开发(2)文本标签显示和隐藏的切换开关漏刻有时百度地图API实战开发(3)自动获取地图多边形中心点坐标漏刻有时百度地图API实战开发(4)显示指定区域在移动端异常的解…

龙芯loongarch64服务器编译安装scipy

前言 根据我之前的文章介绍,龙芯loongarch64服务器中的很多python依赖包安装有问题,发现其中安装的"scikit-learn"就无法正常使用,所有这里在 pip3 install scikit-learn -U -i https://pypi.tuna.tsinghua.edu.cn/simple 的时候发现"scipy"就无法正常…

轻松下载网页音频和视频

在网页上看到好看的视频或者听到的音乐想保存&#xff0c;让我来教你&#xff08;仅供学习&#xff09; 注意&#xff1a;有极少部分的网站视频经过加密&#xff0c;无法下载 一、视频下载 1.打开视频网页 2.右键“检查” 3.刷新网页 4.按照下图中步骤操作 5.把复制的链接放…

数字化工厂管理系统的三个关键技术是什么

随着科技的飞速发展&#xff0c;数字化工厂管理系统已经成为了现代制造业的重要发展方向。数字化工厂管理系统通过充分运用建模技术、仿真技术和单一数据源技术&#xff0c;实现了产品设计和生产的虚拟化&#xff0c;为制造业带来了前所未有的效率和创新能力。本文将深入探讨这…

k8s configMap挂载(项目配置文件放到configMap中,不同环境不同配置)

背景说明 项目对接配置文件加密&#xff0c;比如数据库密码、redis密码等。但是密文只能放到指定的配置文件中(important.properties)&#xff0c;该配置文件又不能接收环境变量&#xff0c;所以就很难区分不同环境的不同配置&#xff08;不同环境的数据库密码、redis密码一般…

Gui基础使用之项目部署

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 越努力 &#xff0c;越幸运。 1.gui图形化界面的使用 1.1 前期准备 新建仓库&#xff0c;具体操作如下&#xff1a; 初始化readme文件&…

软件测试面试会问哪些问题?

软件测试面试&#xff0c;一般会被问到下面这九类问题。 1、基础问题 2、Linux命令 3、数据库 4、功能测试 5、Python基础 6、接口测试 7、自动化测试 8、性能测试 9、人事问题 接下来&#xff0c;以上9类问题&#xff0c;我都会分别结合2个案例&#xff0c;附上答案&#xff0…

Banana Pi BPI-M6(Raspberry Pi 5 替代品)初始设置及固件烧录

Banana Pi BPI-M6&#xff1a;初始设置和镜像烧录 Banana Pi BPI-M6 的首次测试 在上一篇文章中&#xff0c;我比较了Banana Pi BPI-M6和Raspberry Pi 5的硬件特性。两者都拥有出色的硬件技术&#xff0c;在性能方面应该不会有太大的问题。 今天我想测试一下 Banana Pi。作为…

阿里云双11优惠云服务器99元一年,4年396元

阿里云99元服务器新老用户均可以买&#xff0c;你没看错&#xff0c;老用户可以买&#xff0c;活动页面 aliyunfuwuqi.com/go/aliyun 配置为云服务器ECS经济型e实例、2核2G、3M固定带宽、40G ESSD Entry云盘&#xff0c;并且续费不涨价&#xff0c;原价99元即可续费&#xff0c…

【全网首发】【Python】Python控制parrot ARDrone 2.0无人机

&#x1f389;欢迎来到Python专栏~Python控制parrot ARDrone 2.0无人机 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误…

AIGC:使用生成对抗网络GAN实现MINST手写数字图像生成

1 生成对抗网络 生成对抗网络&#xff08;Generative Adversarial Networks, GAN&#xff09;是一种非常经典的生成式模型&#xff0c;它受到双人零和博弈的启发&#xff0c;让两个神经网络在相互博弈中进行学习&#xff0c;开创了生成式模型的新范式。从 2017 年以后&#x…

vue项目js原生属性IntersectionObserver实现图片懒加载

vue项目js原生属性IntersectionObserver实现图片懒加载 IntersectionObserver 使用js原生属性IntersectionObserver实现观察img元素是否处于游览器视口中 懒加载原理&#xff1a;给img设置一个默认url图片&#xff0c;观察图片处于视口内以后&#xff0c;动态改变img的url为自己…

如何利用产品帮助中心提升用户体验

在当今竞争激烈的市场中&#xff0c;提供优秀的用户体验是吸引和保留客户的关键。而一个高效和易于使用的产品帮助中心&#xff0c;正成为越来越多企业用以提升用户体验的重要工具。产品帮助中心是一个集中的信息库&#xff0c;为用户提供关于产品功能、故障排除、常见问题解答…

SQL Server SSIS的安装

标题SQL SERVER 安装 下载SQL SERVER数据库&#xff1a;&#xff08;以SQL SERVER 2022 Developer版本&#xff09;(https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads?rtc1) 以administrator权限安装&#xff1a; 下载完成后&#xff0c;会出现以下界面&a…

GPIO实验:ARM汇编代码实现LED灯亮灭控制

GPIO实验&#xff1a;ARM汇编代码实现LED灯亮灭控制 一、 汇编工程模板Makefile分析 NAMEasm-led #指定编译的源文件名字 CROSS_COMPILE arm-linux-gnueabihf- #指定交叉编译工具链前缀CC $(CROSS_COMPILE)gcc #指定gcc名字LD $(CROSS_COMPILE)ld #指定链接器名字…

pytorch直线拟合

目录 1、数据分析 2、pytorch直线拟合 1、数据分析 直线拟合的前提条件通常包括以下几点&#xff1a; 存在线性关系&#xff1a;这是进行直线拟合的基础&#xff0c;数据点之间应该存在一种线性关系&#xff0c;即数据的分布可以用直线来近似描述。这种线性关系可以是数据点…

【hcie-cloud】【2】华为云Stack解决方案介绍、缩略语整理 【下】

文章目录 华为文档获取方式、云计算发展背景、坚实基座华为云Stack&#xff0c;政企只能升级首选智能数据湖仓一体&#xff0c;让业务洞见更准&#xff0c;价值兑现更快MRS&#xff1a;一个架构可构建三种数据湖&#xff0c;业务场景更丰富离线数据湖&#xff1a;提供云原生、湖…