原理
背景差分法的思想是用图像序列中的当前帧和背景参考模型比较来检测运动物体。其核心是背景的建模方法。这里实现一种简单的背景建模方法,即对视频的全部帧取像素平均值得到背景。
当然这种简单的算法局限性很大,视频的时长,光线与背景的变化都会对检测效果产生极大的影响。
实现步骤
- 背景建模:对视频的全部帧取像素平均值得到背景
- 比较:当前帧与背景作做差,差值大于一定阈值的像素点识别为前景
- 提取:在原始帧上扣取出前景
效果
原始图像 建立的背景 目标检测结果源代码
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
# 读取帧数
img_number = 48
# 各帧的集合
all_img = [np.array(Image.open('F:/input/'+str(i+1)+'.jpg', 'r')) for i in range(img_number)]
# 帧的宽高
h = all_img[0].shape[0]
v = all_img[0].shape[1]
# 计算得到背景
back_img = np.zeros((h, v))
for single_img in all_img:
back_img += single_img
back_img /= img_number
# 保存背景
Image.fromarray(back_img).convert('RGB').save('F:/output/background.jpg')
# 原视频与背景逐帧相减后取绝对值 得到前景
front_img = np.array([i - back_img for i in all_img])
front_img = front_img.__abs__()
# 前景二值化 设定阈值将前景像素值化为0或1
threshold_level = 50
threshold = np.full((h, v), threshold_level)
front_img = np.array([i < threshold for i in front_img], dtype=np.int8)*255
# 在原帧上抠图 得到真实的前景
front_img = np.fmax(np.array(front_img), all_img)
# 保存
for i in range(img_number):
Image.fromarray(front_img[i]).convert('RGB').save('F:/output/'+str(i+1)+'.jpg')
# 显示
loc_h = 6
loc_v = int(img_number / loc_h)
for i in range(loc_h * loc_v):
plt.subplot(loc_v, loc_h, i+1)
plt.imshow(front_img[i], cmap='gray')
plt.show()
视频转为图像是使用matlab实现的
%将视频转换为图片
clear
clc
file_name = 'F:\input.avi'; %视频所在文件夹
obj = VideoReader(file_name); %读取视频文件
numFrames = obj.NumberOfFrames; %视频总的帧数
for k = 1: numFrames
frame = read(obj,k);
%imshow(frame);
gray_frame = rgb2gray(frame); %若每一帧为彩色图片,转换为灰度图
imshow(frame); %显示每一帧图片
%保存每一帧图片
imwrite(gray_frame,strcat('F:\input\',num2str(k),'.jpg'),'jpg');
end
网友评论