在.NET生态系统中,有多种机器学习和图像处理库可供选择。在本系列的最后一篇文章中,将简要地使用ML.NET。在所有选项中,为什么要使用Keras.NET呢?Keras.NET非常容易学习,因为它基本上是将Python中的经典TensorFlow直接映射到C#。这使得对于不熟悉机器学习的读者来说,跟随示例变得更加容易,如果使用其他替代方案,可能会更加困难。
硬币检测过程分为三个阶段:
颜色为检测任务增加了复杂性,在许多情况下,它们并没有传达出无法从图像亮度中获得的任何相关信息。
由于硬币通常包含一个内圆,应用这种变换来模糊图像。这确保了任何内圆在下一步中被忽略,这样算法就不会错误地认为它们是单独的硬币。
这是为了检测圆形。关于霍夫变换的更多信息可以在这里找到。
让在Visual Studio Community 2019中创建一个.NET Framework 4.7.2控制台应用程序。将解决方案和项目命名为"CoinRecognitionExample",并在其中创建一个名为Detection的文件夹,并在其中创建一个类CoinDetector。
将使用OpenCVSharp,因此可以继续在Visual Studio的Nuget包管理器中安装依赖项。要做到这一点,请转到:
Tools > Nuget Package Manager.
可以看到需要安装的依赖项,这些依赖项与OpenCVSharp有关。
实际的实现发生在CoinDetector类中:
public class CoinDetector {
private Mat _image;
private Mat _originalImage;
private string _pathToFile;
public CoinDetector(string pathToFile) {
_pathToFile = pathToFile;
}
public void ImagePreprocessing() {
_image = new Mat(_pathToFile, ImreadModes.Color);
_originalImage = _image.Clone();
TransformGrayScale();
TransformGaussianBlur();
HoughSegmentation();
}
private void TransformGrayScale() {
_image = _originalImage.CvtColor(ColorConversionCodes.BGR2GRAY);
new Window("Grayed Coins", WindowMode.Normal, _image);
Cv2.WaitKey();
}
private void TransformGaussianBlur() {
Cv2.GaussianBlur(_image, _image, new Size(0, 0), 1);
new Window("Blurred Coins", WindowMode.Normal, _image);
Cv2.WaitKey();
}
private void HoughSegmentation() {
Mat result = _image.Clone();
var circleSegments = Cv2.HoughCircles(_image, HoughMethods.Gradient, 1.02, 40);
for (int i = 0; i < circleSegments.Length; i++) {
Cv2.Circle(result, (Point)circleSegments[i].Center, (int)circleSegments[i].Radius, new Scalar(255, 255, 0), 2);
}
using (new Window("Circles", result)) {
Cv2.WaitKey();
}
}
}
在类的构造函数中,接收硬币图像的路径。这个和ImagePreprocessing方法都是CoinDetector类仅有的两个公共实体。所有其他方法都是私有的,并且与上面列出的三个阶段有关。
在ImageProcessing方法中,保存原始的Mat(像素矩阵)对象,并为其进行变换。Mat类和所有对Cv2类的调用都来自OpenCVSharp。在每次变换后,都会调用new Window来直观地显示变换。
Cv2.HoughCircles的参数取决于正在面临的问题,也就是说,取决于正在处理的图像。代码中显示的参数适合示例。
为了完成硬币检测示例,可以在控制台应用程序项目的主方法中添加以下几行并执行。
string filePath = @"C:/Users/arnal/Documents/coins.jpg";
var coinDetector = new CoinDetector(filePath);
coinDetector.ImagePreprocessing();