%% 主程序
function video_surveillance_system()
% 1. 读取视频文件
[filename, pathname] = uigetfile({'*.mp4;*.avi;*.mov','视频文件'}, '选择监控视频');
if isequal(filename, 0)
disp('用户取消选择');
return;
end
video_path = fullfile(pathname, filename);
video_reader = VideoReader(video_path);
% 2. 获取第一帧用于设置警戒线
first_frame = readFrame(video_reader);
imshow(first_frame);
title('请设置警戒线:点击起点和终点,按Enter确认');
% 3. 手动设置警戒线
[x, y] = ginput(2);
close;
alert_line = [x(1), y(1); x(2), y(2)]; % 警戒线起点和终点
% 4. 初始化背景减法器
detector = setup_detector();
% 5. 创建视频播放界面
fig = figure('Name', '智能视频监控系统', 'NumberTitle', 'off');
h_img = imshow(first_frame);
hold on;
% 绘制警戒线
line_plot = plot(alert_line(:,1), alert_line(:,2), 'r-', 'LineWidth', 2);
start_point = plot(alert_line(1,1), alert_line(1,2), 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');
end_point = plot(alert_line(2,1), alert_line(2,2), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
% 6. 视频处理主循环
alert_triggered = false;
prev_positions = [];
while hasFrame(video_reader)
frame = readFrame(video_reader);
gray_frame = rgb2gray(frame);
% 运动目标检测
bbox = detect_moving_objects(detector, gray_frame);
% 更新显示
set(h_img, 'CData', frame);
delete(findobj(gca, 'Type', 'rectangle'));
% 绘制检测到的物体和轨迹
current_positions = [];
for i = 1:size(bbox, 1)
rectangle('Position', bbox(i,:), 'EdgeColor', 'g', 'LineWidth', 2);
center = [bbox(i,1)+bbox(i,3)/2, bbox(i,2)+bbox(i,4)/2];
current_positions = [current_positions; center];
plot(center(1), center(2), 'b.', 'MarkerSize', 15);
end
% 检测越界行为
if ~isempty(prev_positions) && ~isempty(current_positions)
[crossed, crossing_point] = check_line_crossing(prev_positions, current_positions, alert_line);
if crossed && ~alert_triggered
trigger_alert(frame, crossing_point);
alert_triggered = true;
end
end
prev_positions = current_positions;
pause(1/video_reader.FrameRate); % 保持视频原速
end
end
%% 设置运动检测器
function detector = setup_detector()
detector = vision.ForegroundDetector(...
'NumGaussians', 3, ...
'NumTrainingFrames', 50, ...
'MinimumBackgroundRatio', 0.7, ...
'LearningRate', 0.005);
% 形态学操作参数
detector.BlobAnalysis = vision.BlobAnalysis(...
'AreaOutputPort', true, ...
'CentroidOutputPort', true, ...
'BoundingBoxOutputPort', true, ...
'MinimumBlobArea', 500, ... % 最小检测区域
'MaximumCount', 10); % 最大目标数
end
%% 运动物体检测
function bbox = detect_moving_objects(detector, frame)
% 前景检测
fg_mask = step(detector, frame);
% 形态学处理
se = strel('square', 3);
clean_mask = imopen(fg_mask, se);
clean_mask = imclose(clean_mask, se);
clean_mask = imfill(clean_mask, 'holes');
% 检测连通区域
[~, ~, bbox] = step(detector.BlobAnalysis, clean_mask);
end
%% 检测越界行为
function [crossed, crossing_point] = check_line_crossing(prev_pos, curr_pos, line)
crossed = false;
crossing_point = [];
% 计算警戒线向量
line_vec = line(2,:) - line(1,:);
for i = 1:size(curr_pos, 1)
% 计算物体运动向量
move_vec = curr_pos(i,:) - prev_pos(i,:);
% 计算向量叉积判断交叉
cross1 = cross_product([prev_pos(i,:) - line(1,:); line_vec]);
cross2 = cross_product([curr_pos(i,:) - line(1,:); line_vec]);
% 如果叉积符号相反,说明穿过直线
if cross1 * cross2 < 0
% 计算精确交叉点
t = cross_product([line(1,:) - prev_pos(i,:); move_vec]) / cross_product([move_vec; line_vec]);
if t >= 0 && t <= 1
crossed = true;
crossing_point = prev_pos(i,:) + t * move_vec;
return;
end
end
end
end
%% 叉积计算
function cp = cross_product(vectors)
cp = vectors(1,1)*vectors(2,2) - vectors(1,2)*vectors(2,1);
end
%% 触发报警
function trigger_alert(frame, point)
% 显示报警信息
fig_alert = figure('Name', '警报!', 'NumberTitle', 'off', 'Color', 'r');
imshow(frame);
hold on;
plot(point(1), point(2), 'rx', 'MarkerSize', 30, 'LineWidth', 3);
text(10, 30, '检测到非法越界!', 'Color', 'r', 'FontSize', 20, 'FontWeight', 'bold');
% 发出报警声音
Fs = 8192;
t = 0:1/Fs:0.5;
y = sin(2*pi*800*t) .* exp(-5*t);
sound(y, Fs);
% 保存警报帧
timestamp = datestr(now, 'yyyymmdd_HHMMSS');
imwrite(frame, ['alert_' timestamp '.jpg']);
disp('警报已触发! 越界事件已记录');
end
将该代码提取的第一帧图像进行灰度化 → 高斯滤波 → 梯度,是图片清晰,然后下面和原来一样进行警戒线部分
最新发布