python --face_recognition(人脸识别,检测,特征提取,绘制鼻子,眼睛,嘴巴,眉毛)/活体检测

news2025/4/21 19:45:50

dlib 安装方法 之前博文 https://blog.csdn.net/weixin_44634704/article/details/141332644

环境:

python==3.8
opencv-python==4.11.0.86
face_recognition==1.3.0
dlib==19.24.6

人脸检测

import cv2
import face_recognition

# 读取人脸图片
img = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
face_List = face_recognition.face_locations(img) # 检测人脸,返回人脸坐标信息
print(face_List)

for x in face_List: # 画框
    cv2.rectangle(img, (x[3], x[0]), (x[1], x[2]), (0, 255, 0), 2)
cv2.imshow("a", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 输出: [(116, 306, 223, 199)]

在这里插入图片描述

人脸分割(切割)

import cv2
import face_recognition

# 读取人脸图片
img = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
face_List = face_recognition.face_locations(img) # 检测人脸,返回人脸坐标信息
print(face_List)

for x in face_List: # 画框
    cv2.rectangle(img, (x[3], x[0]), (x[1], x[2]), (0, 255, 0), 2)
    qie_img = img[x[0]:x[2], x[3]:x[1]]
    
cv2.imshow("a", qie_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

提取人脸特征向量

img = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
# 提取人脸特征向量
face01 = face_recognition.face_encodings(img)[0]
print(face01)

人脸比对(欧式距离)

import cv2
import face_recognition
import numpy as np

# 读取人脸图片
img = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # face_recognition库,处理是RGB格式, CV默认为BGR
# 提取人脸特征向量
face01 = face_recognition.face_encodings(img)[0]
# 读取人脸原图的图片
img2 = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
face02 = face_recognition.face_encodings(img2)[0]
#
# 计算欧几里得距离
v = np.linalg.norm(face01 - face02)
if v < 0.8:
    print("是一个人")
else:
    print("不是一个人")

转为置信度

import cv2
import face_recognition
import numpy as np

def euclidean_distance_to_confidence(distance, max_distance):
    # 确保距离在合理范围内
    distance = min(distance, max_distance)
    # 计算置信度
    confidence = 1 - (distance / max_distance)
    return confidence

# 读取人脸图片
img = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # face_recognition库,处理是RGB格式, CV默认为BGR
# 提取人脸特征向量
face01 = face_recognition.face_encodings(img)[0]
# 读取人脸原图的图片
img2 = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
face02 = face_recognition.face_encodings(img2)[0]
#
# 计算欧几里得距离
v = np.linalg.norm(face01 - face02)
w = euclidean_distance_to_confidence(v, 1) # 置信度最大阈值为1
print(w) # 计算置信度,距离越小,置信度越高。

人脸比对(余弦)

import cv2
import face_recognition
import numpy as np


def cosine_similarity_to_confidence(similarity):
    # 将余弦相似度从 [-1, 1] 映射到 [0, 1]
    confidence = (similarity + 1) / 2
    return confidence


# 读取人脸图片
img = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # face_recognition库,处理是RGB格式, CV默认为BGR
# 提取人脸特征向量
face01 = face_recognition.face_encodings(img)[0]
# 读取人脸原图的图片
img2 = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
face02 = face_recognition.face_encodings(img2)[0]
#
dot_product = np.dot(face01, face02)
norm_face01 = np.linalg.norm(face01)
norm_face02 = np.linalg.norm(face02)
similarity = dot_product / (norm_face01 * norm_face02)
print("余弦相似度:", similarity)
confidence = cosine_similarity_to_confidence(similarity)
print("置信度:", confidence)

绘制眼睛,嘴巴,鼻子,轮廓线条

import cv2
import face_recognition
import numpy as np




# 读取人脸图片
img = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # face_recognition库,处理是RGB格式, CV默认为BGR

#img = face_recognition.load_image_file("face.jpg")
face_landmarks = face_recognition.face_landmarks(img)

# 把特征点都画出来
for landmarks in face_landmarks:
    print(landmarks)
    # 画眼睛
    for eye in ('left_eye', 'right_eye'):
        pts = np.array(landmarks[eye], np.int32)
        cv2.polylines(img, (pts,), True, (0, 255, 0), 2)
    # 画嘴巴
    mouth_pts = np.array(landmarks['top_lip'], np.int32)
    cv2.polylines(img, (mouth_pts,), True, (0, 0, 255), 2)
    # 画鼻子
    nose_pts = np.array(landmarks['nose_bridge'], np.int32)
    cv2.polylines(img, (nose_pts,), True, (255, 0, 0), 2)

    # 绘制脸部轮廓
    chin_pts = np.array(landmarks['chin'], np.int32)
    cv2.polylines(img, [chin_pts], False, (255, 255, 0), 2)

cv2.imwrite("landmarks.jpg", img[:, :, ::-1])

在这里插入图片描述

face_recognition 库检测出的人脸特征点中,默认是不包含耳朵特征点的。这是因为在很多常见的人脸识别应用场景里,耳朵的特征稳定性和独特性相对较弱,所以库没有专门对耳朵的特征点进行检测。
不过,要是你想要标记耳朵位置,可以考虑使用更高级的人脸关键点检测模型,像 dlib 库提供的 68 点或者 81 点人脸关键点检测器,其中 81 点模型包含了耳朵相关的关键点。

import cv2
import dlib
import numpy as np

# 加载 dlib 的人脸检测器和 81 点关键点预测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_81_face_landmarks.dat")

# 读取图片
image = cv2.imread(r"C:\Users\123\Desktop\1.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 检测人脸
faces = detector(gray)

for face in faces:
    # 检测关键点
    landmarks = predictor(gray, face)

    # 绘制眼睛
    left_eye_points = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(36, 42)]
    right_eye_points = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(42, 48)]
    for eye_points in [left_eye_points, right_eye_points]:
        pts = np.array(eye_points, np.int32)
        cv2.polylines(image, [pts], True, (0, 255, 0), 2)

    # 绘制嘴巴
    mouth_points = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(48, 60)]
    pts = np.array(mouth_points, np.int32)
    cv2.polylines(image, [pts], True, (0, 0, 255), 2)

    # 绘制鼻子
    nose_points = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(27, 36)]
    pts = np.array(nose_points, np.int32)
    cv2.polylines(image, [pts], True, (255, 0, 0), 2)

    # 绘制脸部轮廓
    chin_points = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(0, 17)]
    pts = np.array(chin_points, np.int32)
    cv2.polylines(image, [pts], False, (255, 255, 0), 2)

    # 绘制耳朵
    left_ear_points = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(71, 75)]
    right_ear_points = [(landmarks.part(n).x, landmarks.part(n).y) for n in range(75, 79)]
    for ear_points in [left_ear_points, right_ear_points]:
        pts = np.array(ear_points, np.int32)
        cv2.polylines(image, [pts], False, (0, 255, 255), 2)

# 保存图片
cv2.imwrite("landmarks.jpg", image)

实时取摄像头绘制

import numpy as np
import cv2
import face_recognition

# 打开摄像头
video_capture = cv2.VideoCapture(0)

while True:
    # 读取一帧视频
    ret, frame = video_capture.read()

    # 将图像从BGR颜色空间转换为RGB颜色空间,因为face_recognition库使用RGB格式
    rgb_frame = frame[:, :, ::-1]

    # 检测人脸特征点
    face_landmarks_list = face_recognition.face_landmarks(rgb_frame)

    # for face_landmarks in face_landmarks_list:
    #     # 打印所有特征点类型及其对应的关键点坐标
    #     for facial_feature in face_landmarks.keys():
    #         print(f"{facial_feature}: {face_landmarks[facial_feature]}")

    for face_landmarks in face_landmarks_list:
        # 绘制脸部轮廓
        chin_points = face_landmarks['chin']
        pts = [tuple(point) for point in chin_points]
        pts = np.array(pts, np.int32)
        cv2.polylines(frame, [pts], False, (255, 255, 0), 2)

        # 绘制眼睛
        for eye in ('left_eye', 'right_eye'):
            eye_points = face_landmarks[eye]
            pts = [tuple(point) for point in eye_points]
            pts = np.array(pts, np.int32)
            cv2.polylines(frame, [pts], True, (0, 255, 0), 2)

        # 绘制左右眉毛
        for eyebrow in ('left_eyebrow', 'right_eyebrow'):
            eyebrow_points = face_landmarks[eyebrow]
            eyebrow_pts = np.array(eyebrow_points, np.int32)
            cv2.polylines(frame, [eyebrow_pts], False, (255, 0, 255), 2)

        # 上嘴唇
        mouth_pts = np.array(face_landmarks['top_lip'], np.int32)
        cv2.polylines(frame, (mouth_pts,), True, (0, 0, 255), 2)

        # 下嘴唇
        bottom_lip_points = face_landmarks['bottom_lip']
        bottom_lip_pts = np.array(bottom_lip_points, np.int32)
        cv2.polylines(frame, [bottom_lip_pts], True, (0, 0, 255), 2)

        # 绘制鼻子代表鼻梁部分的关键点
        nose_bridge_points = face_landmarks['nose_bridge']
        pts = [tuple(point) for point in nose_bridge_points]
        pts = np.array(pts, np.int32)
        cv2.polylines(frame, [pts], True, (255, 0, 0), 2)

        # 绘制鼻尖
        nose_tip_points = face_landmarks['nose_tip']
        nose_tip_pts = np.array(nose_tip_points, np.int32)
        cv2.polylines(frame, [nose_tip_pts], True, (0, 255, 255), 2)

    # 显示结果图像
    cv2.imshow('Video', frame)

    # 按 'q' 键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放摄像头并关闭所有窗口
video_capture.release()
cv2.destroyAllWindows()

活体检测

import cv2
import face_recognition
import numpy as np

# 计算眼睛的纵横比
def eye_aspect_ratio(eye):
    A = np.linalg.norm(np.array(eye[1]) - np.array(eye[5]))
    B = np.linalg.norm(np.array(eye[2]) - np.array(eye[4]))
    C = np.linalg.norm(np.array(eye[0]) - np.array(eye[3]))
    ear = (A + B) / (2.0 * C)
    return ear

# 计算嘴巴的纵横比
def mouth_aspect_ratio(mouth):
    # 重新选择特征点
    top_mid = (np.array(mouth[2]) + np.array(mouth[3])) // 2
    bottom_mid = (np.array(mouth[10]) + np.array(mouth[11])) // 2
    left = np.array(mouth[0])
    right = np.array(mouth[6])
    A = np.linalg.norm(top_mid - bottom_mid)
    C = np.linalg.norm(left - right)
    mar = A / C
    return mar

# 初始化变量
EYE_AR_THRESH = 0.2  # 眼睛纵横比阈值
EYE_AR_CONSEC_FRAMES = 3  # 连续闭眼帧数阈值
COUNTER_EYE = 0  # 连续闭眼帧数计数器
TOTAL_EYE = 0  # 眨眼次数计数器

MOUTH_AR_CONSEC_FRAMES = 3  # 连续张嘴帧数阈值
COUNTER_MOUTH = 0  # 连续张嘴帧数计数器
TOTAL_MOUTH = 0  # 张嘴次数计数器

PREVIOUS_LANDMARKS = None  # 上一帧的人脸特征点
HEAD_MOTION_THRESH = 10  # 头部运动阈值
HEAD_MOTION = False  # 头部是否移动标志

# 动态阈值相关变量
INITIAL_FRAMES = 10  # 用于确定初始阈值的帧数
initial_mar_values = []
MOUTH_AR_THRESH = None

# 打开摄像头
video_capture = cv2.VideoCapture(0)

frame_count = 0
while True:
    # 读取一帧视频
    ret, frame = video_capture.read()

    # 将图像从 BGR 颜色空间转换为 RGB 颜色空间
    rgb_frame = frame[:, :, ::-1]

    # 检测人脸特征点
    face_landmarks_list = face_recognition.face_landmarks(rgb_frame)

    for face_landmarks in face_landmarks_list:
        # 提取左右眼睛的特征点
        left_eye = face_landmarks['left_eye']
        right_eye = face_landmarks['right_eye']

        # 计算左右眼睛的纵横比
        left_ear = eye_aspect_ratio(left_eye)
        right_ear = eye_aspect_ratio(right_eye)

        # 计算平均纵横比
        ear = (left_ear + right_ear) / 2.0

        # 检测眨眼
        if ear < EYE_AR_THRESH:
            COUNTER_EYE += 1
        else:
            if COUNTER_EYE >= EYE_AR_CONSEC_FRAMES:
                TOTAL_EYE += 1
            COUNTER_EYE = 0

        # 提取嘴巴的特征点
        mouth = face_landmarks['top_lip'] + face_landmarks['bottom_lip']

        # 计算嘴巴的纵横比
        mar = mouth_aspect_ratio(mouth)
        print(f"嘴巴纵横比: {mar}")  # 打印嘴巴纵横比,用于调试

        # 动态确定嘴巴纵横比阈值
        if frame_count < INITIAL_FRAMES:
            initial_mar_values.append(mar)
            if frame_count == INITIAL_FRAMES - 1:
                MOUTH_AR_THRESH = np.mean(initial_mar_values) * 1.2  # 阈值设为初始平均值的 1.2 倍
        else:
            # 检测张嘴
            if mar > MOUTH_AR_THRESH:
                COUNTER_MOUTH += 1
            else:
                if COUNTER_MOUTH >= MOUTH_AR_CONSEC_FRAMES:
                    TOTAL_MOUTH += 1
                COUNTER_MOUTH = 0

        # 检测头部运动
        if PREVIOUS_LANDMARKS is not None:
            current_landmarks = []
            for feature in face_landmarks.values():
                current_landmarks.extend(feature)
            current_landmarks = np.array(current_landmarks)
            previous_landmarks = []
            for feature in PREVIOUS_LANDMARKS.values():
                previous_landmarks.extend(feature)
            previous_landmarks = np.array(previous_landmarks)
            displacement = np.linalg.norm(current_landmarks - previous_landmarks)
            if displacement > HEAD_MOTION_THRESH:
                HEAD_MOTION = True
            else:
                HEAD_MOTION = False

        PREVIOUS_LANDMARKS = face_landmarks

        # 在图像上显示眨眼次数、张嘴次数和头部是否移动
        cv2.putText(frame, f"Blinks: {TOTAL_EYE}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        cv2.putText(frame, f"Opens: {TOTAL_MOUTH}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        cv2.putText(frame, f"Head Motion: {'Yes' if HEAD_MOTION else 'No'}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

    # 显示结果图像
    cv2.imshow('Video', frame)
    frame_count += 1

    # 按 'q' 键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放摄像头并关闭所有窗口
video_capture.release()
cv2.destroyAllWindows()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2321821.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

redis解决缓存穿透/击穿/雪崩

文章目录 1.缓存穿透1.1 概念1.2 解决方案1.2.1 缓存空对象1.2.2 布隆过滤 1.2 店铺查询使用缓存穿透解决方案1.2.1 流程 2.缓存雪崩2.1 什么是缓存雪崩&#xff1f;2.2 雪崩解决方案 3.缓存击穿3.1 什么是缓存击穿&#xff1f;3.2解决方案3.2.1 基于互斥锁解决缓存击穿问题&am…

《TCP/IP网络编程》学习笔记 | Chapter 22:重叠 I/O 模型

《TCP/IP网络编程》学习笔记 | Chapter 22&#xff1a;重叠 I/O 模型 《TCP/IP网络编程》学习笔记 | Chapter 22&#xff1a;重叠 I/O 模型理解重叠 I/O 模型重叠 I/O本章讨论的重叠 I/O 的重点不在于 I/O 创建重叠 I/O 套接字执行重叠 I/O 的 WSASend 函数进行重叠 I/O 的 WSA…

python每日十题(10)

在Python语言中&#xff0c;源文件的扩展名&#xff08;后缀名&#xff09;一般使用.py。 保留字&#xff0c;也称关键字&#xff0c;是指被编程语言内部定义并保留使用的标识符。Python 3.x有35个关键字&#xff0c;分别为&#xff1a;and&#xff0c;as&#xff0c;assert&am…

LabVIEW液压振动锤控制系统

在现代工程机械领域&#xff0c;液压振动锤的高效与精准控制日益显得重要。本文通过LabVIEW软件&#xff0c;展开液压振动锤启停共振控制技术的研究与应用&#xff0c;探讨如何通过改进控制系统来优化液压振动锤的工作性能&#xff0c;确保其在复杂工况下的稳定性与效率。 ​ …

简单介绍My—Batis

1.什么是My—Batis&#xff1f; My—Batis是一个持久层框架&#xff0c;提供了sql映射功能&#xff0c;能方便的将数据库表和java对象进行映射&#xff0c;通过My—Batis可以将项目中的数据存储在数据库中&#xff0c;以便我们进行调用。值得注意的是My—Batis和spring不是一回…

ALTER TABLE SHRINK SPACE及MOVE的区别与适用场景

以下是 ‌Oracle 数据库‌中三个收缩表空间命令的对比&#xff1a; 1. ALTER TABLE table_name SHRINK SPACE;‌ ‌作用‌&#xff1a;直接重组表数据并移动高水位线&#xff08;HWM&#xff09;&#xff0c;释放未使用的空间到表空间‌。 影响‌&#xff1a; 会锁表&#…

docker远程debug

1. 修改 Java 启动命令 在 Docker 容器中启动 Java 程序时&#xff0c;需要添加 JVM 调试参数&#xff0c;jdk8以上版本 java -agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005 -jar your-app.jar jdk8及以下版本&#xff1a; java -Xdebug -Xrunjdwp:tra…

rosbag|ROS中.bag数据包转换为matlab中.mat数据类型

代码见代码 msg_dict中设置自定义消息类型 test_config中设置需要记录的具体的值 test_config中topic_name以及message_type照搬plotjuggler打开时的参数 最后生成.mat文件在matlab中进行使用

pytest-xdist 进行高效并行自动化测试

pytest-xdist 的核心功能是通过多进程分发测试任务&#xff0c;每个进程独立运行测试&#xff0c;确保测试隔离。2025 年 3 月 25 日&#xff0c;pytest-xdist 在 GitHub 上已有超过 1,200,000 次下载&#xff0c;表明其在测试社区中的广泛接受。 在自动化测试中&#xff0c;随…

位置编码再思考

最近在做多模态&#xff0c;发现基于 transformer 的多模态&#xff0c;position embedding 是一个非常重要的内容&#xff0c;而且还没有统一方案&#xff0c;先暂做记录&#xff0c;几篇还不错的博客&#xff1a; Transformer学习笔记一&#xff1a;Positional Encoding&…

Deepseek API+Python 测试用例一键生成与导出 V1.0.3

** 功能详解** 随着软件测试复杂度的不断提升,测试工程师需要更高效的方法来设计高覆盖率的测试用例。Deepseek API+Python 测试用例生成工具在 V1.0.3 版本中,新增了多个功能点,优化了提示词模板,并增强了对文档和接口测试用例的支持,极大提升了测试用例设计的智能化和易…

[c语言日寄MAX]深度解析:大小端字节序

【作者主页】siy2333 【专栏介绍】⌈c语言日寄MAX⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还…

Android ADB工具使用教程(从安装到使用)

目录 ADB工具介绍 什么是ADB&#xff1f; 组成 主要功能 ADB工具安装与连接设备 WIFI连接&#xff0c;提示计算机积极拒绝10061 WIFI成功连接后&#xff0c;拔掉数据线显示offline 提示adb版本不一致​编辑 ADB工具使用 ★日志操作命令 adb logcat:抓取日志 日志格式…

基于SSM框架的线上甜品销售系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0c;所以对于信息的宣传和管理就很关键。因此网上销售信息的…

Redis原理:Monitor 实现

在调用 Redis 的 MONITOR 命令后&#xff0c;可以在对应的客户端上实时查看服务器的执行情况。今天&#xff0c;我们将从源码的角度来深入探讨 MONITOR 机制是如何处理这些请求以及如何将数据反馈给用户的。 MONITOR 命令的实现 Redis 中所有命令的具体实现细节都可以在其源代…

计算机工具基础(七)——Git

Git 本系列博客为《Missing in CS Class(2020)》课程笔记 Git是一种分布式版本控制系统&#xff0c;被其跟踪的文件可被查询精细到行的修改记录、回退版本、建立分支等 模型 一般流程&#xff1a;工作区 → \to →暂存区 → \to →仓库(本地 → \to →远端) 工作区&#xff1…

23种设计模式-创建型模式-工厂方法

文章目录 简介场景问题1. 直接依赖具体实现2. 违反开闭原则3. 条件分支泛滥4. 代码重复风险 解决根本问题完整类图完整代码说明核心优势代码优化静态配置表动态策略 总结 简介 工厂方法是一种创建型设计模式&#xff0c;它提供了在父类中创建对象的接口&#xff0c;但允许子类…

142. 环形链表 II——考察数学,难!

142. 环形链表 IIhttps://leetcode.cn/problems/linked-list-cycle-ii/ 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,…

从零开始:使用Luatools工具高效烧录Air780EPM核心板项目的完整指南

本文将深入讲解如何使用Luatools工具烧录一个具体的项目到Air780EPM开发板中。如何使用官方推荐的Luatools工具&#xff08;一款跨平台、命令行驱动的烧录利器&#xff09;&#xff0c;通过“环境配置→硬件连接→参数设置→一键烧录”四大步骤&#xff0c;帮助用户实现Air780E…

一套云HIS系统源码,系统融合HIS与EMR,基于云端部署,采用B/S架构与SaaS模式

云HIS系统完全基于云端部署&#xff0c;采用B/S架构&#xff0c;并通过软件即服务&#xff08;SaaS&#xff09;的形式面向二级及以下医院可快速交付、便捷运维、云化的医院核心业务平台产品。融合医院HIS和EMR两大主营系统&#xff0c;构建涵盖患者、费用、医嘱、电子病历等核…