C#调用skiasharp操作并绘制图片

2024-05-01 02:36

本文主要是介绍C#调用skiasharp操作并绘制图片,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  之前学习ViewFaceCore时采用Panel控件和GDI+将图片及识别出的人脸方框和关键点绘制出来,本文将其修改为基于SKControl和SKCanvas实现相同的显示效果并支持保存为本地图片。
在这里插入图片描述
  新建Winform项目,在Nuget包管理器中搜索并安装一下SkiaSharp和ViewFaceCore包,同时在主界面添加SKControl控件。
在这里插入图片描述
  使用SKBitmap类的Decode方法加载本地图片文件,然后在skControl1的PaintSurface事件中调用SKCanvas.DrawBitmap函数绘制图形,函数原型如下所示:
在这里插入图片描述
  对于ViewFaceCore识别出的人脸区域及关键点坐标,调用SKCanvas的DrawRect、DrawCircle绘制矩形和圆形,同时调用DrawText函数绘制人脸区域顺序号,这些函数在GDI+的Graphics类中都有对应的函数,但是函数名又不完全相同,看着很别扭。还有感觉很怪的是DrawRect函数(如下图所示),如果是直接输入矩形坐标(第一行重载函数),参数格式是左上角坐标及矩形宽和高,而输入矩形对象(第二行重载函数),构建矩形对象时输入的是矩形左上角和右下角坐标,同时绘制圆形时输入参数是圆心坐标和半径,并没有像Graphics类中的绘图函数参数模式那么一致(也可能是用GDI+习惯了,还没有转变过来)。

在这里插入图片描述
在这里插入图片描述
    主要绘图代码和运行效果如下所示:

SKCanvas canvas = e.Surface.Canvas;
canvas.Clear();if (m_image != null)
{canvas.DrawBitmap(m_image, new SKRect(m_startX, m_startY, m_startX + m_image.Width * m_scale, m_startY + m_image.Height * m_scale));if (m_faces.Count > 0){using var paint = new SKPaint{Color = SKColors.Red,Style = SKPaintStyle.Stroke,IsAntialias = true,StrokeWidth = 2};for (int i = 0; i < m_faces.Count; i++){canvas.DrawRect(m_startX + m_faces[i].Face.Location.X * m_scale,m_startY + m_faces[i].Face.Location.Y * m_scale,m_faces[i].Face.Location.Width * m_scale,m_faces[i].Face.Location.Height * m_scale,paint);canvas.DrawText(Convert.ToString(i + 1),m_startX + m_faces[i].Face.Location.X * m_scale,m_startY + m_faces[i].Face.Location.Y * m_scale - skControl1.Font.Height * 1.5f,paint);if (m_faces[i].MarkPoints != null && m_faces[i].MarkPoints.Length > 0){foreach (FaceMarkPoint mp in m_faces[i].MarkPoints){canvas.DrawCircle(m_startX + Convert.ToInt32(mp.X) * m_scale, m_startY + Convert.ToInt32(mp.Y) * m_scale, 3 * m_scale, paint);}}}}
}

在这里插入图片描述
  将SKBitmap对象保存到本地的包括以下步骤:
 &emsp1)新建SKBitmap对象;
 &emsp2)基于SKBitmap对象创建SKCanvas对象;
 &emsp3)依次绘制原始图片、人脸区域及关键点坐标;
 &emsp4)将SKBitmap对象数据保存到本地文件,主要有两种方式,第一种是使用bitmap.Encode方法以指定格式写入本地文件流,测试过程中能以png格式保存,其它格式报错,暂时不清楚原因;第二种方式,安装的SkiaSharp.Views包的SkiaSharp.Views.Desktop提供有扩展函数ToBitmap,支持将SKBitmap对象转换为System.Drawing.Bitmap对象,再调用Bitmap对象的Save函数保存为需要的格式即可。主要代码如下:

using SKBitmap bitmap=new SKBitmap(m_image.Width, m_image.Height);
using SKCanvas canvas = new SKCanvas(bitmap);
canvas.DrawBitmap(m_image, 0, 0);if (m_faces.Count > 0)
{......
}canvas.Flush();bitmap.ToBitmap().Save(sfd.FileName, ImageFormat.Bmp);//using (FileStream fsStream = new FileStream(sfd.FileName,FileMode.CreateNew,FileAccess.Write))
//{
//    if(bitmap.Encode(fsStream,SKEncodedImageFormat.Png, 100))
//    {
//        MessageBox.Show("保存成功");
//    }
//}

参考文献:
[1]https://github.com/mono/SkiaSharp
[2]https://learn.microsoft.com/en-us/dotnet/api/skiasharp?view=skiasharp-2.88
[3]https://blog.csdn.net/ken0online/article/details/132363856
[4]https://www.cnblogs.com/bigben0123/p/14984984.html
[5]https://www.jb51.net/article/257125.htm

这篇关于C#调用skiasharp操作并绘制图片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950520

相关文章

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

Python操作PDF文档的主流库使用指南

《Python操作PDF文档的主流库使用指南》PDF因其跨平台、格式固定的特性成为文档交换的标准,然而,由于其复杂的内部结构,程序化操作PDF一直是个挑战,本文主要为大家整理了Python操作PD... 目录一、 基础操作1.PyPDF2 (及其继任者 pypdf)2.PyMuPDF / fitz3.Fre

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

C#中lock关键字的使用小结

《C#中lock关键字的使用小结》在C#中,lock关键字用于确保当一个线程位于给定实例的代码块中时,其他线程无法访问同一实例的该代码块,下面就来介绍一下lock关键字的使用... 目录使用方式工作原理注意事项示例代码为什么不能lock值类型在C#中,lock关键字用于确保当一个线程位于给定实例的代码块中时

MySQL 强制使用特定索引的操作

《MySQL强制使用特定索引的操作》MySQL可通过FORCEINDEX、USEINDEX等语法强制查询使用特定索引,但优化器可能不采纳,需结合EXPLAIN分析执行计划,避免性能下降,注意版本差异... 目录1. 使用FORCE INDEX语法2. 使用USE INDEX语法3. 使用IGNORE IND

C# $字符串插值的使用

《C#$字符串插值的使用》本文介绍了C#中的字符串插值功能,详细介绍了使用$符号的实现方式,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录$ 字符使用方式创建内插字符串包含不同的数据类型控制内插表达式的格式控制内插表达式的对齐方式内插表达式中使用转义序列内插表达式中使用

C#中的Converter的具体应用

《C#中的Converter的具体应用》C#中的Converter提供了一种灵活的类型转换机制,本文详细介绍了Converter的基本概念、使用场景,具有一定的参考价值,感兴趣的可以了解一下... 目录Converter的基本概念1. Converter委托2. 使用场景布尔型转换示例示例1:简单的字符串到

C#监听txt文档获取新数据方式

《C#监听txt文档获取新数据方式》文章介绍通过监听txt文件获取最新数据,并实现开机自启动、禁用窗口关闭按钮、阻止Ctrl+C中断及防止程序退出等功能,代码整合于主函数中,供参考学习... 目录前言一、监听txt文档增加数据二、其他功能1. 设置开机自启动2. 禁止控制台窗口关闭按钮3. 阻止Ctrl +

C#解析JSON数据全攻略指南

《C#解析JSON数据全攻略指南》这篇文章主要为大家详细介绍了使用C#解析JSON数据全攻略指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、为什么jsON是C#开发必修课?二、四步搞定网络JSON数据1. 获取数据 - HttpClient最佳实践2. 动态解析 - 快速

Python使用openpyxl读取Excel的操作详解

《Python使用openpyxl读取Excel的操作详解》本文介绍了使用Python的openpyxl库进行Excel文件的创建、读写、数据操作、工作簿与工作表管理,包括创建工作簿、加载工作簿、操作... 目录1 概述1.1 图示1.2 安装第三方库2 工作簿 workbook2.1 创建:Workboo