开发环境:.NET Framework4.8
输出类型 winfrom窗体应用程序
在这篇博客文章中,我将介绍如何使用 OpenCvSharp 在图像中检测圆形。这是一个有趣且实用的计算机视觉任务,可以应用于许多实际场景,如硬币检测、细胞计数等。
项目结构
首先,让我们看看项目的结构。这个项目是一个 Windows 窗体应用程序,包含以下组件:
一个 OpenFileDialog 组件用于选择图像文件。
一个 PictureBox 组件用于显示图像。
五个 NumericUpDown 组件用于调整霍夫圆检测算法的参数。
一个 ListView 组件用于显示检测到的圆形的直径。
1:加载图像
```csharp
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
label1.Text = dialog.FileName.ToString();
pictureBox1.Image = Image.FromFile(dialog.FileName);
}
}
3.处理图像
当用户调整参数或点击检测按钮时,触发图像处理流程。该流程包括加载图像、应用高斯模糊、使用霍夫变换检测圆形,并显示结果。
private async void button1_Click(object sender, EventArgs e)
{
await ProcessImage(label1.Text);
}
private async Task ProcessImage(string imagePath)
{
await Task.Run(() =>
{
// 检查图像文件是否存在
if (!System.IO.File.Exists(imagePath))
{
MessageBox.Show($"未找到图像文件: {imagePath}");
return;
}
// 加载图像
Mat image = Cv2.ImRead(imagePath, ImreadModes.Grayscale);
// 检查图像是否成功加载
if (image.Empty())
{
MessageBox.Show($"加载图像失败: {imagePath}");
return;
}
// 应用高斯模糊以减少噪声
Mat blurred = new Mat();
Cv2.GaussianBlur(image, blurred, new OpenCvSharp.Size(9, 9), 2, 2);
// 使用霍夫圆检测找到圆
HoughModes houghMode = HoughModes.Gradient;
double minDist = 0.0;
double param1 = 0.0;
double param2 = 0.0;
int minRadius = 0;
int maxRadius = 0;
numericUpDown1.Invoke((Action)(() =>
{
minDist = double.Parse(numericUpDown1.Value.ToString());
}));
numericUpDown2.Invoke((Action)(() =>
{
param1 = double.Parse(numericUpDown2.Value.ToString());
}));
numericUpDown3.Invoke((Action)(() =>
{
param2 = double.Parse(numericUpDown3.Value.ToString());
}));
numericUpDown4.Invoke((Action)(() =>
{
minRadius = int.Parse(numericUpDown4.Value.ToString());
}));
numericUpDown5.Invoke((Action)(() =>
{
maxRadius = int.Parse(numericUpDown5.Value.ToString());
}));
CircleSegment[] circles = Cv2.HoughCircles(blurred, houghMode, 1, minDist, param1: param1, param2: param2, minRadius: minRadius, maxRadius: maxRadius);
// 创建用于显示结果的图像
Mat resultImage = new Mat();
Cv2.CvtColor(image, resultImage, ColorConversionCodes.GRAY2BGR);
// 设置文本绘制的字体和参数
HersheyFonts font = HersheyFonts.HersheySimplex;
double fontScale = 0.5;
int thickness = 1;
double coinDiameterCm = 25; // 假设一元硬币直径为25毫米
listView1.Invoke((Action)(() =>
{
listView1.Items.Clear();
listView1.Columns.Clear();
listView1.Columns.Add("直径", 100);
}));
foreach (var circle in circles)
{
Point center = new Point((int)circle.Center.X, (int)circle.Center.Y);
int radius = (int)circle.Radius;
double diameterCm = (radius * 2) * (coinDiameterCm / 1000); // 假设像素到毫米的比例为1:100
Cv2.Circle(resultImage, center, radius, new Scalar(0, 0, 255), 5);
string diameterText = $" {diameterCm:0.0} mm";
listView1.Invoke((Action)(() =>
{
listView1.Items.Add(new ListViewItem(new string[] { diameterText }));
}));
}
// 显示检测到的圆的总数量
string totalCirclesText = $"总圆形数量: {circles.Length}";
label2.Invoke((Action)(() =>
{
label2.Text = totalCirclesText;
}));
// 将Mat转换为Bitmap,并在PictureBox中显示
Bitmap bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(resultImage);
pictureBox1.Invoke((Action)(() =>
{
pictureBox1.Image = bitmap;
}));
});
}
总结
通过本文的介绍,你应该可以了解到如何使用 OpenCvSharp 实现图像中的圆形检测。这个过程包括加载图像、预处理图像、应用霍夫变换检测圆形,以及在用户界面中显示结果。希望这篇文章对你有所帮助,如果你有任何问题或建议,欢迎在评论区留言!