当前位置: 首页 > news >正文

未来做哪些网站致富临海app开发

未来做哪些网站致富,临海app开发,wordpress 军事主题,做视频网站容易收录吗前言在游乐场、玻璃天桥、滑雪场等娱乐场所#xff0c;经常能看到有摄影师在拍照片#xff0c;令这些经营者发愁的一件事就是照片太多了#xff0c;客户在成千上万张照片中找到自己可不是件容易的事。在一次游玩等活动或家庭聚会也同理#xff0c;太多了照片导致挑选十分困… 前言在游乐场、玻璃天桥、滑雪场等娱乐场所经常能看到有摄影师在拍照片令这些经营者发愁的一件事就是照片太多了客户在成千上万张照片中找到自己可不是件容易的事。在一次游玩等活动或家庭聚会也同理太多了照片导致挑选十分困难。还好有 .NET只需少量代码即可轻松找到人脸并完成分类。本文将使用 MicrosoftAzure云提供的 认知服务 CognitiveServices API来识别并进行人脸分类可以免费使用注册地址是https://portal.azure.com。注册完成后会得到两个 密钥通过这个 密钥即可完成本文中的所有代码这个 密钥长这个样子非真实密钥fa3a7bfd807ccd6b17cf559ad584cbaa使用方法首先安装 NuGet包 Microsoft.Azure.CognitiveServices.Vision.Face目前最新版是 2.5.0-preview.1然后创建一个 FaceClientstring key fa3a7bfd807ccd6b17cf559ad584cbaa; // 替换为你的keyusing var fc new FaceClient(new ApiKeyServiceClientCredentials(key)){ Endpoint https://southeastasia.api.cognitive.microsoft.com,};然后识别一张照片using var file File.OpenRead(C:\Photos\DSC_996ICU.JPG);IListDetectedFace faces await fc.Face.DetectWithStreamAsync(file);其中返回的 faces是一个 IList结构很显然一次可以识别出多个人脸其中一个示例返回结果如下已转换为 JSON[ { FaceId: 9997b64e-6e62-4424-88b5-f4780d3767c6, RecognitionModel: null, FaceRectangle: { Width: 174, Height: 174, Left: 62, Top: 559 }, FaceLandmarks: null, FaceAttributes: null }, { FaceId: 8793b251-8cc8-45c5-ab68-e7c9064c4cfd, RecognitionModel: null, FaceRectangle: { Width: 152, Height: 152, Left: 775, Top: 580 }, FaceLandmarks: null, FaceAttributes: null } ]可见该照片返回了两个 DetectedFace对象它用 FaceId保存了其 Id用于后续的识别用 FaceRectangle保存了其人脸的位置信息可供对其做进一步操作。 RecognitionModel、 FaceLandmarks、 FaceAttributes是一些额外属性包括识别 性别、 年龄、 表情等信息默认不识别如下图 API所示可以通过各种参数配置非常好玩有兴趣的可以试试 最后通过 .GroupAsync来将之前识别出的多个 faceId进行分类var faceIds faces.Select(x x.FaceId.Value).ToList();GroupResult reslut await fc.Face.GroupAsync(faceIds);返回了一个 GroupResult其对象定义如下public class GroupResult{ public IListIListGuid Groups { get; set; } public IListGuid MessyGroup { get; set; } // ...}包含了一个 Groups对象和一个 MessyGroup对象其中 Groups是一个数据的数据用于存放人脸的分组 MessyGroup用于保存未能找到分组的 FaceId。有了这个就可以通过一小段简短的代码将不同的人脸组分别复制对应的文件夹中void CopyGroup(string outputPath, GroupResult result, DictionaryGuid, (string file, DetectedFace face) faces){ foreach (var item in result.Groups .SelectMany((group, index) group.Select(v (faceId: v, index))) .Select(x (info: faces[x.faceId], i: x.index 1)).Dump()) { string dir Path.Combine(outputPath, item.i.ToString()); Directory.CreateDirectory(dir); File.Copy(item.info.file, Path.Combine(dir, Path.GetFileName(item.info.file)), overwrite: true); } string messyFolder Path.Combine(outputPath, messy); Directory.CreateDirectory(messyFolder); foreach (var file in result.MessyGroup.Select(x faces[x].file).Distinct()) { File.Copy(file, Path.Combine(messyFolder, Path.GetFileName(file)), overwrite: true); }}然后就能得到运行结果如图我传入了 102张照片输出了 15个分组和一个“未找到队友”的分组 还能有什么问题就两个 API调用而已代码一把梭感觉太简单了其实不然还会有很多问题。图片太大需要压缩毕竟要把图片上传到云服务中如果上传网速不佳流量会挺大而且现在的手机、单反、微单都能轻松达到好几千万像素 jpg大小轻松上 10MB如果不压缩就上传一来流量和速度遭不住。二来……其实 Azure也不支持文档(https://docs.microsoft.com/en-us/rest/api/cognitiveservices/face/face/detectwithstream)显示最大仅支持 6MB的图片且图片大小应不大于 1920x1080的分辨率JPEG, PNG, GIF (the first frame), and BMP format are supported. The allowed image file size is from 1KB to 6MB.The minimum detectable face size is 36x36 pixels in an image no larger than 1920x1080 pixels. Images with dimensions higher than 1920x1080 pixels will need a proportionally larger minimum face size.因此如果图片太大必须进行一定的压缩当然如果图片太小显然也没必要进行压缩了使用 .NET的 Bitmap并结合 C# 8.0的 switchexpression这个判断逻辑以及压缩代码可以一气呵成byte[] CompressImage(string image, int edgeLimit 1920){ using var bmp Bitmap.FromFile(image); using var resized (1.0 * Math.Max(bmp.Width, bmp.Height) / edgeLimit) switch { var x when x 1 new Bitmap(bmp, new Size((int)(bmp.Size.Width / x), (int)(bmp.Size.Height / x))), _ bmp, }; using var ms new MemoryStream(); resized.Save(ms, ImageFormat.Jpeg); return ms.ToArray();}竖立的照片相机一般都是 3:2的传感器拍出来的照片一般都是横向的。但偶尔寻求一些构图的时候我们也会选择纵向构图。虽然现在许多 API都支持正负 30度的侧脸但竖着的脸 API基本都是不支持的如下图实在找不到可以授权使用照片的模特了???? 还好照片在拍摄后都会保留 exif信息只需读取 exif信息并对照片做相应的旋转即可void HandleOrientation(Image image, PropertyItem[] propertyItems){ const int exifOrientationId 0x112; PropertyItem orientationProp propertyItems.FirstOrDefault(i i.Id exifOrientationId); if (orientationProp null) return; int val BitConverter.ToUInt16(orientationProp.Value, 0); RotateFlipType rotateFlipType val switch { 2 RotateFlipType.RotateNoneFlipX, 3 RotateFlipType.Rotate180FlipNone, 4 RotateFlipType.Rotate180FlipX, 5 RotateFlipType.Rotate90FlipX, 6 RotateFlipType.Rotate90FlipNone, 7 RotateFlipType.Rotate270FlipX, 8 RotateFlipType.Rotate270FlipNone, _ RotateFlipType.RotateNoneFlipNone, }; if (rotateFlipType ! RotateFlipType.RotateNoneFlipNone) { image.RotateFlip(rotateFlipType); }}旋转后我的照片如下 这样竖拍的照片也能识别出来了。并行速度前文说过一个文件夹可能会有成千上万个文件一个个上传识别速度可能慢了点它的代码可能长这个样子DictionaryGuid, (string file, DetectedFace face) faces GetFiles(inFolder) .Select(file { byte[] bytes CompressImage(file); var result (file, faces: fc.Face.DetectWithStreamAsync(new MemoryStream(bytes)).GetAwaiter().GetResult()); (result.faces.Count 0 ? ${file} not detect any face!!! : ${file} detected {result.faces.Count}.).Dump(); return (file, faces: result.faces.ToList()); }) .SelectMany(x x.faces.Select(face (x.file, face))) .ToDictionary(x x.face.FaceId.Value, x (file: x.file, face: x.face));要想把速度变化可以启用并行上传有了 C#/ .NET的 LINQ支持只需加一行 .AsParallel()即可完成DictionaryGuid, (string file, DetectedFace face) faces GetFiles(inFolder) .AsParallel() // 加的就是这行代码 .Select(file { byte[] bytes CompressImage(file); var result (file, faces: fc.Face.DetectWithStreamAsync(new MemoryStream(bytes)).GetAwaiter().GetResult()); (result.faces.Count 0 ? ${file} not detect any face!!! : ${file} detected {result.faces.Count}.).Dump(); return (file, faces: result.faces.ToList()); }) .SelectMany(x x.faces.Select(face (x.file, face))) .ToDictionary(x x.face.FaceId.Value, x (file: x.file, face: x.face));断点续传也如上文所说有成千上万张照片如果一旦网络传输异常或者打翻了桌子上的咖啡谁知道呢……或者完全一切正常只是想再做一些其它的分析所有东西又要重新开始。我们可以加入下载中常说的“断点续传”机制。其实就是一个缓存记录每个文件读取的结果然后下次运行时先从缓存中读取即可缓存到一个 json文件中class CacheT{ static string cacheFile outFolder $\cache-{typeof(T).Name}.json; Dictionarystring, T cachingData; public Cache() { cachingData File.Exists(cacheFile) switch { true JsonSerializer.DeserializeDictionarystring, T(File.ReadAllBytes(cacheFile)), _ new Dictionarystring, T() }; } public T GetOrCreate(string key, FuncT fetchMethod) { if (cachingData.TryGetValue(key, out T cachedValue)) { return cachedValue; } var realValue fetchMethod(); lock(this) { cachingData[key] realValue; File.WriteAllBytes(cacheFile, JsonSerializer.SerializeToUtf8Bytes(cachingData, new JsonSerializerOptions { WriteIndented true, })); return realValue; } }}注意代码下方有一个 lock关键字是为了保证多线程下载时的线程安全。使用时只需只需在 Select中添加一行代码即可var cache new CacheListDetectedFace(); // 重点DictionaryGuid, (string file, DetectedFace face) faces GetFiles(inFolder) .AsParallel() .Select(file (file: file, faces: cache.GetOrCreate(file, () // 重点 { byte[] bytes CompressImage(file); var result (file, faces: fc.Face.DetectWithStreamAsync(new MemoryStream(bytes)).GetAwaiter().GetResult()); (result.faces.Count 0 ? ${file} not detect any face!!! : ${file} detected {result.faces.Count}.).Dump(); return result.faces.ToList(); }))) .SelectMany(x x.faces.Select(face (x.file, face))) .ToDictionary(x x.face.FaceId.Value, x (file: x.file, face: x.face));将人脸框起来照片太多如果活动很大或者合影中有好几十个人分出来的组将长这个样子 完全不知道自己的脸在哪因此需要将检测到的脸框起来。注意框起来的过程也很有技巧回忆一下上传时的照片本来就是压缩和旋转过的因此返回的 DetectedFace对象值它也是压缩和旋转过的如果不进行压缩和旋转找到的脸的位置会完全不正确因此需要将之前的计算过程重新演算一次using var bmp Bitmap.FromFile(item.info.file);HandleOrientation(bmp, bmp.PropertyItems);using (var g Graphics.FromImage(bmp)){ using var brush new SolidBrush(Color.Red); using var pen new Pen(brush, 5.0f); var rect item.info.face.FaceRectangle; float scale Math.Max(1.0f, (float)(1.0 * Math.Max(bmp.Width, bmp.Height) / 1920.0)); g.ScaleTransform(scale, scale); g.DrawRectangle(pen, new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height));}bmp.Save(Path.Combine(dir, Path.GetFileName(item.info.file)));使用我上面的那张照片检测结果如下有点像相机对焦时人脸识别的感觉 1000个脸的限制.GroupAsync方法一次只能检测 1000个 FaceId而上次活动 800多张照片中有超过 2000个 FaceId因此需要做一些必要的分组。分组最简单的方法就是使用 System.Interactive包它提供了 Rx.NET那样方便快捷的 API这些 API在 LINQ中未提供但又不需要引入 ObservableT那样重量级的东西因此使用起来很方便。这里我使用的是 .Buffer(int)函数它可以将 IEnumerableT按指定的数量如 1000进行分组代码如下foreach (var buffer in faces .Buffer(1000) .Select((list, groupId) (list, groupId)){ GroupResult group await fc.Face.GroupAsync(buffer.list.Select(x x.Key).ToList()); var folder outFolder \gid- buffer.groupId; CopyGroup(folder, group, faces);}总结文中用到的完整代码全部上传了到我的博客数据 Github只要输入图片和 key即可直接使用和运行 https://github.com/sdcb/blog-data/tree/master/2019/20191122-dotnet-face-detection这个月我参加了上海的 .NETConf我上述代码对 .NETConf的 800多张照片做了分组识别出了 2000多张人脸我将其中我的照片的前三张找出来结果如下  ......总的来说这个效果还挺不错渣渣分辨率的照片的脸都被它找到了????。注意不一定非得用 AzureCognitiveServices来做人脸识别国内还有阿里云等厂商也提供了人脸识别等服务并提供了 .NET接口无非就是调用 API注意其限制代码总体差不多。另外如有离线人脸识别需求 Luxand提供了还有离线版人脸识别 SDK名叫 LuxandFaceSDK同样提供了 .NET接口。因为无需网络调用其识别更快匹配速度更是可达每秒5千万个人脸数据精度也非常高亲测好用目前最新版是 v7.1.0授权昂贵但百度有惊喜。微信不能留言有想法的朋友欢迎前往我的博客园进行评论、点赞https://www.cnblogs.com/sdflysha/p/20191122-dotnet-face-detection.html
http://wiki.neutronadmin.com/news/61787/

相关文章:

  • 广东重工建设监理有限公司官方网站密山网站
  • 许昌小学网站建设网站模板超市
  • php网站外包网络科技有限公司取名四个字
  • 七星彩网投网站建设网络营销实施方案
  • 网站使用费用深圳属于哪个省
  • 如何注册网站怎么注册建设工程教育网好还是环球网站好
  • 做隐私的网站网站建设工期时间表
  • 自己做简历网站wordpress html伪静态
  • 潜江做网站网络营销名词解释汇总
  • 二级目录怎么做网站官网网站备案流程图
  • 企业网站建设价格商丘网站推广的方法
  • 成都科技网站建设电话多少内蒙古银税互动平台
  • 保险网站推荐公司画册
  • WordPress臃肿主题怎样做网站排名优化
  • 济南网站开发招聘外包做网站公司
  • 网站织梦温江建设网站
  • 网站手机端优化html演示网站
  • 淄博建企业网站如何起手做网站项目
  • 招工网站58同城wordpress添加new
  • 做外语网站中国网站模板下载
  • 网站后台用什么语言合适50个适合县城做的代理
  • 视频剪辑素材免费网站可以做代销的网站都有哪些
  • 用.net做购物网站甘肃网站备案审核
  • 网站开发的需要的技术人员wordpress修改数据库表
  • 方正网站制作东莞石龙网站建设定制
  • 为什么不建议学网络工程seo网站快速排名软件
  • 做网站找哪家公司好网站首页素材
  • 汽车4s店网站模板个人中心网页
  • 单页网站搭建域名注册解析管理网站
  • 深圳网站建设推广平台小程序商城的服务哪家好