MogFace-large教程如何修改webui.py源码以支持视频流实时检测今天咱们来聊一个很实用的技术问题怎么把MogFace-large这个超强的人脸检测模型从只能处理静态图片升级到能实时处理视频流。如果你用过MogFace肯定知道它在人脸检测领域有多厉害——在Wider Face榜单上霸榜一年多检测精度高得离谱。但默认的WebUI只能上传图片检测要是能实时处理摄像头视频或者视频文件那应用场景就广多了。我最近正好有个项目需要实时人脸检测就研究了一下怎么改源码。整个过程其实不难主要是理解Gradio的事件处理机制然后加一些视频处理逻辑。下面我就手把手带你走一遍保证小白也能看懂。1. 环境准备与项目理解1.1 先看看我们有什么首先你得确保MogFace-large已经部署好了。根据提供的资料项目结构大概是这样的模型加载和前端代码在/usr/local/bin/webui.py用的是ModelScope加载模型Gradio做前端界面目前功能上传图片 → 检测人脸 → 显示结果我们要做的就是在这个基础上增加视频流处理能力。1.2 需要安装的额外依赖如果你要处理视频文件或者摄像头需要安装OpenCVpip install opencv-python如果是用conda环境conda install -c conda-forge opencv2. 理解现有的webui.py结构2.1 先看看原来的代码逻辑在动手改之前我们先理解一下原来的代码是怎么工作的。虽然我没看到完整的webui.py源码但根据Gradio的常见模式它大概长这样import gradio as gr from modelscope.pipelines import pipeline from modelscope.utils.constant import Tasks # 1. 加载模型 model pipeline(Tasks.face_detection, damo/cv_resnet101_face-detection_cvpr22papermogface) # 2. 定义检测函数 def detect_faces(image): # 这里调用模型进行检测 result model(image) # 处理结果画框等 return annotated_image # 3. 创建Gradio界面 with gr.Blocks() as demo: gr.Markdown(# MogFace人脸检测) with gr.Row(): input_image gr.Image(label上传图片) output_image gr.Image(label检测结果) detect_btn gr.Button(开始检测) detect_btn.click(detect_faces, inputsinput_image, outputsoutput_image) demo.launch()这个结构很简单上传图片 → 点击按钮 → 调用检测函数 → 显示结果。2.2 视频处理的不同之处处理视频和图片有几个关键区别输入形式不同视频可以是文件也可以是摄像头实时流处理方式不同视频要一帧一帧处理输出形式不同视频要保存成文件或者实时显示性能要求不同视频要实时处理速度很重要3. 修改webui.py支持视频检测3.1 第一步增加视频输入组件我们先在界面上增加视频输入选项。打开/usr/local/bin/webui.py找到创建界面的部分。原来的界面可能只有图片上传我们改成这样with gr.Blocks() as demo: gr.Markdown(# MogFace人脸检测 - 支持图片和视频) # 创建一个选项卡让用户选择输入类型 with gr.Tabs(): with gr.TabItem(图片检测): with gr.Row(): img_input gr.Image(label上传图片, typenumpy) img_output gr.Image(label检测结果) img_btn gr.Button(检测图片) with gr.TabItem(视频检测): with gr.Row(): # 视频文件上传 video_input gr.Video(label上传视频文件) # 或者摄像头输入 camera_input gr.Image(sourcewebcam, streamingTrue, label摄像头实时检测) with gr.Row(): video_output gr.Video(label处理后的视频) camera_output gr.Image(label实时检测画面) video_btn gr.Button(处理视频文件) # 摄像头不需要按钮实时处理这里我做了几个重要改动用gr.Tabs()创建了两个选项卡一个给图片一个给视频视频部分支持两种输入上传视频文件和摄像头实时流摄像头用了streamingTrue这样就能实时获取帧3.2 第二步修改检测函数支持视频帧原来的detect_faces函数只能处理单张图片我们需要一个新的函数来处理视频帧import cv2 import numpy as np from PIL import Image import tempfile # 原来的图片检测函数保持不变 def detect_faces(image): 处理单张图片 if image is None: return None # 调用MogFace模型 result model(image) # 在图片上画检测框 annotated_image draw_boxes(image, result) return annotated_image # 新增处理视频文件的函数 def process_video(video_path): 处理整个视频文件 if video_path is None: return None # 读取视频 cap cv2.VideoCapture(video_path) # 获取视频信息 fps int(cap.get(cv2.CAP_PROP_FPS)) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 创建临时文件保存处理后的视频 temp_output tempfile.NamedTemporaryFile(suffix.mp4, deleteFalse) output_path temp_output.name # 创建视频写入器 fourcc cv2.VideoWriter_fourcc(*mp4v) out cv2.VideoWriter(output_path, fourcc, fps, (width, height)) # 逐帧处理 frame_count 0 while True: ret, frame cap.read() if not ret: break # 转换颜色空间 BGR - RGB frame_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 检测人脸 result model(frame_rgb) # 画检测框 annotated_frame draw_boxes(frame_rgb, result) # 转换回BGR用于写入视频 annotated_frame_bgr cv2.cvtColor(annotated_frame, cv2.COLOR_RGB2BGR) out.write(annotated_frame_bgr) frame_count 1 if frame_count % 30 0: # 每30帧打印一次进度 print(f已处理 {frame_count} 帧) # 释放资源 cap.release() out.release() return output_path # 新增实时摄像头处理函数 def process_camera_frame(frame): 处理摄像头实时帧 if frame is None: return None # 检测人脸 result model(frame) # 画检测框 annotated_frame draw_boxes(frame, result) return annotated_frame # 辅助函数在图像上画检测框 def draw_boxes(image, detection_result): 在图像上绘制人脸检测框 if detection_result is None or boxes not in detection_result: return image # 复制图像避免修改原图 img_copy image.copy() # 获取画图工具 if isinstance(img_copy, np.ndarray): # 如果是numpy数组用OpenCV画图 for box in detection_result[boxes]: x1, y1, x2, y2 map(int, box[:4]) confidence box[4] if len(box) 4 else 1.0 # 画矩形框 cv2.rectangle(img_copy, (x1, y1), (x2, y2), (0, 255, 0), 2) # 显示置信度 label fFace: {confidence:.2f} cv2.putText(img_copy, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) else: # 如果是PIL图像用PIL画图 from PIL import ImageDraw draw ImageDraw.Draw(img_copy) for box in detection_result[boxes]: x1, y1, x2, y2 map(int, box[:4]) confidence box[4] if len(box) 4 else 1.0 # 画矩形框 draw.rectangle([x1, y1, x2, y2], outlinegreen, width2) # 显示置信度 label fFace: {confidence:.2f} draw.text((x1, y1-15), label, fillgreen) return img_copy3.3 第三步连接界面和函数现在我们需要把界面组件和这些函数连接起来# 连接图片检测 img_btn.click(detect_faces, inputsimg_input, outputsimg_output) # 连接视频文件处理 video_btn.click(process_video, inputsvideo_input, outputsvideo_output) # 连接摄像头实时处理 # 这里用streaming模式不需要点击按钮 camera_input.stream(process_camera_frame, inputscamera_input, outputscamera_output)注意摄像头这里用了.stream()而不是.click()这是Gradio的流式处理API可以实时处理每一帧。3.4 第四步处理性能优化实时视频处理对性能要求很高MogFace-large虽然准确但可能不够快。我们可以加一些优化# 在文件开头添加 import time from functools import lru_cache # 可以缓存模型避免重复加载如果代码结构允许 # lru_cache(maxsize1) # def get_model(): # return pipeline(Tasks.face_detection, damo/cv_resnet101_face-detection_cvpr22papermogface) # 修改摄像头处理函数加入帧率控制 class CameraProcessor: def __init__(self): self.last_time time.time() self.frame_count 0 self.fps 0 def process_frame_with_fps(self, frame): 带FPS计算的帧处理 current_time time.time() self.frame_count 1 # 每秒计算一次FPS if current_time - self.last_time 1.0: self.fps self.frame_count self.frame_count 0 self.last_time current_time print(f处理FPS: {self.fps}) # 如果帧率太低可以跳帧处理 if self.fps 10 and self.frame_count % 2 0: return frame # 跳过这一帧直接返回原图 # 正常处理 result model(frame) annotated_frame draw_boxes(frame, result) # 在画面上显示FPS if isinstance(annotated_frame, np.ndarray): cv2.putText(annotated_frame, fFPS: {self.fps}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) return annotated_frame # 创建处理器实例 processor CameraProcessor() # 修改摄像头处理函数 def process_camera_frame_optimized(frame): return processor.process_frame_with_fps(frame)4. 完整代码示例把上面的代码片段组合起来完整的webui.py修改后大概长这样import gradio as gr import cv2 import numpy as np from PIL import Image import tempfile import time from modelscope.pipelines import pipeline from modelscope.utils.constant import Tasks # 加载MogFace-large模型 print(正在加载MogFace-large模型...) model pipeline(Tasks.face_detection, damo/cv_resnet101_face-detection_cvpr22papermogface) print(模型加载完成) class CameraProcessor: 摄像头处理器带性能优化 def __init__(self): self.last_time time.time() self.frame_count 0 self.fps 0 def process_frame(self, frame): 处理单帧带FPS计算和跳帧逻辑 if frame is None: return None # 计算FPS current_time time.time() self.frame_count 1 if current_time - self.last_time 1.0: self.fps self.frame_count self.frame_count 0 self.last_time current_time # 性能优化如果FPS太低就跳帧 if self.fps 15 and self.frame_count % 2 0: # 跳过检测直接返回原图或者返回上一帧的结果 return frame # 进行人脸检测 try: result model(frame) annotated_frame self.draw_boxes(frame, result) # 在画面上显示FPS if isinstance(annotated_frame, np.ndarray): cv2.putText(annotated_frame, fFPS: {self.fps}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) return annotated_frame except Exception as e: print(f检测出错: {e}) return frame def draw_boxes(self, image, detection_result): 绘制检测框 if detection_result is None or boxes not in detection_result: return image img_copy image.copy() if isinstance(img_copy, np.ndarray): # OpenCV格式 for box in detection_result[boxes]: x1, y1, x2, y2 map(int, box[:4]) confidence box[4] if len(box) 4 else 1.0 # 画框 cv2.rectangle(img_copy, (x1, y1), (x2, y2), (0, 255, 0), 2) # 显示置信度 label f{confidence:.2f} cv2.putText(img_copy, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) else: # PIL格式 from PIL import ImageDraw draw ImageDraw.Draw(img_copy) for box in detection_result[boxes]: x1, y1, x2, y2 map(int, box[:4]) confidence box[4] if len(box) 4 else 1.0 draw.rectangle([x1, y1, x2, y2], outlinegreen, width2) draw.text((x1, y1-15), f{confidence:.2f}, fillgreen) return img_copy def process_image(image): 处理单张图片 if image is None: return None result model(image) processor CameraProcessor() return processor.draw_boxes(image, result) def process_video_file(video_path): 处理视频文件 if video_path is None: return None print(f开始处理视频: {video_path}) # 读取视频 cap cv2.VideoCapture(video_path) if not cap.isOpened(): print(无法打开视频文件) return None # 获取视频参数 fps int(cap.get(cv2.CAP_PROP_FPS)) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) total_frames int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) print(f视频信息: {width}x{height}, {fps}FPS, 总帧数: {total_frames}) # 创建输出文件 temp_output tempfile.NamedTemporaryFile(suffix.mp4, deleteFalse) output_path temp_output.name # 创建视频写入器 fourcc cv2.VideoWriter_fourcc(*mp4v) out cv2.VideoWriter(output_path, fourcc, fps, (width, height)) processor CameraProcessor() processed_frames 0 # 逐帧处理 while True: ret, frame cap.read() if not ret: break # 转换颜色空间 frame_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 检测人脸 result model(frame_rgb) annotated_frame processor.draw_boxes(frame_rgb, result) # 转换回BGR并写入 frame_bgr cv2.cvtColor(annotated_frame, cv2.COLOR_RGB2BGR) out.write(frame_bgr) processed_frames 1 if processed_frames % 30 0: progress (processed_frames / total_frames) * 100 print(f进度: {processed_frames}/{total_frames} ({progress:.1f}%)) # 清理资源 cap.release() out.release() print(f视频处理完成保存到: {output_path}) return output_path # 创建处理器实例 camera_processor CameraProcessor() def process_camera(frame): 处理摄像头帧 return camera_processor.process_frame(frame) # 创建Gradio界面 with gr.Blocks(themegr.themes.Soft()) as demo: gr.Markdown( # MogFace-large人脸检测系统 ### 支持图片、视频文件和摄像头实时检测 ) with gr.Tabs(): # 标签页1图片检测 with gr.TabItem( 图片检测): gr.Markdown(上传图片进行人脸检测) with gr.Row(): with gr.Column(): image_input gr.Image(label上传图片, typenumpy) image_button gr.Button(开始检测, variantprimary) with gr.Column(): image_output gr.Image(label检测结果) # 示例图片 gr.Examples( examples[[example1.jpg], [example2.jpg]], inputsimage_input, outputsimage_output, fnprocess_image, cache_examplesTrue ) # 标签页2视频文件检测 with gr.TabItem( 视频文件检测): gr.Markdown(上传视频文件系统将检测每一帧中的人脸) with gr.Row(): with gr.Column(): video_input gr.Video(label上传视频文件) video_button gr.Button(处理视频, variantprimary) video_status gr.Textbox(label处理状态, interactiveFalse) with gr.Column(): video_output gr.Video(label处理后的视频) # 标签页3摄像头实时检测 with gr.TabItem( 摄像头实时检测): gr.Markdown(开启摄像头进行实时人脸检测) with gr.Row(): with gr.Column(): camera_input gr.Image( sourcewebcam, streamingTrue, label摄像头画面, typenumpy ) gr.Markdown(提示摄像头已自动开启检测结果实时显示在右侧) with gr.Column(): camera_output gr.Image( label实时检测结果, typenumpy ) # 连接事件 image_button.click(process_image, inputsimage_input, outputsimage_output) video_button.click( process_video_file, inputsvideo_input, outputsvideo_output ).then( lambda: 处理完成, outputsvideo_status ) # 摄像头流式处理 camera_input.stream(process_camera, inputscamera_input, outputscamera_output) # 启动应用 if __name__ __main__: demo.launch( server_name0.0.0.0, server_port7860, shareFalse, debugTrue )5. 实际使用与测试5.1 启动修改后的应用保存修改后的webui.py然后运行python /usr/local/bin/webui.py你会看到Gradio界面现在有三个选项卡了。5.2 测试不同功能测试图片检测点击图片检测选项卡上传一张带人脸的图片点击开始检测查看结果应该能看到绿色的人脸框测试视频文件检测点击视频文件检测选项卡上传一个MP4或AVI格式的视频点击处理视频处理时间取决于视频长度下载处理后的视频用播放器打开查看效果测试摄像头实时检测点击摄像头实时检测选项卡允许浏览器访问摄像头你会看到实时画面人脸会被自动框出来注意右上角的FPS显示如果太低可以调整跳帧逻辑5.3 常见问题解决问题1摄像头无法打开检查浏览器是否允许摄像头权限检查是否有其他程序占用了摄像头尝试换一个浏览器Chrome兼容性最好问题2视频处理太慢可以降低视频分辨率再上传修改代码中的跳帧逻辑if self.fps 15这个阈值考虑使用更轻量级的模型版本问题3检测框不准确MogFace-large在大多数情况下都很准但极端角度或遮挡可能有问题可以调整置信度阈值代码中默认是显示所有检测结果问题4内存不足处理大视频时可能内存不足可以分块处理视频不要一次性加载整个视频到内存6. 进阶优化建议如果你想让这个系统更强大可以考虑以下优化6.1 批量处理优化# 可以一次处理多帧利用GPU并行能力 def process_batch(frames): 批量处理多帧 # 将多帧组合成batch batch np.stack(frames) # 这里需要模型支持batch处理 # results model(batch) # 实际中MogFace可能需要逐帧处理 results [] for frame in frames: results.append(model(frame)) return results6.2 添加更多输出信息def draw_detailed_boxes(image, result): 绘制更详细的信息 img_copy image.copy() if boxes in result: for i, box in enumerate(result[boxes]): x1, y1, x2, y2 map(int, box[:4]) confidence box[4] if len(box) 4 else 1.0 # 画框 cv2.rectangle(img_copy, (x1, y1), (x2, y2), (0, 255, 0), 2) # 显示详细信息 info fFace {i1}: {confidence:.3f} cv2.putText(img_copy, info, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) # 显示统计信息 total_faces len(result[boxes]) if boxes in result else 0 stats fTotal Faces: {total_faces} cv2.putText(img_copy, stats, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2) return img_copy6.3 支持更多视频格式def process_video_general(video_path): 支持更多视频格式 # 尝试不同的解码器 codecs [mp4v, XVID, MJPG, H264] for codec in codecs: cap cv2.VideoCapture(video_path) if cap.isOpened(): break # 如果都打不开尝试用ffmpeg if not cap.isOpened(): # 可以用subprocess调用ffmpeg转换格式 import subprocess temp_file tempfile.NamedTemporaryFile(suffix.mp4, deleteFalse) cmd [ffmpeg, -i, video_path, -c:v, libx264, temp_file.name] subprocess.run(cmd, checkTrue) video_path temp_file.name cap cv2.VideoCapture(video_path) # 继续处理...7. 总结通过上面的步骤我们成功把MogFace-large从只能处理图片升级到了支持视频流实时检测。主要做了以下几件事理解了原有代码结构先搞清楚原来的webui.py是怎么工作的增加了视频输入组件用Gradio的Video和Image(sourcewebcam)组件编写了视频处理函数包括视频文件处理和摄像头实时处理优化了性能加了FPS计算和跳帧逻辑确保实时性完善了用户界面用选项卡组织功能让界面更清晰现在你的MogFace-large系统可以检测图片中的人脸原来就有的功能处理视频文件给每一帧标出人脸实时摄像头检测看到实时画面和人脸框这个升级后的系统可以用在很多实际场景安防监控实时检测摄像头中的人脸视频分析分析已有的视频素材统计人脸出现情况互动应用做一个人脸互动的演示系统内容审核自动检测视频中是否有人脸修改源码听起来有点吓人但实际做起来并不难。关键是一步一步来先理解原有代码然后在小范围内修改测试。Gradio的流式处理API让实时视频处理变得特别简单基本上就是stream()一个函数的事情。如果你在修改过程中遇到问题或者有更好的优化建议欢迎交流讨论。技术就是在不断改进中进步的。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。