使用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 ...
随机推荐
- 13、Actor
1.介绍 Scala的Actor类似于Java中的多线程编程.但是不同的是,Scala的Actor提供的模型与多线程有所不同. Scala的Actor尽可能地避免锁和共享状态,从而避免多线程并发时出现 ...
- C#使用Json.NET解析Json
本文转载自 http://xiaosheng.me/2016/10/01/article25/ 最近在 C# 项目中需要使用到 Json 格式的数据,我简单上网搜索了一下,基本上有两种操作 Json ...
- 在虚拟机环境(CentOS7系统)下将kubernetes中部署服务成功,但在虚拟机外部无法访问到服务
在CentOS7环境下,kubernetes单机版环境,成功部署一个服务,在虚拟机中访问服务没问题,下面这样: curl http://172.27.73.26:8888/eureka-server/ ...
- hdu 1576 A/B (求逆元)
题目链接 Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1). Inpu ...
- Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)(2)
接上篇 2. <dynamicField> 为满足前辍或后辍的一些字段提供统一的定义.如<dynamicField name="*_s" index=&qu ...
- mysql安装等操作
CentOS 6.5系统中安装配置MySQL数据库 卸载掉原有mysql rpm -qa | grep mysql // 这个命令就会查看该操作系统上是否已经安装了mysql数据库 rpm -e my ...
- Discuz!快速对接个人支付插件
## Discuz!快速对接个人支付插件 由于近期准备使用老牌论坛程序Discuz建立一个交流社区分享一些资源,但是测试了各种支付方式都不满意,偶然发现一个简直不要太完美的解决方案.今天抽时间搭建好并 ...
- Eclipse项目中乱码问题的解决办法
一.产生的原因: 1.Http协议进行通信的时候是基于请求和响应的,传输的内容我们称之为报文! 2.Http协议会按照一定的规则将报文编码,然后在读取的时候再使用响应的解码格式进行解码! 3.这个一定 ...
- [转]Xcode概览:调试应用程序
原文网址: blog.csdn.net/fhbystudy/article/details/12856261 本文由CocoaChina翻译组成员Creolophus(github主页)翻译自苹果官方 ...
- CF987C Three displays 解题报告
题目传送门 题目大意 n个位置,每个位置有两个属性s,c,要求选择3个位置i,j,k,使得s_i<s_j<s_k,并使得c_i+c_j+c_k最小 方法1 n³枚举每一种情况(也许可以拿 ...