SaaS架构:流程架构分析 - 架构师汤师爷 - 博客园

mikel阅读(183)

来源: SaaS架构:流程架构分析 – 架构师汤师爷 – 博客园

大家好,我是汤师爷~

今天聊聊SaaS架构中的流程架构分析。

业务流程的概念

业务流程是企业为实现目标而制定的一套系统化的工作方法。它由一系列有序的业务活动组成,按照既定规则将资源(输入)转化为有价值的结果(输出)。这一过程需结合企业的具体情况和可用资源,旨在为客户创造价值,同时达成企业目标。

通过梳理和设计业务流程,我们可以明确责任分配和绩效要求。这不仅指导和推动流程的建设、优化和整合,还能打破部门间的壁垒,有效管理企业的变革和运营,从而显著提升整体运营效率。

在业务架构设计阶段,业务流程发挥着关键作用。它不仅影响企业资源的有效利用,还直接决定了应用架构中的应用服务的设计。

业务流程有2个核心视角:

  • 端到端流程:强调跨部门的协作与整体效率,贯穿整个业务链条,从客户需求的起点到最终满足的终点。
  • 职能流程:聚焦于各个部门内部的专业化分工,确保每个职能领域的高效运作。

这两种流程相辅相成,共同构建了企业的完整业务体系。

端到端流程

简单来说,端到端流程就是从客户需求发起,到最终客户需求被满足的整个过程。

端到端流程是对价值流的具体实现和优化。前文中讲到,通过梳理价值流,我们可以聚焦客户需求,发现哪些环节是在为客户创造价值,哪些环节存在浪费。然后,基于这些环节,形成高效的端到端流程。

从价值流到端到端流程,就是把企业的价值创造流程化、系统化。通过优化端到端流程,企业可以提高效率、降低成本,更好地满足客户需求。端到端流程的价值包括:

  • 全面了解业务:通过梳理从需求发起到满足的完整过程,揭示各环节衔接和潜在问题,就像清晰的路线图,指明了工作方向。
  • 聚焦核心目标:端到端流程始于客户的真实需求。通过聚焦这些需求,我们能提供更精准的产品或服务,从而避免资源浪费。
  • 增强企业响应能力:面对瞬息万变的市场和客户需求,清晰的流程让企业能够迅速调整策略。当新需求出现时,企业可以快速组合现有的流程模块,及时响应市场机会。

端到端流程如何切分?

端到端流程可以基于客户的核心业务场景进行划分的。这种方法确保流程设计始终以客户需求为中心,让企业能更好地理解和优化客户体验,同时提高内部运营效率。

例如,在零售行业中,销售类端到端流程可以根据客户的购买渠道和消费场景进行细分。例如,我们可以将流程划分为以下几类:

  • 线上渠道销售流程:包括自有商城、社交媒体平台(如微信、抖音等)的销售流程。
  • 线下门店销售流程:涵盖传统实体店、旗舰店和快闪店等不同类型门店的销售流程。
  • 外卖平台销售流程:针对与第三方外卖平台合作的销售流程。

此外,在单一渠道内,我们还可以根据不同的交付方式细分流程。比如:

  • 即时配送流程:适用于需要快速送达的商品。
  • 预约自提流程:允许客户在线下单,选择方便的时间到店取货。
  • 门店服务流程:针对实体店内客户的服务全过程。

职能流程

职能流程是企业各部门为完成特定任务而制定的工作规范。

职能流程有什么价值?通过梳理和完善职能流程,各部门的工作流程变得清晰明确。这为构建端到端流程提供了可靠的基础模块。职能流程的价值包括:

  • 看清企业管理的完整性:职能流程的构建让企业能从业务角度审视职能的完整性。由于企业组织架构通常基于职能分工,梳理各职能流程就像对企业进行全面体检,找出需要改进的方面。
  • 构建端到端流程:梳理职能流程使各部门工作更加明确。这为构建端到端流程提供了可靠基础,没有职能流程架构,端到端流程可能需要重复梳理,并且无法准确反映企业的实际管理情况。

职能流程如何切分?

关键在于以”业务对象”为核心进行划分。业务对象指在业务活动中产生的具有业务含义的文档、表单或数据,它们记录了业务事项的完整过程。以业务对象为基础切分职能流程,可确保每个流程涵盖完整的业务事项,避免过度拆分或模糊不清。

以蛋糕加工作业流程为例,从提交加工单开始,经过领料、配料、烘烤、裱花与装饰,直到加工完成。整个流程都围绕加工单这一对象展开,不应将领料、配料等环节拆分成独立流程,以免导致流程不闭环,增加管理复杂性。

通过以业务对象管理闭环为核心,切分职能流程,企业可统一流程得颗粒度,确保各部门在流程梳理时标准一致。

从价值流到业务流程

“价值流”是企业业务的战略蓝图,概括了整体价值创造过程;”端到端流程”则是这个蓝图的具体实施方案,详细描绘了每个环节的操作细节。

价值流为企业提供了宏观视角,而端到端流程则将其转化为可执行的具体步骤。这种从概念到落地的转化,确保企业能够有效地将战略意图转化为日常运营。

示例:新零售企业的业务流程

下图展示了一个典型的线上预订蛋糕并配送到家得端到端流程,其中包含了多个部门的职能流程。例如,客服部门负责接收、确认蛋糕细节、派单。中央厨房负责蛋糕的制作,物流部门则负责配送。

这些部门各自的工作流程体现了职能流程的具体实施。每个部门的泳道内的活动序列,准确地反映了该部门在整个业务流程中的职责和具体操作步骤。

从整体来看,我们可以清晰地观察到各个职能部门如何协同工作,共同完成从接收订单到最终交付的全过程。

总结

本文深入探讨了业务架构中的流程架构,重点阐述了以下几个方面:

  1. 业务流程的概念:解释了业务流程是企业为实现目标而制定的系统化工作方法,强调了其在企业运营中的重要性。
  2. 核心视角:介绍了端到端流程和职能流程两个核心视角,说明了它们在企业业务体系中的作用。
  3. 端到端流程:详细讨论了其定义、价值和切分方法,强调了以客户需求为中心的重要性。
  4. 职能流程:阐述了其定义、价值和切分方法,强调了以业务对象为核心进行划分的重要性。
  5. 价值流与业务流程的关系:解释了如何从战略层面的价值流转化为可执行的具体业务流程。

本文已收录于,我的技术网站tangshiye.cn 里面有,算法Leetcode详解,面试八股文、BAT面试真题、简历模版、架构设计,等经验分享。

.NET常见的几种项目架构模式,你知道几种?(附带使用情况投票) - 追逐时光者 - 博客园

mikel阅读(237)

来源: .NET常见的几种项目架构模式,你知道几种?(附带使用情况投票) – 追逐时光者 – 博客园

前言

项目架构模式在软件开发中扮演着至关重要的角色,它们为开发者提供了一套组织和管理代码的指导原则,以提高软件的可维护性、可扩展性、可重用性和可测试性。

假如你有其他的项目架构模式推荐,欢迎在文末留言🤞!!!

项目架构模式使用情况收集(微信投票,请在微信中打开参与):https://mp.weixin.qq.com/s/kr1vlt4tj3dSyXyRv-GqOw

三层架构

三层架构是一种经典的软件架构模式,它将应用程序分为三个主要层次:表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)。

分层职责

  • 表示层(UI):负责用户界面和用户交互,是用户直接接触的部分。
  • 业务逻辑层(BLL):处理业务规则和业务逻辑,是应用程序的核心部分。它负责数据的处理、验证、计算等业务操作。
  • 数据访问层(DAL):负责与数据库的交互,包括数据的CRUD(创建、读取、更新、删除)操作。

MVC架构

MVC架构模式将一个应用区分为三部分主要组件:模型、视图、与控制器。这种模式有助实现关注分离,使用这种模式,用户请求被路由到控制器,控制器负责与模型协作以执行用户操作和/或返回请求结果。极大地提高了应用程序的可维护性和扩展性。

分层职责

  • 模型(Model):表示应用程序和任何应由其执行的业务逻辑或操作的状态。业务逻辑应与保持应用程序状态的任何实现逻辑一起封装在模型中。
  • 视图(View):负责通过用户界面展示内容。它们使用 Razor 视图引擎在 HTML 标记中嵌入 .NET 代码。视图中应该有最小逻辑,并且其中的任何逻辑都必须与展示内容相关。
  • 控制器(Controller):处理用户交互、使用模型并最终选择要呈现的视图的组件。在 MVC 应用程序中,视图仅显示信息;控制器处理并响应用户输入和交互。在 MVC 模式中,控制器是初始入口点,负责选择要使用的模型类型和要呈现的视图。

DDD分层架构

领域驱动设计(Domain-Driven Design,简称DDD)是一种软件设计方法和理念,由Eric Evans在2004年提出。它通过深入理解业务领域,将复杂的业务逻辑转化为可维护、可扩展的软件系统。DDD的核心在于建立一个丰富的领域模型,这个模型能够反映业务实体、业务规则和业务流程。

DDD 强调以领域模型为核心来驱动软件的设计和开发。

分层职责

  • 表示层(UI): 负责处理用户界面和用户交互,它可以是Web界面、移动应用程序或桌面应用程序等形式。表示层负责接收用户的输入和展示数据给用户,但它不包含业务逻辑。
  • 应用层(Application): 表示层与领域层的中介,编排业务对象执行特定的应用程序任务,使用应用程序逻辑实现用例。
  • 领域层(Domain): 包含业务对象以及业务规则,是应用程序的核心。领域层的设计应遵循领域驱动设计的原则,通过深入理解业务领域,将业务知识和业务逻辑封装在领域模型中,以提高软件系统的可维护性和可扩展性。
  • 基础设施层(Infrastructure): 提供技术基础设施支持,如数据库访问、消息队列、缓存等。

整洁架构

整洁架构(Clean Architecture)是一种软件架构设计原则,由罗伯特·C·马丁(Robert C. Martin)提出,它旨在使软件系统更加灵活、可维护和可测试,其核心目标是构建一种简洁、灵活且易于维护的系统结构。

分层职责

  • 实体层(Entities):实体层代表了系统中的核心业务概念和对象。这一层包含了那些在整个系统的生命周期中持续存在且具有明确业务含义的实体。
  • 用例层(Use Cases):用例层包含了系统的具体业务逻辑和用例。它协调实体层和其他层之间的交互,以实现特定的业务功能。
  • 接口适配器层(Interface Adapters):接口适配器层将用例层与外部系统(如数据库、用户界面、外部服务等)进行连接。它将外部系统的接口转换为用例层可以理解的形式,并将用例层的输出转换为适合外部系统的格式。
  • 框架与驱动层(Frameworks and Drivers):框架与驱动层包含了外部的框架和工具,如数据库、Web 框架、消息队列等。这一层通常是由具体的技术实现组成,为上层提供基础设施支持。

CQRS架构

CQRS(命令和查询责任分离)是一种架构模式,旨在将一个系统的读操作(查询)和写操作(命令)分离开来。通过这种分离,系统可以在处理读写请求时进行不同的优化,从而提高系统性能、可扩展性和维护性。

分层职责

  • Presentation(表现层):负责处理用户界面的请求和响应。它接收用户输入并将其传递给后端服务,同时将后端服务的响应展示给用户。
  • Validation(验证):在命令被处理之前,对用户输入的数据进行验证,确保数据的合法性和完整性。
  • Commands(命令):封装用户请求的写操作,如创建、更新或删除数据的操作。
  • Domain Logic(领域逻辑):执行核心业务逻辑和规则,命令处理器通常会调用领域模型和领域服务来执行业务逻辑,确保业务规则得到正确应用。
  • Data Persistence(数据持久化):在命令处理完成后,数据会被保存到写数据存储中,确保数据的一致性和持久性。
  • Write Data Store(写数据存储):写数据存储负责管理所有写操作的数据,包括事务处理和数据一致性。
  • Read Data Store(读数据存储):读数据存储优化了读取操作的性能,提供快速响应的查询结果。
  • Queries(查询):查询对象被传递给查询处理器,查询处理器直接从读数据存储中获取数据,并生成DTOs返回给展示层。

最后总结

每种项目架构模式都有其各自特点和适用场景,开发者应根据项目的具体需求和技术栈来选择最合适的项目架构模式。

参考文章

DotNetGuide技术社区

  • DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目框架推荐、求职和招聘资讯、以及解决问题的平台。
  • 在DotNetGuide技术社区中,开发者们可以分享自己的技术文章、项目经验、学习心得、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
  • 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。

.NET 7+Angular 4 轻量级新零售进销存系统 - 小码编匠 - 博客园

mikel阅读(203)

来源: .NET 7+Angular 4 轻量级新零售进销存系统 – 小码编匠 – 博客园

前言

给大家推荐一个专为新零售快消行业打造了一套高效的进销存管理系统。

系统不仅具备强大的库存管理功能,还集成了高性能的轻量级 POS 解决方案,确保页面加载速度极快,提供良好的用户体验。

项目介绍

Dorisoy.POS 是一款基于 .NET 7 和 Angular 4 开发的新零售快消进销存管理系统。

系统集成了先进的库存管理和高性能的轻量级 POS 功能,拥有出色的性能和快速的页面加载速度,确保用户获得流畅的操作体验。

无论是快速销售还是库存控制,Dorisoy.POS 都能实现业务流程的自动化与优化。

项目功能

  • 客户管理:记录并维护所有客户的详细信息。
  • 产品管理:全面管理产品信息,包括品牌、类别、单位、销售价格、采购价格和税率。
  • 供应商管理:管理供应商的账单和发货地址信息。
  • 采购订单管理
  • 处理包含多种产品和税率的采购订单。
  • 生成并打印采购订单发票/收据。
  • 根据请求/报价创建多个采购订单。
  • 管理采购订单的付款。
  • 支持采购订单中的退货处理,并生成相关发票/收据。
  • 在采购订单交付日期收到自动通知/电子邮件。
  • 销售订单管理
  • 管理包含多种产品和税率的销售订单。
  • 生成并打印销售订单发票/收据。
  • 管理销售订单的付款。
  • 支持销售订单中的退货处理,并生成相关发票/收据。
  • 在销售订单发货日期收到自动通知/电子邮件。
  • 库存管理
  • 自动管理产品库存,包括平均销售额、采购价格等。
  • 支持手动调整库存。
  • 查看所有采购、销售、采购退货和销售退货的历史记录。
  • 费用管理:记录和管理所有公司的费用及其类别。
  • 查询管理
  • 跟踪所有查询及其产生的活动。
  • 设置特定日期的提醒,以发送通知或电子邮件。
  • 仪表板
  • 快速统计销售、采购、销售退货及采购退货总额。
  • 展示月度畅销产品排行榜。
  • 提供带有提醒功能的日历。
  • 显示最新查询列表。
  • 展示最近销售订单的预计发货情况。
  • 显示最近采购订单的预计收货情况。
  • 报告: 提供多种报告,包括但不限于采购订单、销售订单、支出、损益分析等。
  • 生成产品采购、销售报告及库存报告。
  • 提醒计划程序:支持设置每日、每周、每月、季度、半年、每年或特定日期的提醒。
  • 多语言支持:默认支持英语和中文,可快速添加其他语言。
  • 用户和角色管理:管理员可通过管理面板创建用户和角色,并分配权限。
  • 权限管理:授予员工特定权限,覆盖角色和用户权限。
  • 高性能:高级轻量级 POS 系统,具有闪电般的性能和快速的页面加载速度。
  • 电子邮件集成:使用文本编辑器设置预定义的电子邮件模板,管理 SMTP 设置,并一键发送邮件。
  • 完整源代码:提供完整的源代码和 SQL Server 及 MySQL 数据库的版本。

项目环境

  • 核心框架:.NET 6 SDK
  • 数据库:SQL SERVER 或 MYSQL 8+
  • Node.js(同时安装 npm 前端包管理工具)
  • 开发工具:Visual Studio 2022

项目运行

1、选择数据库

根据您的需求,在相应的源文件夹中选择 SQL 或 MySQL API。

2、打开解决方案文件

使用 Visual Studio 2022 打开 .NET 核心文件夹中的解决方案文件 POS.sln。

3、还原 NuGet 包

在解决方案资源管理器中,右键单击解决方案,选择”管理 NuGet 包”,并确保所有依赖项已安装。

4、配置数据库连接字符串

修改 POS.API 项目中的 appsettings.Development.json 文件中的数据库连接字符串。

5、设置启动项目

在解决方案资源管理器中,右键单击 POS.API 项目,然后从上下文菜单中选择”设为启动项目”。

6、运行项目

按 F5 运行项目

项目展示

1、仪表盘

2、销售订单

3、库存管理

4、客户信息

项目地址

GitHub:https://github.com/dorisoy/Dorisoy.POS

在C# 中Sql 执行超时的问题 - 郝奕 Frank Hao - 博客园

mikel阅读(186)

来源: 在C# 中Sql 执行超时的问题 – 郝奕 Frank Hao – 博客园

解决方法:

C#代码
SQLCommand selectCommand = new SQLCommand(queryText, this.openConnection());
//得到Web.config里DB_ConnectionString中Connection Timeout=90
selectCommand.CommandTimeout = cn.ConnectionTimeout;
或者
SQLCommand selectCommand = new SqlCommand(queryText, this.openConnection());
selectCommand.CommandTimeOut=0;

Web.config(.NET 2005)
<connectionStrings>
<add name=”DB_ConnectionString” connectionString=”Data Source=xxx.xxx.xxx.xxx;Initial Catalog=DB NAME;Persist Security Info=false;User ID=sa;Password=sa;Connection Timeout=90;” providerName=”System.Data.SqlClient”/>
</connectionStrings>

CommandTimeout 属性

指示执行命令期间在终止尝试和产生错误之前需等待的时间。

设置和返回值

设置或返回 Long 值,该值指示等待命令执行的秒数。默认值为 30。

说明

用 Connection 对象或 Command 对象的 CommandTimeout 属性来允许因网络拥挤或服务器负载过重产生的延迟而取消 Execute 方法调用。如果在 CommandTimeout 属性设置的时间间隔内未执行完命令,将产生错误,并且 ADO 取消该命令。如果将属性设置为零,ADO 将一直等待到命令执行完毕。请确保正在为其编写代码的提供者和数据源支持 CommandTimeout 功能。

Connection 对象的 CommandTimeout 设置对同一 Connection 中 Command 对象上的 CommandTimeout 设置没有影响,即 Command 对象的 CommandTimeout 属性不继承 Connection 对象的 CommandTimeout 值。

在 Connection 对象上,打开 Connection 后,CommandTimeout 属性将保持为读/写。

ConnectionTimeout 属性

指示在终止尝试和产生错误前建立连接期间所等待的时间。

设置和返回值

设置或返回指示等待连接打开的时间的长整型值(单位为秒)。默认值为 15。

说明

如果由于网络拥塞或服务器负载过重导致的延迟使得必须放弃连接尝试时,请使用 Connection 对象的 ConnectionTimeout 属性。如果打开连接前所经过的时间超过 ConnectionTimeout 属性上设置的时间,将产生错误,并且 ADO 将取消该尝试。如果将该属性设置为零,ADO 将无限等待直到连接打开。请确认正在对其编写代码的提供者会支持 ConnectionTimeout 功能。

连接关闭时 ConnectionTimeout 属性为读/写,而打开时其属性为只读。

还原数据库提示“ 因为数据库正在使用,所以无法获得对数据库的独占访问权_还原数据库失败 因为数据库正在使用-CSDN博客

mikel阅读(198)

来源: 还原数据库提示“ 因为数据库正在使用,所以无法获得对数据库的独占访问权_还原数据库失败 因为数据库正在使用-CSDN博客

 

问题:提示错误信息:
因为数据库正在使用,所以无法获得对数据库的独占访问权。

解决方案:
解决方案1.
如果你使用管理工具还原数据库并且在SQL Server Management Studio 2016或以上版本的话,可以在还原的时候勾选”关闭到目标数据库的现有链接”
解决方案2.
SQL SERVER 2016或以下的版本的
在需要还原的数据库上右击,在右键菜单命令上选择**“属性”- >“选项”- >“状态”- >“限制访问”- >“Single”**
单用户模式,直接还原,完成后把访值改回来
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/qq_36701078/article/details/111560416

Scratch的下载与安装_scratch1.0安装包-CSDN博客

mikel阅读(586)

来源: Scratch的下载与安装_scratch1.0安装包-CSDN博客

如果你在某搜索引擎用这个,就是离被骗钱不远了

 

添加图片注释,不超过 140 字(可选)

废话不多说,直接放软件安装包。重要的事情说三遍,收费的全是骗人的!收费的全是骗人的!收费的全是骗人的!

夸克网盘分享​ Scratch软件下载

包里各版本的软件都有,根据自己的需求下载一个就行:

 

添加图片注释,不超过 140 字(可选)

Scratch有三个大的版本,Scratch1.0(几乎没人用了),Scratch2.0,支持win7系统,现在用的人也比较少。最新的版本是Scratch3.0,现在更新到了3.29.1,大家直接下载安装就可以。其它版本的也建议保存,老版本的可能不好找了。

MAC版本的在这里:

 

添加图片注释,不超过 140 字(可选)

安装方式:

1,双击安装文件:

 

添加图片注释,不超过 140 字(可选)

2,选中为使用这台电脑的任何人安装(所有用户),点击安装。

 

添加图片注释,不超过 140 字(可选)

3,正在安装

 

添加图片注释,不超过 140 字(可选)

4,取消运行Scratch 3(R)的选中框,点击完成。Scratch程序就安装好了。

 

添加图片注释,不超过 140 字(可选)

5,电脑桌面会出现Scratch图标。双击打开,就是咱们的Scratch程序了。

 

添加图片注释,不超过 140 字(可选)

大家在下载过程中遇到问题可以流言,我会在评论区回复。
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/liuhejianwei/article/details/140909302

C# 解析获取Url参数值 - 傅小灰 - 博客园

mikel阅读(297)

来源: C# 解析获取Url参数值 – 傅小灰 – 博客园

今天遇到一个需求,需要处理通过接口传过来的一个参数,参数内容为一个拼接好的Url地址,且该地址还会携带了一些额外的参数,包括但不限于数字,字符串,json串。样例如下:

http://www.cplemom.com/?url=https://www.cnblogs.com/cplemom/?id=15&data={"id":12,"name":"今天天气不错"}

现在的问题就是,我需要将url参数中的data值的json中的id修改为url参数中id的值,然后再拼接成完整的url去获取数据。简单来说就是将url进行如下改变,现在问题的重点就在于如何根据url获取对应的参数值了。

//处理前
https://www.cnblogs.com/cplemom/?id=15&data={"id":12,"name":"今天天气不错"}

//处理后
https://www.cnblogs.com/cplemom/?id=15&data={"id":15,"name":"今天天气不错"}

Url编码

这里插一句,在将url作为参数进行请求的时候,需要注意一些特殊字符(比如 ? "" / 等)对请求的影响,特别是发送Get请求的时候。可以在发送请求前,先对url进行编码处理。

encodeURIComponent(url) //js
HttpUtility.UrlEncode(url) //C#
url.QueryEscape(url) //Go

获取Url参数

仔细思考了下,解析url获取参数的也无非通过分割关键字符来实现。区别就是分割字符的方式是通过正则匹配或者遍历字符罢了。下面就介绍框架带的方法,然后通过总结一些规律,最后自己实现一个方法。

我知道肯定有很多朋友经常使用HttpUtility类中的UrlEncode/UrlDecode方法,其实该类还有一个ParseQueryString方法,用来解析url参数。该方法需要传入url参数部分字符串,然后返回一个NameValueCollection对象(以key/value的形式记录了所有参数)。

string url = "https://www.cnblogs.com/cplemom/?id=15&data={'id':12,'name':'今天天气不错'}";
var uri = new Uri(url);

var collection= HttpUtility.ParseQueryString(uri.Query);//默认采用UTF-8编码,当然也可以传入特定编码进行解析
//var collection= HttpUtility.ParseQueryString(uri.Query,Encoding.ASCII);

Console.WriteLine(collection["data"]);//输出结果:  {'id':12,'name':'今天天气不错'}

该方法有几个要注意的点

  1. uri.Query是?开头的,但是在转为键值对以后被自动过滤掉了,且只会过滤一个?字符
  2. 参数内容会自动使用UTF-8解码
  3. 对于传递的数组参数(?ids=1&ids=2),会通过,拼接
  4. 在参数字符中通过&划分后,只会把第一个=前的字符串作为key

基于上述一些要求就可以自己写一个解析参数的方式了。

public static Dictionary<string, string> ParseQueryString(string url)
{
	if (string.IsNullOrWhiteSpace(url))
	{
		throw new ArgumentNullException("url");
	}
	var uri = new Uri(url);
	if (string.IsNullOrWhiteSpace(uri.Query))
	{
		return new Dictionary<string, string>();
	}
                  //1.去除第一个前导?字符
	var dic = uri.Query.Substring(1)
                        //2.通过&划分各个参数
			.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
                        //3.通过=划分参数key和value,且保证只分割第一个=字符
			.Select(param => param.Split(new char[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries))
                        //4.通过相同的参数key进行分组
			.GroupBy(part => part[0], part => part.Length > 1 ? part[1] : string.Empty)
                        //5.将相同key的value以,拼接
			.ToDictionary(group => group.Key, group => string.Join(",", group));

	return dic;
}

总结

总体来说这只是一个小小的功能点,往往框架本身就帮我们封装好了解析url获取参数的方法,但是自己去实现的时候,可能就会有这样那样的情况没有考虑到。最后如果有遇到相似需求的朋友,我建议还是用HttpUtility.ParseQueryString()吧~~~

基于OpenCV的刷脸考勤&人脸校验&用户管理系统(源码&教程) | qunmasj

mikel阅读(294)

来源: 基于OpenCV的刷脸考勤&人脸校验&用户管理系统(源码&教程) | qunmasj

由于图床过期,图片无法正常显示,有图阅览请移步以下Gitee/Github网址,文末获取【源码和部署教程】或者通过以下Gitee/Github的文末邮件获取

Gitee(推荐国内访问): https://gitee.com/qunmasj/projects

Github(推荐国外访问): https://github.com/qunshansj?tab=repositories

# 1.研究背景
随着人工智能时代的来临,深度学习赋予了以人脸图像为中心的计算机视觉任务更多的可能。人脸检测是人脸识别系统组成的关键部分之一,其目的是检测出任意给定图片中的包含的一个或多个人脸,是人脸识别、表情识别等下游任务的基础。人脸识别是通过采集包含人脸的图像或视频数据,通过对比和分析人脸特征信息从而实现身份识别的生物识别技术,是人脸识别系统的核心组件。如今人脸识别系统广泛应用于写字楼、学校、医院和车站等需要对入场人员身份信息进行确认和鉴别的场所。进而利用人脸检测算法检测出摄像头拍摄图片中包含的人脸,再使用识别算法对比当前人脸特征和数据库内的人脸特征,确认人员身份,最终输出人员相关的身份信息并生成打卡记录。在实际的运行测试中,针对戴口罩的场景也有优异的表现,满足公司打卡应用的实际需求。

2.视频演示

基于OpenCV的刷脸考勤&人脸校验&用户管理系统(源码&教程)_哔哩哔哩_bilibili

3.考勤打卡算法原理

人脸识别

基于Python语言,通过对图像预处理、提取特征向量、与人脸数据库中数据进行校验进而判别人物身份的一项技术。具体流程图如图所示。
12.png
(1)人脸图像采集与对齐:首先 Dlib检测人脸并输出人脸矩形的四个坐标点,即在图片中识别到人脸的位置。然后由OpenCV ( Open Source Computer Vision Library)从底层采集人脸图像并转换成数据集,并通过对图像的灰度化、二值化等对人脸图像进行预处理【5】。
人脸对齐即在检测到的人脸矩阵中找到人脸上的眼鼻口和脸部轮廓等标志性特征向量。
(2)计算人脸图像与待识别人脸对应的特征向量:首先利用Dlib中的梯度提升树(Gradient Boosting Deci-sion Tree,GBDT)提取人脸68个特征点【6】。再利用ResNet残差学习深度神经网络为待识别人脸创建128维特征向量T。
(3)计算人脸间的欧式距离:假设数据库中的人脸图像向量与待识别人脸向量分别为x (x1,x2,X3…,Xn)与y(yi,y2zy3.….yn),根据欧式距离公式(1)计算两向量欧式距离,为人脸校验提供数据。
(4)人脸校验:两个人脸特征向量的欧式距离越小,则两张人脸越相似,若人脸图像与待识别人像之间的欧式距离小于设定的阈值时,则判定为同一人。

算法流程图

13.png

4.刷脸&密码登录(用户&管理员)

2.png

8.png

代码实现

用户注册

plaintext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
def register(self):
    username = self.textEdit_1.toPlainText()
    password = self.textEdit_2.toPlainText()
    #print(username,password)


    # 执行的都是原生SQL语句
    sql = '''
    SELECT Name
    FROM   users
    '''

    has_name = 0
    for row in self.get(sql):
        if username == str(row[0]):
            #print(row)
            has_name = 1
            self.textEdit_1.setText('用户已经注册')
            break
    if not has_name:
        savepath = './images_db'
        if not os.path.exists(savepath):
            os.makedirs(savepath)
        # 打开摄像头
        detector = dlib.get_frontal_face_detector()
        predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
        cap = cv2.VideoCapture(0)
        for x in range(50):
            ret, image = cap.read()
            imagecopy = image.copy()
            img_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

            # 使用人脸检测器检测每一帧图像中的人脸。并返回人脸数rects
            faces = detector(img_gray, 0)

            # 待会要显示在屏幕上的字体
            font = cv2.FONT_HERSHEY_SIMPLEX

            # 如果检测到人脸
            if (len(faces) != 0):

                for i in range(len(faces)):
                    # enumerate方法同时返回数据对象的索引和数据,k为索引,d为faces中的对象
                    for k, d in enumerate(faces):
                        # 用红色矩形框出人脸
                        cv2.rectangle(imagecopy, (d.left(), d.top()), (d.right(), d.bottom()), (0, 255, 0))
                        # 计算人脸热别框边长
                        face_width = d.right() - d.left()

                        shape = predictor(image, d)
                        mouth_width = (shape.part(54).x - shape.part(48).x) / face_width  # 嘴巴咧开程度
                        mouth_higth = (shape.part(66).y - shape.part(62).y) / face_width  # 嘴巴张开程度
                        for i in range(68):
                            if i > 27:
                                cv2.circle(imagecopy, (shape.part(i).x, shape.part(i).y), 2, (0, 0, 255), -1, 2)

            self.showimg(imagecopy)
            QApplication.processEvents()
        cv2.imwrite(savepath + '/' + str(username) + '.jpg', image, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
        val = (str(username),str(password))
        sql = 'insert into users (Name , Password) values (%s, %s)'
        self.add(sql, val)
        self.textEdit_1.setText('注册成功')

用户登录

plaintext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
def login(self):
    global inname
    username = self.textEdit_1.toPlainText()
    password = self.textEdit_2.toPlainText()
    # print(username,password)

    # 执行的都是原生SQL语句
    sql = '''
            SELECT Name, Password
            FROM   users
            '''
    has_name = 0
    for row in self.get(sql):
        if username == 'administrator' and username == str(row[0]):
            has_name = 1
            if password == str(row[1]):
                print('密码正确,登陆成功')
                inname = str(row[0])
                MainWindow.close()
                ui4.show()
                try:
                    show = cv2.imread('./images_db/' + str(inname) + '.jpg')
                    ui4.showimg(show)
                except:
                    pass
                ui4.printf('密码正确,登陆成功')
                ui4.printf('欢迎您,管理员')
            else:
                self.textEdit_2.setText('密码错误')
            break

        if username == str(row[0]):
            # print(row)
            has_name = 1
            if password == str(row[1]):
                print('密码正确,登陆成功')
                inname = str(row[0])
                MainWindow.close()
                ui2.show()
                try:
                    show = cv2.imread('./images_db/' + str(inname) + '.jpg')
                    ui2.showimg(show)
                except:
                    pass
                ui2.printf('密码正确,登陆成功')
                ui2.printf('欢迎您 ' + str(inname))
            else:
                self.textEdit_2.setText('密码错误')
            break

    if not has_name:
        self.textEdit_1.setText('该用户不存在')

5.用户考勤打卡&管理员考勤查看

10.png

11.png

6.管理员用户信息管理&MySQL增删改查

9.png

MySQL的主要优势

运行速度快,MySQL体积小,命令执行的速度快。
使用成本低。MySQL是开源的,且提供免费版本,对大多数用户来说大大降低了使用成本。
使用容易。与其他大型数据库的设置和管理相比,其复杂程度较低,易于使用。
可移植性强。MySQL能够运行与多种系统平台上,如windouws,Linux,Unix等。
适用更多用户。MySQL支持最常用的数据管理功能,适用于中小型企业甚至大型网站应用。

Mysql增删改查

代码实现如下

plaintext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def get(self,sql):
    try:
        conn = MySQLdb.connect(
            host=host,  # 主机名
            user=user,  # 用户名
            passwd=passwd,  # 密码
            db=db)  # 数据库名

        # 查询前,必须先获取游标
        cursor = conn.cursor()
        cursor.execute(sql)
        results = cursor.fetchall()
        cursor.close()  # 关闭游标连接
        conn.close()  # 关闭数据库连接
        return results
    except Exception:
        print("查询失败")

def update(self,sql,cg):
    try:
        conn = MySQLdb.connect(
            host=host,  # 主机名
            user=user,  # 用户名
            passwd=passwd,  # 密码
            db=db)  # 数据库名

        # 查询前,必须先获取游标
        cursor = conn.cursor()
        cursor.execute(sql,cg)
        conn.commit()     # 提交
        cursor.close()  # 关闭游标连接
        conn.close()  # 关闭数据库连接

    except Exception:
        print("修改失败")

def add(self,sql,val):
    try:
        conn = MySQLdb.connect(
            host=host,  # 主机名
            user=user,  # 用户名
            passwd=passwd,  # 密码
            db=db)  # 数据库名

        # 查询前,必须先获取游标
        cursor = conn.cursor()
        cursor.execute(sql, val)
        conn.commit()     # 提交
        cursor.close()  # 关闭游标连接
        conn.close()  # 关闭数据库连接
    except Exception:
        print("插入失败")

def delete(self,sql):
    try:
        conn = MySQLdb.connect(
            host=host,  # 主机名
            user=user,  # 用户名
            passwd=passwd,  # 密码
            db=db)  # 数据库名

        # 查询前,必须先获取游标
        cursor = conn.cursor()
        cursor.execute(sql)
        conn.commit()
        cursor.close()  # 关闭游标连接
        conn.close()  # 关闭数据库连接
    except Exception:
        print("删除失败")

7.人脸校验&年龄、性别、民族识别(防替考&本人检测)

5.png

参考原博客提出的思路

代码实现

plaintext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import cv2
import numpy as np
import face_recognition
from age_detection import f_my_age
from gender_detection import f_my_gender
from race_detection import f_my_race
from emotion_detection import f_emotion_detection
from my_face_recognition import f_main



# instanciar detectores
age_detector = f_my_age.Age_Model()
gender_detector =  f_my_gender.Gender_Model()
race_detector = f_my_race.Race_Model()
emotion_detector = f_emotion_detection.predict_emotions()
rec_face = f_main.rec()
#----------------------------------------------



def get_face_info(im):
    # face detection
    boxes_face = face_recognition.face_locations(im)
    out = []
    if len(boxes_face)!=0:
        for box_face in boxes_face:
            # segmento rostro
            box_face_fc = box_face
            x0,y1,x1,y0 = box_face
            box_face = np.array([y0,x0,y1,x1])
            face_features = {
                "name":[],
                "age":[],
                "gender":[],
                "race":[],
                "emotion":[],
                "bbx_frontal_face":box_face             
            } 

            face_image = im[x0:x1,y0:y1]

            # -------------------------------------- face_recognition ---------------------------------------
            face_features["name"] = rec_face.recognize_face2(im,[box_face_fc])[0]

            # -------------------------------------- age_detection ---------------------------------------
            age = age_detector.predict_age(face_image)
            face_features["age"] = str(round(age,2))

            # -------------------------------------- gender_detection ---------------------------------------
            face_features["gender"] = gender_detector.predict_gender(face_image)

            # -------------------------------------- race_detection ---------------------------------------
            face_features["race"] = race_detector.predict_race(face_image)

            # -------------------------------------- emotion_detection ---------------------------------------
            _,emotion = emotion_detector.get_emotion(im,[box_face])
            face_features["emotion"] = emotion[0]

            # -------------------------------------- out ---------------------------------------       
            out.append(face_features)
    else:
        face_features = {
            "name":[],
            "age":[],
            "gender":[],
            "race":[],
            "emotion":[],
            "bbx_frontal_face":[]             
        }
        out.append(face_features)
    return out



def bounding_box(out,img):
    for data_face in out:
        box = data_face["bbx_frontal_face"]
        if len(box) == 0:
            continue
        else:
            x0,y0,x1,y1 = box
            img = cv2.rectangle(img,
                            (x0,y0),
                            (x1,y1),
                            (0,0,255),2);
            thickness = 2
            fontSize = 0.6
            step = 13

            try:
                cv2.putText(img, "age: " +data_face["age"], (x0, y0-7), cv2.FONT_HERSHEY_SIMPLEX, fontSize, (0,255,0), thickness)
            except:
                pass
            try:
                cv2.putText(img, "gender: " +data_face["gender"], (x0, y0-step-15*1), cv2.FONT_HERSHEY_SIMPLEX, fontSize, (0,255,0), thickness)
            except:
                pass
            try:
                cv2.putText(img, "race: " +data_face["race"], (x0, y0-step-15*2), cv2.FONT_HERSHEY_SIMPLEX, fontSize, (0,255,0), thickness)
            except:
                pass
            try:
                cv2.putText(img, "emotion: " +data_face["emotion"], (x0, y0-step-15*3), cv2.FONT_HERSHEY_SIMPLEX, fontSize, (0,255,0), thickness)
            except:
                pass
            try:
                cv2.putText(img, "name: " +data_face["name"], (x0, y0-step-15*4), cv2.FONT_HERSHEY_SIMPLEX, fontSize, (0,255,0), thickness)
            except:
                pass
    return img

8.情绪&状态&表情识别(用户状态监测)

7.png

参考原博客提出的方案

背景

面部表情识别技术主要的应用领域包括人机交互、智能控制、安全、医疗、通信等领域。笔者目前接触过的两个领域,
第一个是商场门店的顾客情绪分析。即通过摄像头捕获商场或门店的顾客画面,分析其面部表情,再进一步解读出客人的情绪信息,从而分析顾客在商场的体验满意度。
第二个是人机交互。在笔者参与的一个教育辅助机器人项目中,负责视觉部分的研发工作,其中一项功能就是通过面部表情分析来判断机器人眼前的用户的情绪和心理。

代码实现

plaintext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#encoding:utf-8
import pandas as pd
import numpy as np
import scipy.misc as sm
import os
 
emotions = {
    '0':'anger', #生气
    '1':'disgust', #厌恶
    '2':'fear', #恐惧
    '3':'happy', #开心
    '4':'sad', #伤心
    '5':'surprised', #惊讶
    '6':'normal', #中性
}
 
#创建文件夹
def createDir(dir):
    if os.path.exists(dir) is False:
        os.makedirs(dir)
 
def saveImageFromFer2013(file):
 
 
    #读取csv文件
    faces_data = pd.read_csv(file)
    imageCount = 0
    #遍历csv文件内容,并将图片数据按分类保存
    for index in range(len(faces_data)):
        #解析每一行csv文件内容
        emotion_data = faces_data.loc[index][0]
        image_data = faces_data.loc[index][1]
        usage_data = faces_data.loc[index][2]
        #将图片数据转换成48*48
        data_array = list(map(float, image_data.split()))
        data_array = np.asarray(data_array)
        image = data_array.reshape(48, 48)
 
        #选择分类,并创建文件名
        dirName = usage_data
        emotionName = emotions[str(emotion_data)]
 
        #图片要保存的文件夹
        imagePath = os.path.join(dirName, emotionName)
 
        # 创建“用途文件夹”和“表情”文件夹
        createDir(dirName)
        createDir(imagePath)
 
        #图片文件名
        imageName = os.path.join(imagePath, str(index) + '.jpg')
 
        sm.toimage(image).save(imageName)
        imageCount = index
    print('总共有' + str(imageCount) + '张图片')
 
 
if __name__ == '__main__':
    saveImageFromFer2013('fer2013.csv')

9.用户疲劳检测

6.png

参考原博客

(6条消息) Python基于OpenCV的工作疲劳检测系统[源码&UI界面&部署教程]_weixin__qunmasj的博客-CSDN博客

算法逻辑

定义 EYE_AR_THRESH。如果眼睛纵横比低于此阈值,我们将开始计算人闭上眼睛的帧数。
如果该人闭上眼睛的帧数超过 EYE_AR_CONSEC_FRAMES,我们将发出警报。

在实验中,我发现 0.3 的 EYE_AR_THRESH 在各种情况下都能很好地工作(尽管您可能需要为自己的应用程序自己调整它)。

我还将 EYE_AR_CONSEC_FRAMES 设置为 48 ,这意味着如果一个人连续闭眼 48 帧,我们将播放警报声。

您可以通过降低 EYE_AR_CONSEC_FRAMES 来使疲劳检测器更敏感——同样,您可以通过增加它来降低疲劳检测器的敏感度。

定义了 COUNTER,即眼睛纵横比低于 EYE_AR_THRESH 的连续帧的总数。

如果 COUNTER 超过 EYE_AR_CONSEC_FRAMES ,那么我们将更新布尔值 ALARM_ON。

plaintext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# start the video stream thread

print("[INFO] starting video stream thread...")

vs = VideoStream(src=args["webcam"]).start()

time.sleep(1.0)

# loop over frames from the video stream

while True:

    # grab the frame from the threaded video file stream, resize

    # it, and convert it to grayscale

    # channels)

    frame = vs.read()

    frame = imutils.resize(frame, width=450)

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # detect faces in the grayscale frame

    rects = detector(gray, 0)

实例化 VideoStream。

暂停一秒钟,让相机传感器预热。

开始遍历视频流中的帧。

读取下一帧,然后我们通过将其大小调整为 450 像素的宽度并将其转换为灰度进行预处理。

应用 dlib 的人脸检测器来查找和定位图像中的人脸。

下一步是应用面部标志检测来定位面部的每个重要区域:

plaintext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# loop over the face detections

for rect in rects:

    # determine the facial landmarks for the face region, then

    # convert the facial landmark (x, y)-coordinates to a NumPy

    # array

    shape = predictor(gray, rect)

    shape = face_utils.shape_to_np(shape)

    # extract the left and right eye coordinates, then use the

    # coordinates to compute the eye aspect ratio for both eyes

    leftEye = shape[lStart:lEnd]

    rightEye = shape[rStart:rEnd]

    leftEAR = eye_aspect_ratio(leftEye)

    rightEAR = eye_aspect_ratio(rightEye)

    # average the eye aspect ratio together for both eyes

    ear = (leftEAR + rightEAR) / 2.0

循环遍历检测到的每个人脸——在我们的实现中(特别与司机睡意有关),我们假设只有一张脸——司机——但我把这个 for 循环留在这里以防万一你想应用多张脸视频的技术。

对于每个检测到的人脸,我们应用 dlib 的面部标志检测器并将结果转换为 NumPy 数组。

使用 NumPy 数组切片,我们可以分别提取左眼和右眼的 (x, y) 坐标。

给定双眼的 (x, y) 坐标,我们然后计算它们的眼睛纵横比。

代码实现

plaintext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# check to see if the eye aspect ratio is below the blink

# threshold, and if so, increment the blink frame counter

if ear < EYE_AR_THRESH:

    COUNTER += 1

    # if the eyes were closed for a sufficient number of

    # then sound the alarm

    if COUNTER >= EYE_AR_CONSEC_FRAMES:

        # if the alarm is not on, turn it on

        if not ALARM_ON:

            ALARM_ON = True

            # check to see if an alarm file was supplied,

            # and if so, start a thread to have the alarm

            # sound played in the background

            if args["alarm"] != "":

                t = Thread(target=sound_alarm,

                    args=(args["alarm"],))

                t.deamon = True

                t.start()

        # draw an alarm on the frame

        frame=cv2ImgAddText(frame,"醒醒,别睡!",10,30,(255, 0, 0),30)

# otherwise, the eye aspect ratio is not below the blink

# threshold, so reset the counter and alarm

else:

    COUNTER = 0

    ALARM_ON = False

10.系统整合

下图源码&环境部署视频教程&自定义UI界面
1.png
参考博客《基于OpenCV的刷脸考勤&人脸校验&用户管理系统(源码&教程)》

11.参考文献

[1]刘淇缘,卢树华,兰凌强.遮挡人脸检测方法研究进展[J].计算机工程与应用.2020,(13).33-46.DOI:10.3778/j.issn.1002-8331.2003-0142.
[2]蒋纪威,何明祥,孙凯.基于改进YOLOv3的人脸实时检测方法[J].计算机应用与软件.2020,(5).200-204.DOI:10.3969/j.issn.1000-386x.2020.05.035.
[3]张文超,山世光,张洪明,等.基于局部Gabor变化直方图序列的人脸描述与识别[J].软件学报.2006,(12).2508-2517.
[4]王蕴红,朱勇,谭铁牛.基于虹膜识别的身份鉴别[J].自动化学报.2002,(1).1-10.
[5]梁路宏,艾海舟,徐光档,等.人脸检测研究综述[J].计算机学报.2002,(5).449-458.
[6]尹义龙,宁新宝,张晓梅.自动指纹识别技术的发展与应用[J].南京大学学报(自然科学版).2002,(1).29-35.
[7]孙冬梅,裘正定.生物特征识别技术综述[J].电子学报.2001,(z1).1744-1748.
[8]卢春雨,张长水,闻芳,等.基于区域特征的快速人脸检测法[J].清华大学学报(自然科学版).1999,(1).101-105.
[9]梁路宏,艾海舟,何克忠.基于多模板匹配的单人脸检测[J].中国图象图形学报.1999,(10).825-830.
[10]孙晓玲.人脸识别系统中眼睛定位方法的研究[D].2008
[11]山世光.人脸识别中若干关键问题的研究[D].2004
[12]刘伟强.基于级联卷积神经网络的人脸检测算法的研究[D].2017
[13]Li Liu,Wanli Ouyang,Xiaogang Wang,等.Deep Learning for Generic Object Detection: A Survey[J].International Journal of Computer Vision.2020,128(2).261-318.DOI:10.1007/s11263-019-01247-4.
[14]Lin, Tsung-Yi,Goyal, Priya,Girshick, Ross,等.Focal Loss for Dense Object Detection[J].IEEE Transactions on Pattern Analysis and Machine Intelligence.2020,42(2).318-327.DOI:10.1109/TPAMI.2018.2858826.
[15]Yang, Shuo,Luo, Ping,Loy, Chen Change,等.Faceness-Net: Face Detection through Deep Facial Part Responses.[J].IEEE Transactions on Pattern Analysis & Machine Intelligence.2018,40(8).1845-1859.
[16]Xiang,Zhang,Wei,Yang,Xiaolin,Tang,等.A Fast Learning Method for Accurate and Robust Lane Detection Using Two-Stage Feature Extraction with YOLO v3.[J].Sensors (Basel, Switzerland).2018,18(12).DOI:10.3390/s18124308.
[17]Kaipeng Zhang,Zhanpeng Zhang,Zhifeng Li,等.Joint Face Detection and Alignment Using Multitask Cascaded Convolutional Networks[J].IEEE signal processing letters.2016,(10).1499-1503.
[18]LeCun, Yann,Bengio, Yoshua,Hinton, Geoffrey.Deep learning[J].Nature.2015,521(May 28 TN.7553).436-444.DOI:10.1038/nature14539.
[19]Xuelong Li,Jing Pan,Yuan Yuan,等.Efficient HOG human detection[J].Signal Processing: The Official Publication of the European Association for Signal Processing.2011,91(4).
[20]Viola P,Jones MJ.Robust real-time face detection[J].International Journal of Computer Vision.2004,57(2).
[21]Giles C.L.,Lawrence S..Face recognition: a convolutional neural-network approach[J].IEEE Transactions on Neural Networks.1997,8(1).
[22]C. Lawrence Zitnick,Piotr Dollar.Edge Boxes: Locating Object Proposals from Edges[C].2014
[23]Sun, Yi,Wang, Xiaogang,Tang, Xiaoou.Deep Convolutional Network Cascade for Facial Point Detection[C].2013
[24]Zhou, Erjin,Fan, Haoqiang,Cao, Zhimin,等.Extensive Facial Landmark Localization with Coarse-to-Fine Convolutional Network Cascade[C].2013
[25]Neubeck, A.,Van Gool, L..Efficient Non-Maximum Suppression[C].2006
[26]T.F.Cootes,G.J.Edwards,C.J.Taylor.Active appearance models[C].1998
[27]Guanglu Song,Yu Liu,Ming Jiang,等.Beyond Trade-Off: Accelerate FCN-Based Face Detector with Higher Accuracy[C].
[28]Hao Wang,Yitong Wang,Zheng Zhou,等.CosFace: Large Margin Cosine Loss for Deep Face Recognition[C].
[29]Ranjan, R.,Patel, V.M.,Chellappa, R..A deep pyramid Deformable Part Model for face detection[C].
[30]Kaipeng Zhang,Zhanpeng Zhang,Zhifeng Li,等.Joint Face Detection and Alignment Using Multitask Cascaded Convolutional Networks[C].
[31]Weiyang Liu,Yandong Wen,Zhiding Yu,等.SphereFace: Deep Hypersphere Embedding for Face Recognition[C].
[32]Taigman, Y.,Ming Yang,Ranzato, M.,等.DeepFace: Closing the Gap to Human-Level Performance in Face Verification[C].
[33]Chenchen Zhu,Ran Tao,Khoa Luu,等.Seeing Small Faces from Robust Anchor’s Perspective[C].
[34]Jiangjing Lv,Xiaohu Shao,Junliang Xing,等.A Deep Regression Architecture with Two-Stage Re-initialization for High Performance Facial Landmark Detection[C].


如果您需要更详细的【源码和环境部署教程】,除了通过【系统整合】小节的链接获取之外,还可以通过邮箱以下途径获取:

1.请先在GitHub上为该项目点赞(Star),编辑一封邮件,附上点赞的截图、项目的中文描述概述(About)以及您的用途需求,发送到我们的邮箱

sharecode@yeah.net

2.我们收到邮件后会定期根据邮件的接收顺序将【完整源码和环境部署教程】发送到您的邮箱。

GitHub 6大热门实时人脸识别开源项目!哪个最适合初级开发者?_github上有哪些好的深度学习人脸表情识别图像分类项目-CSDN博客

mikel阅读(288)

来源: GitHub 6大热门实时人脸识别开源项目!哪个最适合初级开发者?_github上有哪些好的深度学习人脸表情识别图像分类项目-CSDN博客

实时人脸识别系统在计算机视觉领域仍然是一个非常热门的话题,许多公司已经开发了自己的解决方案来尝试进入不断增长的市场。 与传统的识别方法相比,实时人脸识别系统的优势在于在连续帧中使用同一个人的多个实例。

如果你希望利用实时人脸识别的优势,开源项目可能是一个很好的起点。 由于源代码已发布,你可以看到它是如何工作的,并确保它不会窃取你的数据。 在本文中,我们将帮助你挑选最佳开源人脸识别项目,并向你展示为什么选择开源软件通常是最佳选择。

为什么选择开源人脸识别项目?
开源软件有很多优点。 首先,使用开源代码,你可以确定数据的处理方式。 其次,开源项目通常质量更高。由于多个开发人员不断审查代码,因此可以非常快速地识别错误。 第三,许可费用较低,此类项目通常由内部开发或由可自由选择的 IT 服务提供商开发。

很难找到过时的开源软件,因为它通常遵循现代软件开发实践。 最后,开源被认为是代码成熟的下一个层次。 它允许开发人员在几分钟内流利地理解代码并激励他们进行工作。

最佳开源人脸识别软件
我们研究了实时开源人脸识别软件的 github 存储库,并准备了一份最佳选择列表:

1.Deepface

该库支持不同的人脸识别方法,如 FaceNet 和 InsightFace。它还提供了 REST API,但它只支持验证方法,因此你无法创建人脸集合并在其中查找人脸。尽管 Python 开发人员很容易上手,但其他人可能更难集成。截至 2021 年初的最新版本是 0.0.49。

2.CompreFace

这个解决方案是2020年7月才在github上发布的,看起来非常有前途。 CompreFace 成为我们最好的开源人脸识别项目名单,因为它是少数可以通过一个 docker-compose 命令启动的自托管 REST API 人脸识别解决方案之一。

REST API 允许你轻松地将其集成到你的系统中,而无需事先具备机器学习技能。此外,它是可扩展的,因此你可以同时识别多个视频流中的人脸。

CompreFace 有一个用于管理用户角色和面部集合的简单 UI。它提供了两种最流行的人脸识别方法之间的选择:FaceNet(LFW 准确率 99.65%)和 InsightFace(LFW 准确率 99.86%)。它仍处于活跃的开发阶段,截至 2021 年初的最新版本是 0.5 版本。

3.Face Recognition

这个解决方案的主要特点是它使用了他们的 Python API 和二进制命令行工具。 此外,他们的 github 上提供了所有主要平台的安装说明,甚至是用于快速设置的 docker 镜像。

尽管它很受欢迎,但该软件有一些缺点。上一次发布是在 2018 年,此后没有重大改进。它使用了一个相当过时的人脸识别模型,在 LFW 上的准确率只有 99.38%,并且没有 REST API。

4.InsightFace

InsightFace 是另一个开源 Python 库,它使用最新最准确的人脸识别方法之一进行人脸检测 (RetinaFace) 和人脸识别 (SubCenter-ArcFace)。 该解决方案的准确率非常高——在 LFW 数据集上为 99.86%。 唯一的缺点是它不易于使用。

5. FaceNet

FaceNet 是一个流行的开源 Python 库。 这种方法的准确率相当高——在 LFW 数据集上为 99.65%,这很好但不是最高的。 此解决方案的缺点是它没有 REST API,并且不再支持存储库(最后一次更新是在 2018 年 4 月)。

6.InsightFace-REST

这是 2019 年创建的另一个有前途的存储库,并于 2020 年 10 月开始积极开发。与 CompreFace 一样,这是一个基于 docker 的解决方案,提供方便的 REST API。最大的优势是它的开发人员将 InsightFace 的识别速度提高了三倍。

这个解决方案的缺点是它只提供人脸的嵌入,没有提供用于实际人脸识别的 API,所以你需要有自己的分类器。该存储库仍然没有许可证,因此你需要询问作者是否可以使用它。截至 2021 年初的最新版本是 v0.5.9.6。

结论
尽管当今 GitHub 上可用的最佳开源人脸识别项目在功能上各不相同,但它们都有可能让你的开发更轻松。

在选择开源人脸识别解决方案时,我们建议编制与你的业务相关的标准列表,并选择优先考虑你所做的相同事情的选项。虽然可能有些功能对你来说比其他功能更重要,但我们在此处确定的每个免费开源项目都将提供高质量的实时人脸识别体验。
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/TsingSee/article/details/120533615

省钱的开源项目「GitHub 热点速览」 - 削微寒 - 博客园

mikel阅读(212)

来源: 省钱的开源项目「GitHub 热点速览」 – 削微寒 – 博客园

本期,我从上周的热门开源项目中挑选了 5 个既省钱又省事,还好玩的开源项目。

首先,推荐的是省钱的电动汽车智能充电管理平台 evcc,它可以根据分时电价智能安排电动车充电时间,从而降低电费,如果你家还有太阳能充电和储能设备,evcc 更能最大限度地利用电能,让你的充电成本降到最低。说到省事,开源的 PaaS 平台 dokku,它可以让你轻松搭建一个类似 Heroku 的平台,又能帮你省下一笔可观的费用。再来看看在线 AI 证件照制作工具 HivisionIDPhotos,这款工具让你无需再花钱拍摄证件“大头照”,随时在线生成专业证件照,方便又实惠。

除此之外,还有两款特别好玩的开源项目。《暗黑破坏神》网页版 diabloweb,让你无需安装游戏就能在浏览器里重温经典;以及 SQLpage,通过 SQL 命令就能创建简单的网页,让你无需编写前端代码,同样省时省力。

  • 本文目录
    • 1. 开源热搜项目
      • 1.1 电动汽车智能充电管理平台:evcc
      • 1.2 基于 Docker 的开源 PaaS 平台:dokku
      • 1.3 一条 SQL 生成网页的工具:SQLpage
      • 1.4 在浏览器里玩《暗黑破坏神》:diabloweb
      • 1.5 轻量级的 AI 证件照制作工具:HivisionIDPhotos
    • 2. HelloGitHub 热评
      • 2.1 强大的终端日志文件查看工具:lnav
      • 2.2 游戏修改器管理工具:Game-Cheats-Manager
    • 3. 结尾

1. 开源热搜项目

1.1 电动汽车智能充电管理平台:evcc

主语言:GoStar:3.1k周增长:200

这是一个开源的 EV(电动汽车)充电器控制平台,为电动汽车车主提供灵活且易于安装的充电解决方案。它提供了可视化且适配移动端的 Web 平台,用户可以通过该平台远程启动、停止和监控车辆的充电状态。智能充电功能还可以根据电价、太阳储能和日程安排,智能安排充电时间,从而节约电费。平台支持多种充电设备和车辆型号,为家庭充电桩提供更加智能的控制。

GitHub 地址→github.com/evcc-io/evcc

1.2 基于 Docker 的开源 PaaS 平台:dokku

主语言:GoStar:28k周增长:1600

该项目是一款开源的 PaaS(平台即服务)平台,利用 Docker 容器进行应用程序的部署和运行。它提供了类似 Heroku 的命令行工具,让部署和管理应用程序的变得更加方便,支持从 Git 仓库自动部署应用、同时管理多个应用以及丰富的插件系统,可作为 Heroku 的开源替代品。

GitHub 地址→github.com/dokku/dokku

1.3 一条 SQL 生成网页的工具:SQLpage

主语言:RustStar:1.4k周增长:100

该项目是用 Rust 编写的基于 SQL 的 Web 应用构建工具。用户只需编写 SQL,就能自动生成可交互的 Web 界面,无需使用其他编程语言,让数据科学家和分析师能够方便地展示 SQL 的查询结果,是一种快速、简单的数据可视化方案,支持多种主流数据库。

GitHub 地址→github.com/lovasoa/SQLpage

1.4 在浏览器里玩《暗黑破坏神》:diabloweb

主语言:JavaScriptStar:2.6k周增长:300

该项目是将经典的动作角色扮演游戏《Diablo 1》(暗黑破坏神)移植到浏览器的开源项目。它通过 WebAssembly 技术,让用户无需安装即可以在浏览器重温这款经典游戏。

GitHub 地址→github.com/d07RiV/diabloweb

1.5 轻量级的 AI 证件照制作工具:HivisionIDPhotos

主语言:PythonStar:1.9k周增长:1.5k

这是一款简单易用的 AI 证件照制作工具,能够生成标准证件照和六寸排版照。它提供了简洁的 Web 界面和 API 服务,即使在没有 GPU 的电脑上也能够运行,支持抠图、尺寸调整和自定义底色等功能。

GitHub 地址→github.com/Zeyi-Lin/HivisionIDPhotos

2. HelloGitHub 热评

在本章节中,我们将为大家介绍本周 HelloGitHub 网站上的热门开源项目。同时,期待您与我们分享使用这些开源项目的心得与体验。

2.1 强大的终端日志文件查看工具:lnav

主语言:C++

这是一款用于查看和分析日志文件的轻量级工具。它无需配置、开箱即用,可自动识别日志格式并解压文件,支持同时处理多个文件和目录、实时更新、文本高亮、正则与 SQL 过滤日志等功能,特别适合在服务器和开发环境中使用。

项目详情→hellogithub.com/repository/f771d96afed44371b9c805d3cc8954c6

2.2 游戏修改器管理工具:Game-Cheats-Manager

主语言:Python

这是一款强大的游戏修改器管理工具,支持搜索、下载、启动、导入和更新游戏修改器等功能。

项目详情→hellogithub.com/repository/3ca6e8e23401477282ba72d2d8932311

3. 结尾

以上就是本期「GitHub 热点速览」的全部内容,希望你能够在这里找到自己感兴趣的开源项目,如果你有其他好玩、有趣的 GitHub 开源项目想要分享,欢迎来 HelloGitHub 与我们交流和讨论。