在工业视觉检测、自动化测量、机器人定位等应用场景中,精确提取图像里圆形目标的圆心是一个常见且关键的任务。云栈社区的技术人员经常需要处理这类问题,而 OpenCVSharp 作为 OpenCV 的 .NET 封装库,为 C# 开发提供了强大的图像处理能力,尤其适合 WinForm / WPF 上位机系统的开发。
本文将基于 OpenCVSharp,介绍如何从一张仅包含半圆的图像中,通过图像预处理、轮廓提取与椭圆拟合,精确计算出圆心位置。整个过程贴近实际项目需求,适合初学者入门和开发参考。
1、OpenCVSharp 简介与安装
OpenCVSharp 是 OpenCV 的 .NET 封装库,项目地址:https://github.com/shimat/opencvsharp。
该项目采用 BSD 开源协议,允许自由使用、修改、商业化,甚至可将修改后的代码作为专有软件发布,非常适合企业级项目集成。
安装方式
方式一:NuGet 包管理器(推荐)
- 打开 Visual Studio → 【工具】→ 【NuGet 包管理器】→ 【管理解决方案的 NuGet 程序包】

- 搜索
OpenCvSharp4(注意:最新版本为 OpenCvSharp4)
- 安装
OpenCvSharp4 和 OpenCvSharp4.runtime.win(支持 Windows 运行时)
方式二:源码编译
从 GitHub 下载源码,自行编译后引用 DLL。

提示:在 VS2017 等环境中,建议将安装后的 OpenCVSharp 相关 DLL 拷贝到项目目录并本地引用,避免运行时依赖问题。
2、实现目标:拟合圆并求取圆心
我们有一张仅包含半圆的图像,目标是通过图像处理技术,提取轮廓并拟合出完整椭圆,进而得到圆心坐标。
原始图像如下(仅显示半圆):

3、核心代码实现
using OpenCvSharp;
namespace FitCircleDemo
{
public class CircleFit
{
public Mat Run(string imgPath)
{
// 读取图片
var img = Cv2.ImRead(imgPath);
// 转换为灰度图
Mat gray = img.CvtColor(ColorConversionCodes.BGR2GRAY);
// 阈值分割
Mat thresholdImg = gray.Threshold(11, 255, ThresholdTypes.Binary);
Cv2.ImShow("Threshold", thresholdImg);
// 形态学开运算降噪(推荐)
Mat element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(3, 3));
Mat openImg = thresholdImg.MorphologyEx(MorphTypes.Open, element);
Cv2.ImShow("Dilate & Erode", openImg);
// 设置感兴趣区域(ROI)
int x = 150, y = 100, w = 294, h = 337;
Rect roi = new Rect(x, y, w, h);
Mat roiImg = new Mat(openImg, roi);
// 寻找轮廓
Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(roiImg, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS);
// 遍历轮廓,拟合椭圆
for (int i = 0; i < contours.Length; i++)
{
if (contours[i].Length < 5) continue; // 至少5个点才能拟合
var ellipse = Cv2.FitEllipse(contours[i]);
// 将椭圆中心还原到原图坐标系
ellipse.Center.X += x;
ellipse.Center.Y += y;
// 绘制拟合椭圆
Cv2.Ellipse(img, ellipse, new Scalar(0, 0, 255), 2, LineTypes.AntiAlias);
// 绘制圆心
Cv2.Circle(img, (int)ellipse.Center.X, (int)ellipse.Center.Y, 4, new Scalar(255, 0, 0), -1);
}
Cv2.ImShow("Fit Circle", img);
return img;
}
}
}
4、图像处理流程详解
灰度化:将彩色图像转为灰度图,减少计算量。
阈值分割:使用 Threshold 函数将图像二值化,便于后续处理。阈值 11 可通过调试工具(如 OpenCV 窗口滑块)动态调整。
降噪处理:
- 中值滤波:
MedianBlur 适合去除椒盐噪声。
- 形态学开运算:先腐蚀再膨胀,有效去除小噪点,保留主体结构(本文采用此方法)。
ROI 设置:通过 Rect 定义感兴趣区域,提升处理效率并避免干扰。
轮廓提取:使用 FindContours 提取所有轮廓。
椭圆拟合:调用 FitEllipse 对轮廓点集进行最小二乘椭圆拟合。
坐标还原:由于在 ROI 内拟合,需将圆心坐标还原到原图坐标系。
可视化:在原图上绘制椭圆和圆心(红色椭圆,蓝色实心圆)。
5、中间处理效果

- 阈值分割后:图像变为黑白二值图,目标区域清晰。
- 形态学开运算后:噪声点被有效去除,边缘更平滑。
- 拟合圆后:在原图上绘制出红色椭圆和蓝色圆心,成功定位。
降噪方法对比:经测试,中值滤波 和 形态学开运算 在本例中效果最佳。
6、形态学操作原理补充
| 操作 |
原理 |
作用 |
| 腐蚀(Erode) |
用结构元素扫描图像,仅保留能完全包含结构元素的像素 |
缩小图像、去除小细节、断开连接区域 |
| 膨胀(Dilate) |
用结构元素扫描图像,并集扩展 |
扩大图像、填充空洞、连接邻近区域 |
| 开运算(Open) |
先腐蚀,再膨胀 |
去除小亮点,平滑轮廓 |
| 闭运算(Close) |
先膨胀,再腐蚀 |
去除小黑点,闭合小裂缝 |
| 形态学梯度 |
膨胀图 - 腐蚀图 |
提取边缘 |
| 顶帽(Top Hat) |
原图 - 开运算图 |
突出亮区域 |
| 黑帽(Black Hat) |
闭运算图 - 原图 |
突出暗区域 |
结构元素(Kernel):常用椭圆或矩形,如 Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(3,3))
总结
本文通过 OpenCVSharp 实现了从半圆图像中拟合完整椭圆并提取圆心的完整流程。关键技术点包括:
- 使用 形态学开运算 有效降噪
- 通过 ROI 提高处理效率
- 利用 FitEllipse 实现高精度拟合
- 注意 坐标系还原,避免定位偏差
该方法可广泛应用于:
- 工业零件定位
- 自动对焦系统
- 视觉引导机器人
- 医学图像分析
OpenCVSharp 作为 .NET 平台强大的图像处理工具,结合 C# 的开发效率,非常适合上位机、MES、SCADA 等系统的视觉模块开发。如果你在项目中遇到类似需求,不妨参考上述步骤动手实践。