使用C#版OpenCV进行圆心求取
OpenCVSharp是OpenCV的.NET wrapper,是一名日本工程师开发的,项目地址为:https://github.com/shimat/opencvsharp。
该源码是 BSD开放协议,BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以”为所欲为”,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布或商业化销售。
1.OpenCVSharp的下载
可以直接从上面的github上下载源码,自行编译引用;
也可用vs中的nuget包管理器下载;
打开【工具】->【库程序包管理器】->【管理解决方案的NuGet程序包】,在其中搜索OpenCVSharp,选择合适的点击【安装】(最好安装最新的)。一直等待完成。
我的环境是vs2017,下载之后最好直接拷贝OpenCVSharp系列dll到项目中引用即可。
2.拟合圆并求取圆心
本次举例比较贴近实际,我们求如下原始图片的中间部分圆的圆心,选取的图片故意只留了一半:
源码如下:
using OpenCvSharp; namespace FitCircleDemo
{
public class CircleFit
{
public Mat Run(string imgPath)
{
//读取图片
//var img = Cv2.ImRead("Data/Image/c1.bmp");
var img = Cv2.ImRead(imgPath);
//显示图片
//Cv2.ImShow("Input Image", img); //转换成灰度图
Mat gray = img.CvtColor(ColorConversionCodes.BGR2GRAY); //阈值操作 阈值参数可以用一些可视化工具来调试得到
Mat ThresholdImg = gray.Threshold(, , ThresholdTypes.Binary);
Cv2.ImShow("Threshold", ThresholdImg); //降噪
//方法一:高斯变化
//Mat gaussImg= ThresholdImg.GaussianBlur(new Size(5, 5), 0.8);
//Cv2.ImShow("GaussianBlur", gaussImg);
//方法二:中值滤波降噪
//Mat medianImg = ThresholdImg.MedianBlur(5);
//Cv2.ImShow("MedianBlur", medianImg); //方法三:膨胀+腐蚀
////膨胀处理
//Mat kernel = new Mat(15, 15, MatType.CV_8UC1);
//Mat DilateImg = ThresholdImg.Dilate(kernel);
////腐蚀处理
//Mat binary = DilateImg.Erode(kernel);
////显示中间结果
//Cv2.ImShow("Dilate & Erode", binary);
Mat element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(, ));
Mat openImg = ThresholdImg.MorphologyEx(MorphTypes.Open, element);
Cv2.ImShow("Dilate & Erode", openImg); //设置感兴趣的区域
int x = , y = , w = , h = ;
Rect roi = new Rect(x, y, w, h);
Mat ROIimg = new Mat(openImg, roi);
//Cv2.ImShow("ROI Image", ROIimg); //寻找图像轮廓
Point[][] contours;
HierarchyIndex[] hierachy;
Cv2.FindContours(ROIimg, out contours, out hierachy, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS);
//根据找到的轮廓点,拟合椭圆
for (int i = ; i < contours.Length; i++)
{
//拟合函数必须至少5个点,少于则不拟合
if (contours[i].Length < ) continue;
//椭圆拟合
var rrt = Cv2.FitEllipse(contours[i]); //ROI复原
rrt.Center.X += x;
rrt.Center.Y += y; //画椭圆
Cv2.Ellipse(img, rrt, new Scalar(, , ), , LineTypes.AntiAlias);
//画圆心
Cv2.Circle(img, (int)(rrt.Center.X), (int)(rrt.Center.Y), , new Scalar(, , ), -, LineTypes.Link8, );
} Cv2.ImShow("Fit Circle", img);
return img;
}
}
}
中间处理过程效果图如下:
分别是阈值分割后,中值滤波后,拟合圆之后
对上图中第一张进行降噪方法有很多,经测试最有效的是中值滤波(MedianBlur)和腐蚀&膨胀(MorphologyEx)处理
中值滤波基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值,让周围的像素值接近真实的值从而消除孤立的噪声点。
高级形态学变换:
开运算:
先腐蚀,再膨胀,可清除一些小东西(亮的),放大局部低亮度的区域
闭运算:
先膨胀,再腐蚀,可清除小黑点
形态学梯度:
膨胀图与腐蚀图之差,提取物体边缘
顶帽:
原图像-开运算图,突出原图像中比周围亮的区域
黑帽:
闭运算图-原图像,突出原图像中比周围暗的区域
1.腐蚀
首先说腐蚀,腐蚀是缩小图像,去除小沟壑细节的一种操作,腐蚀的概念很好理解,但是公式看起来却很麻烦,我这里主要说概念。
腐蚀操作需要两个元素,一个待处理对象A,一个element B,B对A的腐蚀得到的结果是由A中能够包含整个B的像素点所组成的,如下图所示:
其中比较关键的是B的锚点,就是B的锚点在A中扫描时,A能将B完全包住的B的锚点所扫描的像素点。
腐蚀的作用:去除图像中不想要的小细节,比如一张二值图片中的噪点或者小细节。
符号:⊖ \ominus⊖
2.膨胀
膨胀的需要与腐蚀完全相同只是他们的作用相反,element B膨胀图形A的结果是,A和B的并集产生的,如下:
B的锚点在A的边界进行扫描,A与B的并集就是B对A进行膨胀的结果。
使用C#版OpenCV进行圆心求取的更多相关文章
- OpenCV 最小二乘拟合方法求取直线倾角
工业相机拍摄的图像中,由于摄像质量的限制,图像中的直线经过处理后,会表现出比较严重的锯齿.在这种情况下求取直线的倾角(其实就是直线的斜率),如果是直接选取直线的开始点和结束点来计算,或是用opencv ...
- java 求取某一段时间内的每一天、每一月、每一年
1.求取某一段时间内的每一天 Date date0 = new SimpleDateFormat("yyyy-MM-dd").parse("2014-01-01" ...
- php自定义函数求取平方根
<?phpfunction sqare($a, $left, $right){ $mid = ($left + $right)/2; if($mid * $mid == $a || (abs($ ...
- oracle 当前年到指定年的年度范围求取
如下面公式所示,求取2015到当前年(2018)的年度范围,当前年是由系统获取的,用到了sysdate和函数to_char,to_date. 当然,当前年也可以换成指定年份 SELECT TO_CHA ...
- poj 1523Tarjan算法的含义——求取割点可以分出的连通分量的个数
poj 1523Tarjan算法的含义——求取割点可以分出的连通分量的个数 题目大意:如题目所示 给你一些关系图——连通图,想要问你有没有个节点,损坏后,可以生成几个互相独立的网络(也就是连通分量), ...
- python 库 Numpy 中如何求取向量范数 np.linalg.norm(求范数)(向量的第二范数为传统意义上的向量长度),(如何求取向量的单位向量)
求取向量二范数,并求取单位向量(行向量计算) import numpy as np x=np.array([[0, 3, 4], [2, 6, 4]]) y=np.linalg.norm(x, axi ...
- K:求取数组中最大连续子序列和的四个算法
相关介绍: 求取数组中最大连续子序列和问题,是一个较为"古老"的一个问题.该问题的描述为,给定一个整型数组(当然浮点型也是可以的啦),求取其下标连续的子序列,且其和为该数组的所有 ...
- 第3节 mapreduce高级:8、9、自定义分区实现分组求取top1
自定义GroupingComparator求取topN GroupingComparator是mapreduce当中reduce端的一个功能组件,主要的作用是决定哪些数据作为一组,调用一次reduce ...
- 通过spark rdd 求取 特征的稀疏向量
通过spark rdd 求取 特征的稀疏向量 spark 类标签的稀疏 特征向量 - bonelee - 博客园 http://www.cnblogs.com/bonelee/p/7814081.h ...
随机推荐
- Centos下添加/删除用户
useradd具体参数 [root@yhwang ~] useradd -h Usage: useradd [options] LOGIN useradd -D useradd -D [options ...
- 什么是消息循环,一个简单的win32程序如何运行?
预备知识 1.什么是句柄? (HANDLE) 在win32编程中有各种句柄,那么什么是句柄呢? #define DECLARE_HANDLE(name) struct name##_ { int un ...
- storm启动nimbus源码分析-nimbus.clj
nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus >/dev/null 2>&1 &a ...
- Android常见内存泄露,学会这六招优化APP性能
很多开发者都知道,在面试的时候会经常被问到内存泄露和内存溢出的问题. 1.内存溢出(Out Of Memory,简称 OOM),通俗理解就是内存不够,即内存占用超出内存的空间大小. 2.内存泄漏(Me ...
- Webpack 4教程 - 第八部分 使用prefetch和preload进行动态加载
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://wanago.io/2018/08/13/webpack-4-course-part ...
- 2014-11-3 NOIP模拟赛3
字符串 string.pas/c/cpp 1S/256MB [题目描述] 现在给一个字符串,你要做的就是当这个字符串中存在两个挨着的字符是相同的时就将这两个字符消除.需要注意的是,当把这两个字符消除后 ...
- 关于CSRF攻击详解
CSRF的原理以及防范 CSRF概念:CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解: 攻击者盗用了你的身份,以你 ...
- 数据返回正常 而header头Status=500
访问接口数据成功返回,但header头Status Code:500,而调用接口的html用ajax访问一直返回500服务器错误,并且ajax一直走error,走不到success中,错误返回状态是连 ...
- js和css文件位置对页面性能的影响
翻译了一篇Performance上的关于页面性能的文章<DecIPhering the critical rendering path>,原文在这里.需要进一步整理和了解有关js.css等 ...
- 消息中间件 | 消息协议 | AMQP -- 《分布式 消息中间件实践》笔记
04年,AMQP开放标准被开发 06年,AMQP规范被发布 基本概念 Message:与平台无相关的数据. Publisher:向交换器发布消息的客户端应用程序 Excha ...