最近呢,在做一个小小的项目,大体呢就是要识别一张试纸条上的条纹灰度值。#荧光试纸条

  分析灰度值在图像处理领域属于一个常规的算法,用Opencv+Python的话实现起来应该非常非常的轻松,但这个项目的难点在于如何使用手机端APP来实现灰度值计算这个效果,因此需要我们来手搓算法。

  本期介绍使用.NET MAUI和SkiaSharp实现二值化、灰度化、连通区域检测和灰度值计算等实现。#NETMAUI #SkiaSharp #Androdi

项目采用.NET 8.0框架,开发软件使用的Visual Studio 2022,支持IOS、Android和PC三端代码通用。

  由于博主手机是Android系统,因此仅在Android和PC进行了测试,Android系统要求最低5.0.

在xaml文件中我们编写UI界面代码,其中包含两个skia画板分别用于显示原始图片和灰度值趋势变化图。  

  Button用于图像处理开始代码测试还有一个Label标签用于显示我们调试过程中显示的信息。

  当然这个界面还需要做很多优化,这个是一个Demo版本。


 本系统的基本图像处理包括对图像做高斯滤波/中值滤波、灰度化、二值化等操作,由于没有合适的库,我们需要手写这些算法。


internal staticclassImageProcess


我们将这些算法统一封装到ImageProcess类中并在类中实现这些函数,由于个别原因,仅展示部分代码和简单解释。

publicstatic SKBitmap Binarize(SKBitmap source, byte threshold = 128)
{
if (source == null)
thrownew ArgumentNullException(nameof(source));
int width = source.Width;
int height = source.Height;
    var result = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
    var srcPixmap = source.PeekPixels();
    var dstPixmap = result.PeekPixels();
    IntPtr srcPtr = srcPixmap.GetPixels();
    IntPtr dstPtr = dstPixmap.GetPixels();
int bytesPerPixel = 4; 
int stride = srcPixmap.RowBytes;
    unsafe
    {
        byte* src = (byte*)srcPtr;
        byte* dst = (byte*)dstPtr;
for (int y = 0; y < height; y++)
        {
            byte* srcRow = src + y * stride;
            byte* dstRow = dst + y * stride;
for (int x = 0; x < width; x++)
            {
                byte b = srcRow[x * 4 + 0];
                byte g = srcRow[x * 4 + 1];
                byte r = srcRow[x * 4 + 2];
// 灰度计算
                byte gray = (byte)(0.299 * r + 0.587 * g + 0.114 * b);
                byte bw = (gray >= threshold) ? (byte)255 : (byte)0;
                dstRow[x * 4 + 0] = bw; // B
                dstRow[x * 4 + 1] = bw; // G
                dstRow[x * 4 + 2] = bw; // R
                dstRow[x * 4 + 3] = 255; // A
            }
        }
    }

return result;
}

灰度化和二值化算法

  灰度化算法比较简单,只要将各个像素点值的RGBA四个通道值按照灰度算法比例进行叠加即可计算出他们的灰度值。

  计算出灰度值之后,将灰度值和我们设置的阈值进行对比即可对图片进行二值化处理。

  其实这里就能体现C/C++/C# 的好处了,能够直接进行底层指针操作,效率高了几十倍。

 由于图片的目标区域只有一个而且目标巨大,因此使用广度优先算法,对联通内容最大的区域进行记录并标记位置和宽高。

最后当我们找到了目标区域之后就很简单了,我们可以直接对目标区域的每行/列区域进行灰度平均值分析,即可获得如果所示效果。

#NETMAUI&nbsp;#
嘉立创PCB

还没有评论,抢个沙发!