Python视频目标检测与背景移除:代码报错修复请求
视频目标检测与背景移除代码修复方案
错误原因分析
background变量初始值为0,并非与视频帧同尺寸、同通道数的图像,执行cv2.bitwise_and时因输入尺寸/类型不匹配触发断言错误。cv2.VideoWriter使用-1作为fourcc参数存在兼容性问题,部分环境下无法正确编码MP4文件。
修复后的颜色检测版代码
import cv2 import numpy as np import time video_capture = cv2.VideoCapture(0) frame_width = int(video_capture.get(3)) frame_height = int(video_capture.get(4)) # 指定MP4兼容的编码格式 fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter('output.mp4', fourcc, 10, (frame_width, frame_height), True) # 等待3秒后捕获背景帧 time.sleep(3) ret, background = video_capture.read() if not ret: print("无法捕获背景帧") video_capture.release() exit() background = np.flip(background, axis=1) # 和后续帧保持镜像一致 while video_capture.isOpened(): ret, image = video_capture.read() if not ret: break image = np.flip(image, axis=1) # 转换为HSV颜色空间,检测蓝色目标 hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) lower_blue = np.array([94, 80, 2]) upper_blue = np.array([126, 255, 255]) mask_all = cv2.inRange(hsv, lower_blue, upper_blue) # 形态学操作优化掩码 mask_all = cv2.morphologyEx(mask_all, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8)) mask_all = cv2.morphologyEx(mask_all, cv2.MORPH_DILATE, np.ones((3, 3), np.uint8)) # 分离目标与背景 mask2 = cv2.bitwise_not(mask_all) streamA = cv2.bitwise_and(image, image, mask=mask2) # 保留非蓝色区域(原帧内容) streamB = cv2.bitwise_and(background, background, mask=mask_all) # 蓝色区域替换为背景 output = cv2.addWeighted(streamA, 1, streamB, 1, 0) out.write(output) cv2.imshow("cloak_trick", output) if cv2.waitKey(25) == 13: # 回车键退出 break video_capture.release() out.release() cv2.destroyAllWindows()
通用人像分割替代方案(无需颜色检测)
如果需要检测人像并移除背景,推荐使用MediaPipe的人像分割模型,无需依赖颜色特征,保留RGB格式的人像目标:
import cv2 import mediapipe as mp import numpy as np mp_selfie_segmentation = mp.solutions.selfie_segmentation segmentation_model = mp_selfie_segmentation.SelfieSegmentation(model_selection=1) video_capture = cv2.VideoCapture(0) frame_width = int(video_capture.get(3)) frame_height = int(video_capture.get(4)) fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter('portrait_output.mp4', fourcc, 10, (frame_width, frame_height), True) # 自定义背景(可以替换为任意图像路径) background = cv2.imread('background.jpg') background = cv2.resize(background, (frame_width, frame_height)) while video_capture.isOpened(): ret, frame = video_capture.read() if not ret: break # 镜像翻转帧 frame = np.flip(frame, axis=1) rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 执行人像分割 results = segmentation_model.process(rgb_frame) mask = results.segmentation_mask # 将掩码转换为3通道,用于与帧和背景做融合 mask = np.stack((mask,)*3, axis=-1) mask = cv2.GaussianBlur(mask, (5,5), 0) # 模糊掩码边缘,避免生硬 # 融合人像与背景,保留RGB格式的人像 output = frame * mask + background * (1 - mask) output = output.astype(np.uint8) # 转换为OpenCV支持的8位格式 out.write(output) cv2.imshow("Portrait Segmentation", output) if cv2.waitKey(25) == 13: break video_capture.release() out.release() cv2.destroyAllWindows()
说明
- 颜色检测版适合特定颜色的目标(如蓝色衣物),通过HSV阈值分离目标
- 人像分割版适合通用人像场景,无需指定颜色,分割精度更高,背景可自定义为任意图像
内容的提问来源于stack exchange,提问作者hh tt
相关产品推荐
相关产品推荐

