前言
okey, 差不多,再写一篇博文,那么五月份应该也开端发布了四篇文章了。那么今天的话,带来的也是一个深度学习项目。有重视我的朋友因该知道,其实从前的话,我就有再不断得去介绍相似的项目。或者说是把这个项目的一些技术细节分模块给说了出来。
那么今天的话也是把一个bate版别给敞开一下了。关于详细的算法方面的完结和基本原理的话,看我从前的文章都是看得到的,现在咱们更像是把这个系列进行整合了。串起来了,作为了一个系列。当然依照我的习惯是我不喜欢拆来的,可是没办法东西确实多,兼并在一起,文章太长,而且也不好写,一起对我来说也不好看。
那么废话不多说,看看这个bate版别有啥吧。
首要: 智能安防体系是一种运用先进的技术手段来进步安全性和便当性的体系,它能够让运用者愈加方便、快捷、精确地操控和监控其所在环境。智能安防体系通常包含视频监控体系、报警体系、智能门禁体系等,经过这些不同的设备和技术手段,能够完结对区域内的人员、车辆和物品的实时监控、辨认和办理,然后保障用户的生命财产安全。 智能安防体系的开发与实战需要涉及多个方面的知识和技术,包含硬件规划、软件开发、数据库办理、网络通信等等。在开发进程中,需要对体系的需求进行详细剖析和规划,选择合适的设备和技术手段,并进行体系的完结、测验和调试,确保体系的安稳性和可靠性。 在实际使用中,智能安防体系现已被广泛使用于商业建筑、住宅区、公共场所等,为用户供给了全面的安全保障和智能化的便当。例如,经过视频监控体系能够完结对区域内的人员、车辆和物品的实时监控和记载,报警体系能够在发现反常情况时及时向运用者发出警报提示,智能门禁体系能够完结对进出人员和车辆的自动辨认和操控等等。这些功用的完结不仅为用户供给了全面的安全保障,一起也进步了用户的日子和工作效率,为用户带来了愈加智能化、快捷化的运用体验。
首要是咱们的这个首页:
进去之后是这样的:
当然最重要的是这个: 对以及录入人员的一个信息核算。
算法完结
首要,清晰一点,咱们从前所作的功课,那便是原来,咱们的这算法部分是在从前就现已说明了的: 具备人脸辨认功用的多方针在线实时行为检测(yolov5+deepsort+slowfast)
整个项目结构你都能够看到: 和咱们从前泄漏的其实十分像。 只是现在,咱们加入了flask服务端,当然还有对咱们的算法进行修改供给,对应服务的功用。
人脸辨认
在咱们的算法傍边,人脸辨认的部分仍是老样子。 在这儿主要是经过dlib完结,不过这段代码从前给过,就不复述了。 可是,为了能够符合详细的功用,咱们在这个基础代码的基础上,进行了一个封装。这样一来就能够完结到人脸辨认的功用,而且整合到咱们的Flask服务傍边去。
class ProcessAlg(object):
face_name_id_cache = {}
def set_cache(self,face_name_id_cache):
self.face_name_id_cache = face_name_id_cache
def updateFace(self,stream,faceid):
"""
更新人脸信息
:param video:
:param faceid:
:return:
"""
frame_array = np.frombuffer(stream.getvalue(), dtype=np.uint8)
cap = cv2.VideoCapture(frame_array)
result = FaceImg.query.filter(FaceImg.face_id == faceid).all()
if(len(result)==0):
raise Exception("no such face!!!")
# 获取视频帧数
num_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 核算需要保存的帧数
sample_rate = max(num_frames // 50, 1)
images = []
for i in range(num_frames):
ret, frame = cap.read()
if not ret:
break
if i % sample_rate == 0:
images.append(frame)
# 释放资源
cap.release()
#处理人脸信息
col = Collection()
face = result[0]
col.collection_images(images,face.imgs_path, None, None)
#更新人脸信息
build = BuildFace()
def up_model_data(face_id,face_name,feature_vector):
now = datetime.now()
session = SessionFactory()
record = FaceData.query.filter(FaceData.face_id == face_id).first()
record.update_time = now
record.feature_vector=feature_vector
session.commit()
build.building_select([int(face.face_id)],[int(face.face_id)],up_model_data,None)
def creatFace(self,stream,face_name):
"""
stream = io.BytesIO(file.read())
创立人脸
注意,这些信息,咱们在数据库里边有备份
一起在csv文件傍边都是有备份的
:param video:
:param face_name:
:return:
"""
frame_array = np.frombuffer(stream.getvalue(), dtype=np.uint8)
cap = cv2.VideoCapture(frame_array)
# 获取视频帧数
num_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 核算需要保存的帧数
sample_rate = max(num_frames // 50, 1)
images = []
for i in range(num_frames):
ret, frame = cap.read()
if not ret:
break
if i % sample_rate == 0:
images.append(frame)
# 释放资源
cap.release()
#处理人脸信息
col = Collection()
def process(face_name,file_path,face_id):
face_img = FaceImg(face_name=face_name, create_time=datetime.now(),
imgs_path=file_path,face_id=face_id)
session = SessionFactory()
session.add(face_img)
session.commit()
#此刻col将完结人脸图画的收集,一起完结收集之后直线process函数内的方法
col.collection_images(images,None,process,face_name)
#此刻数据库傍边现已有对于的人的姓名了,可是还不行,咱们还需要在faceName.txt傍边记载
faceNameTxt = FACE_FILE.faceName_path
with open(faceNameTxt, 'a+') as f:
f.write('{}\n'.format(face_name))
#开端构建人脸了
session = SessionFactory()
result = session.query(FaceImg).filter_by(face_name=face_name).all()
face = result[0]
build = BuildFace()
def save_model_data(face_id,face_name,feature_vector):
now = datetime.now()
data = FaceData(
face_id=face_id, face_name=face_name, feature_vector=feature_vector,
create_time=now, update_time=now
)
session = SessionFactory()
session.add(data)
session.commit()
build.building_select([int(face.face_id)],[int(face.face_id)],save_model_data,face_name)
def saveVideo(self,image_list,start_time,end_time,cream_id):
"""
:param image_list: cv2.imread()方针列表
:return:
"""
current_time = datetime.datetime.now()
year = current_time.year
month = current_time.month
day = current_time.day
image_uuid = str(uuid.uuid4())
save_dir = os.path.join('Resources', 'video', str(year), str(month), str(day))
save_path = os.path.join(save_dir, f'{image_uuid}.mp4')
# 假如保存途径不存在,就创立它
if not os.path.exists(save_dir):
os.makedirs(save_dir)
# 获取第一张图片的巨细
height, width, channels = image_list[0].shape
# 界说VideoWriter方针
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(save_path, fourcc, 20.0, (width, height))
# 写入每一帧图画
for image in image_list:
out.write(image)
# 释放资源
out.release()
session = SessionFactory()
# 创立一条新的数据
new_video = Videos(
start_time=start_time,
end_time=end_time,
in_day=start_time.date(),
save_path=save_path,
cream_id=cream_id
)
session.add(new_video)
session.commit()
session.close()
def __save_unimg(self,img,id,time_im,cream_id,action_name):
current_time = datetime.datetime.now()
year = current_time.year
month = current_time.month
day = current_time.day
image_uuid = str(uuid.uuid4())
save_dir = os.path.join('Resource', 'img', str(year), str(month), str(day))
save_path = os.path.join(save_dir, f'{image_uuid}.jpg')
# 假如保存途径不存在,就创立它
if not os.path.exists(save_dir):
os.makedirs(save_dir)
# 保存图片
cv2.imwrite(save_path, img)
face_unusual = FaceUnusual()
face_unusual.active_time = time_im
face_unusual.face_id = id
face_unusual.unusual_img = save_path
face_unusual.cream_id = cream_id
face_unusual.action_name = action_name
session = SessionFactory()
# 将FaceUnusual实例增加到会话中并提交更改
session.add(face_unusual)
session.commit()
session.close()
def unusualAction(self,im, ava_label, box, time_im,detectFace:DetectFace,cream_id):
bad_actions = {"fall down":"跌倒","jump/leap":"跳跃","lie/sleep":"躺下","run/jog":"奔跑"}
# 传入图片,传入动作标签,还有辨认的区域,产生时刻,人类辨认器
if(ava_label in bad_actions):
names = detectFace.detect_from_image(im)
if(len(names)):
for name in names:
t_id = self.face_name_id_cache.get(name,-1)
if(t_id==-1):
session = SessionFactory()
#更新一下cache
query_result = session.query(FaceImg).filter_by(face_name=name).first()
if query_result:
face_id = query_result.face_id
self.face_name_id_cache[name] = face_id
#然后再测验更新,假如仍是不可,说明便是陌生人
t_id = self.face_name_id_cache.get(name, -1)
self.__save_unimg(im,t_id,time_im,cream_id,bad_actions.get(ava_label,None))
这个东西类基本上完结了咱们的,这个人脸录入,人脸信息更新的功用。一起对接到咱们的数据库。
数据库规划
没有办法,咱们需要对一些数据进行保存,所以咱们规划了几个简略的表,用来存储。
class BehaviorLevel(Base):
__tablename__ = 'behavior_levels'
level_id = Column(INTEGER(11), primary_key=True, comment='等级id')
level_name = Column(String(255, 'utf8_unicode_ci'), nullable=False, comment='称号')
class Behaviors(Base):
__tablename__ = "behaviors"
behaviors_id = Column(Integer, primary_key=True, autoincrement=True, comment="行为主键")
behaviors_name = Column(String(255), nullable=False, comment="行为称号")
behaviors_level = Column(Integer, comment="行为等级")
def __str__(self):
return "behaviors_id:{},behaviors_name:{},behaviors_level:{}".format(self.behaviors_id,self.behaviors_name,self.behaviors_level)
class Creams(Base):
""" 有必要承继Base """
# 数据库中存储的表名
__tablename__ = "creams"
creams_id = Column(Integer, primary_key=True, autoincrement=True, comment="摄像头主键")
creams_name = Column(String(255), nullable=False, comment="摄像头称号")
start_time = Column(DateTime, nullable=False, comment="敞开时刻")
open_cr = Column(Integer, comment="敞开摄像头")
source_path = Column(String(255), nullable=False, comment="摄像地址")
def __str__(self):
return "creams_id:{},creams_name:{},start_time:{},open_cr:{}"\
.format(self.creams_id,self.creams_name,self.start_time,self.open_cr)
class FaceData(Base):
__tablename__ = 'face_data'
data_id = Column(BIGINT, primary_key=True, comment='数据编号')
face_id = Column(BIGINT, comment='编号')
face_name = Column(String(255, 'utf8_unicode_ci'), nullable=False, comment='人脸称号')
feature_vector = Column(String(255, 'utf8_unicode_ci'), comment='特征向量')
update_time = Column(DATETIME)
create_time = Column(DATETIME, comment='创立时刻')
def __str__(self):
return "data_id:{},face_id:{},face_name:{},feature_vector:{},update_time:{},create_time:{}".\
format(self.data_id,self.face_id,self.face_name,self.feature_vector,self.update_time,self.create_time)
class FaceImg(Base):
__tablename__ = 'face_img'
img_id = Column(BigInteger, primary_key=True, comment='编号')
face_name = Column(String(255), nullable=True, comment='人脸称号')
create_time = Column(DateTime, nullable=False, comment='创立时刻')
imgs_path = Column(String(255), nullable=True, comment='文件途径')
face_id = Column(BigInteger, nullable=False, comment='人脸编号')
def __str__(self):
return f"FaceImg(img_id={self.img_id}, imgs_path='{self.imgs_path}', face_id={self.face_id})"
class FaceUnusual(Base):
__tablename__ = 'face_unusual'
unusual_id = Column(BigInteger, primary_key=True, comment='反常id')
active_time = Column(DateTime, nullable=False, comment='产生时刻')
video_id = Column(BigInteger, nullable=False, comment='videoId')
face_id = Column(BigInteger, nullable=False, comment='人脸id')
unusual_img = Column(String(255), nullable=False, comment='捕捉图画')
cream_id = Column(Integer, nullable=False, comment='摄像头id')
action_name = Column(String(255), nullable=False, comment='动作称号')
def __str__(self):
return f"FaceUnusual(unusual_id={self.unusual_id}, active_time='{self.active_time}', video_id={self.video_id}, face_id={self.face_id}, unusual_img='{self.unusual_img}', cream_id={self.cream_id},action_name={self.action_name})"
class SystemInfo(Base):
__tablename__ = 'system_info'
id = Column(Integer, primary_key=True)
name = Column(String(255))
key = Column(String(255))
root_user = Column(String(255))
index = Column(String(255))
start_time = Column(DateTime)
end_time = Column(DateTime)
def __repr__(self):
return f"<SystemInfo(name='{self.name}', key='{self.key}', root_user='{self.root_user}', index='{self.index}', start_time='{self.start_time}', end_time='{self.end_time}')>"
class Videos(Base):
__tablename__ = 'videos'
video_id = Column(BigInteger,primary_key=True, autoincrement=True,comment="视频id主键")
start_time = Column(DateTime, nullable=False, comment='开端时刻')
end_time = Column(DateTime, nullable=False, comment='完毕时刻')
in_day = Column(Date, nullable=False, comment='视频日期')
save_path = Column(String(255), nullable=False, comment='视频地址')
cream_id = Column(Integer, nullable=False, comment='摄像头id')
# 增加时刻索引
__table_args__ = (
Index('idx_videos_start_time', start_time),
)
def __str__(self):
return f"Videos(video_id={self.video_id}, start_time='{self.start_time}', end_time='{self.end_time}', in_day='{self.in_day}', save_path='{self.save_path}', cream_id={self.cream_id})"
之后的话,咱们在算法运转进程傍边就会将成果存储起来
算法发动
之后的话是咱们算法发动。
这儿的话,咱们仍是规划了一个发动接口。一起封装了一个进程池。
class ProcessPool:
def __init__(self, max_processes=mp.cpu_count()):
self.max_processes = max_processes
self.tasks = queue.Queue()
self.processes = {}
self._stop_event = mp.Event()
# 注册 Ctrl+C 信号处理函数,确保在程序被停止时能够正常整理资源
signal.signal(signal.SIGINT, self._handle_signals)
signal.signal(signal.SIGTERM, self._handle_signals)
def add_process(self, process_id, target, args=()):
if len(target.__code__.co_varnames) > len(args):
raise ValueError("Too few arguments")
p = mp.Process(target=self._wrapper, args=(process_id, target, args), daemon=True)
p.start()
self.processes[process_id] = p
while len(self.processes) >= self.max_processes:
for process_id, p in list(self.processes.items()):
if not p.is_alive():
del self.processes[process_id]
break
else:
time.sleep(0.1)
if not p.is_alive():
return
while not self.tasks.empty():
process_id, target, args = self.tasks.get()
p = mp.Process(target=self._wrapper, args=(process_id, target, args), daemon=True)
p.start()
self.processes[process_id] = p
def stop(self):
"""
停止进程池。
"""
self._stop_event.set()
for p in self.processes.values():
p.terminate()
self.processes.clear()
def restart(self, process_id):
"""
重启指定 id 的进程。
:param process_id: 进程id。
"""
if process_id not in self.processes:
raise ValueError("Process not found")
p = self.processes[process_id]
p.terminate()
p.join()
target, args = self.tasks.queue[0][1:]
p = mp.Process(target=self._wrapper, args=(process_id, target, args), daemon=True)
p.start()
self.processes[process_id] = p
def kill(self, process_id):
"""
完毕指定 id 的进程。
:param process_id: 进程id。
"""
if process_id not in self.processes:
raise ValueError("Process not found")
p = self.processes[process_id]
p.terminate()
def _handle_signals(self, signum, frame):
"""
信号处理函数,用于在进程被停止时正常整理资源。
"""
self.stop()
@staticmethod
def _wrapper(process_id, target, args):
"""
包装方针函数,以便能够支撑动态参数。
:param process_id: 进程id。
:param target: 进程要履行的方针函数。
:param args: 方针函数的参数列表。
"""
target(*args)
class AlgApplication(object):
"""
算法发动类,多个摄像头敞开
然后敞开多个进程
"""
def __init__(self):
self.open = True
session = SessionFactory()
self.face_Names_cahe = {}
for face_img in session.query(FaceImg).all():
self.face_Names_cahe[face_img.face_name] = face_img.face_id
session.close()
self.maxPoolSize = sysConfig.maxPoolSize
self.pool = ProcessPool(max_processes=self.maxPoolSize)
def go_fire(self,creams:Creams,face_name_cache):
"""
1. 初始化东西类
2. 初始化算法
:param cream_id:
:return:
"""
alg_process = ProcessAlg()
alg_process.set_cache(face_name_cache)
pose = PoseRec()
source_path = creams.source_path
try:
source_path_ = int(source_path)
source_path = source_path_
except Exception as e:
pass
"""
process1:是保存图片的
process2:是保存视频的
"""
pose.detect_from_video_realTime(source_path,
str(creams.creams_id),
show=False,
process1=alg_process.unusualAction,
process2=alg_process.saveVideo,
cream_id=creams.creams_id)
def init_start(self):
#初始化,敞开摄像头
session = SessionFactory()
# 运用查询语句读取一切 Creams 表中的数据
creams_list = session.query(Creams).all()
index = 0
# 敞开一切使命
for creams in creams_list:
if(creams.open_cr==1):
if(index>self.maxPoolSize):
warnings.warn('摄像头数量大于线程池最大容量,无法敞开全部摄像头', UserWarning)
continue
self.pool.add_process(creams.creams_id,self.go_fire,args=(creams,self.face_Names_cahe,))
index+=1
def stop_cream(self,cream_id):
"""
关闭摄像头
:param cream_id:
:return:
"""
self.pool.kill(cream_id)
def start_cream(self,creams):
"""
敞开摄像头
:param cream_id:
:return:
"""
self.pool.add_process(creams.creams_id,self.go_fire,args=(creams,self.face_Names_cahe,))
def restart_cream(self,cream_id):
self.pool.restart(cream_id)
def run(self):
"""
此刻履行的轮询函数,每隔1分钟,轮询数据库设置,这儿我现已不想再写什么进程通讯了
:return:
"""
# 初始化,敞开摄像头
self.init_start()
#每隔一分钟轮询
while(self.open):
time.sleep(60)
session = SessionFactory()
creams_list = session.query(Creams).all()
for creams in creams_list:
if (creams.open_cr == 1):
if(creams.creams_id not in self.pool.processes):
if (len(self.pool.processes)+1> self.maxPoolSize):
warnings.warn('摄像头数量大于线程池最大容量,无法敞开全部摄像头', UserWarning)
continue
self.pool.add_process(creams.creams_id, self.go_fire, args=(creams, self.face_Names_cahe,))
elif(creams.open_cr==0):
if(creams.creams_id in self.pool.processes):
self.pool.kill(creams.creams_id)
之后在咱们的,这儿发动,也便是app.py里边
"""
负责供给curd接口
"""
from flask import Flask, Blueprint
from flask_cors import CORS # 引进 CORS
from client.server.blueprints.test_api import test_api
from client.server.blueprints.face_img_api import face_imgs_api
from client.server.blueprints.behavior_levels_api import behavior_levels_api
from client.server.blueprints.behaviors_api import behaviors_api
from client.server.blueprints.creams_api import creams_api
from client.server.blueprints.face_data_api import face_data_api
from client.server.blueprints.face_unusuals_api import face_unusual_api
from client.server.blueprints.system_info_api import system_info_api
from client.server.blueprints.video_api import video_api
from client.server.blueprints.common_api import common_api
from client.server.sysConfig import is_Show
app = Flask(__name__,static_folder='./Resources')
CORS(app, resources=r'/*') # 启用 CORS,允许一切跨域请求
app.register_blueprint(test_api)
app.register_blueprint(behaviors_api)
app.register_blueprint(behavior_levels_api)
app.register_blueprint(creams_api)
app.register_blueprint(face_data_api)
app.register_blueprint(face_imgs_api)
app.register_blueprint(face_unusual_api)
app.register_blueprint(system_info_api)
app.register_blueprint(video_api)
app.register_blueprint(common_api)
#Dome演示模式,不发动,不履行,不发动云端,带不动!!!
import multiprocessing
def worker():
from client.server.alg_utils import AlgApplication
"""同步发动算法,演示时不敞开,开不动"""
algAppliction = AlgApplication()
algAppliction.run()
if __name__ == '__main__':
if(not is_Show):
p = multiprocessing.Process(target=worker)
p.start()
app.run(debug=True,host="127.0.0.1",port=8000)
不过,这儿值得一提的是,这个只是咱们客户端的代码。
咱们完好的架构其实是这样的:
客户端其实又是这样的: 惋惜的是,由于开发时刻紧张,这个端我没做。
项目完结简介
人脸辨认
ok,现在让咱们总览一下这个项目。
在本项目中,人脸辨认主要运用了第三方库dlib供给的算法完结。经过收集人脸图画,对其进行特征提取核算,得到对应人脸的特征向量。待辨认时,重新核算待辨认人脸的特征向量,并将其与库中已录入人脸进行比较,然后完结比照。该进程的流程下:
运转效果图如下:
多方针检测盯梢与行为辨认
在本项目中,咱们选用了 YOLOv5、DeepSORT 和 SlowFast 三种模型,并将它们有机地结合起来,成功完结了多方针的行为动作检测使命。这三个模型别离拥有不同的优势和特色,经过彼此配合,能够更好地满意视频监控的多方针检测和行为动作辨认需求。首要,YOLOv5是一个轻量化的网络架构,它能够高效、快速地进行方针检测,而且确保了一定的精确率。它选用了一些优秀的规划思路,比方选用SPP结构对输入图片进行处理,将不同标准的信息交融在一起以进步检测精度;运用FPN结构进行特征交融,完结多层次的特征提取和分类;还有针对小方针的改善等。此外,YOLOv5还选用了后处理算法,能够对检测到的方针进行筛选和分类,并给出方针的方位和姿态信息。因而,YOLOv5在本项目中被用来进行多方针检测使命。然而在本项目傍边,只是进行方针检测是不行的,还需要对方针进行盯梢和行为动作的辨认。因而,咱们引进了 DeepSORT 模型。DeepSORT模型是一种根据深度学习的多方针盯梢模型,能够对检测到的方针进行追寻,然后确保方针的连续性和正确性。它选用了一些立异的规划思路,比方根据外观和运动特征进行方针的相似性匹配,运用卡尔曼滤波对方针方位进行预测,以及选用一个时序嵌入网络(TSN)来学习方针的运动表明等。此外,DeepSORT还能够处理多个相似的方针,经过矩阵核算和模板匹配的方法区别它们,然后进步了盯梢的精确度和鲁棒性。在本项目中,咱们将YOLOv5模型的检测成果输入到DeepSORT模型中,DeepSORT运用方针的运动轨道和特征进行方针盯梢DeepSORT 模型还能够处理多个相似的方针,并经过矩阵核算和模板匹配等方法进行区别,进步方针盯梢的精确度和鲁棒性。最终,咱们使用 SlowFast 模型来完结对方针的行为动作辨认。SlowFast模型是一种先进的视频分类和动作辨认网络结构,在本项目中被用来完结方针的行为动作辨认。SlowFast模型的长处在于能够一起捕捉方针的上下文信息和细节信息,然后愈加精准地进行行为动作辨认。它选用了慢速和快速两个分支的规划,其间慢速分支能够捕捉方针的上下文信息,快速分支能够捕捉方针的细节信息,然后更好地进行动作分类和辨认。在本项目中,咱们将DeepSORT模型得到的方针轨道输入到SlowFast模型中,经过一系列卷积、池化和全连接层的处理,能够输出方针在轨道上所表现出的不同动作行为。之后当检测到了对应的风险动作之后,咱们将立即对改方针进行人脸辨认,并记载对应的时刻点,视频截图,现已对应的视频时刻点。便于后续快速调取当时产生的时刻点视频,有利于后期进行安全评估和剖析。
Web 操作界面
咱们的使用不仅有根据 Vue 结构开发的 Web UI,一起根据 Flask 结构开发的后端服务器,二者紧密配合,形成了一个完好的完好的项目使用。Vue 结构供给了友爱的用户界面和直观的交互方法,用户能够经过简略的操作调整视频源和视频参数,发动和停止多方针行为动作检测使命,并实时检查检测成果和核算信息。一起,在 Web UI 中咱们运用 Echarts 图表库完结了一系列可视化图表,如柱状图、折线图等,让用户愈加清晰地了解检测成果和核算信息。Flask 结构供给了高效安稳的后端服务,处理前端传来的视频数据,并进行多方针行为动作检测。一起,将检测成果实时推送给前端,并在前端可视化显示。经过供给 API 接口和数据库服务,方便用户进行数据查询和办理。一起,根据配置参数和环境变量,满意使用的各种需求和约束。将二者彼此结合,咱们完结了全栈式的使用开发,使得用户能够愈加快捷地进行多方针行为动作检测使命,完结了全方位的数据处理与剖析:
摄像头检查情况:
检查人脸
录入和修改页面 之后是关于,成员行为的记载,此模块主要分为两大块,人员近期的行为记载,对应时刻点的记载,以及对应时刻点的详细情况,包含事发时刻,事发视频,以及对应的精准视频关键帧。
总结
以上便是全部内容了,其实也是最初做大创的内容,欸,不得不说 现在基本上都是做Application + 机器学习/深度学习, 真的卷哇。不过始终记住,东西便是东西,没什么特别的,用就对了,学就对了,你不学,被干趴下的便是你。
那么这儿的话,来个小小的私心,点赞超过100才开源,我只是静静分享~(注: the_way_inf == Huterox)