数字图像处理拓展题目——利用Matlab实现动态目标检测 二帧差法、ViBe法、高斯混合模型法,可应用于学生递东西行为检测

1.二帧差法实现动态目标检测

先上效果图:

在这里插入图片描述
在这里插入图片描述

利用GUI界面显示出来效果图为:

在这里插入图片描述
在这里插入图片描述

实现流程

在这里插入图片描述

1.利用matlab中的VideoReader函数读取视频流。
2.帧差法:获得视频帧数,用for循环对图像每相邻两帧之间做差,得到差分后的每一帧视频图像(以二帧差法为例,此处也可采用三帧法、ViBe方法、高斯混合建模法得到动态目标检测的二值图像)。
3.对差分后的图像进行二值化处理,然后填充图形区域和空洞,并进行中值滤波实现图形的去噪。
4.利用形态学知识,对图像进行腐蚀和膨胀,实现进一步去噪和细化图形中的目标。
5.对图形的每一行进行行扫描,找出每一行白色区域的临界端点,并将中间的区域填充为白色,实现目标的区域填充。
6.找到差分图像的上下左右边界,用矩形框将目标在视频中框起来。
7.重复以上操作,即可实现视频流中目标的检测。

1.1读取视频流,完成初始化工作。

利用matlab中的VideoReader函数读取视频流。
利用帧差法获得视频帧数,用for循环对图像每相邻两帧之间做差,得到差分后的每一帧视频图像。

在这里插入图片描述

1.2利用帧差法得到差分图像

对差分后的图像进行二值化处理并中值滤波去噪处理后,将其叠加在原图像上

1.3利用形态学知识对象进行膨胀和腐蚀,得出处理后的图像

对差分后的图像填充图形区域和空洞,并进行中值滤波实现图形的去噪,利用形态学知识,对图像进行腐蚀和膨胀,实现进一步去噪和细化图形中的目标

1.4行扫描,对图像进行填充

对图形的每一行进行行扫描,找出每一行白色区域的临界端点,并将中间的区域填充为白色,实现目标的区域填充

1.5找到差分图像的上下左右边界,用矩形框将目标在视频中框起来

在这里插入图片描述

2.利用三帧差法实现动态目标检测

算法实现:第三帧与第二帧做差,第二帧与第一帧做差,对这两个差分图像进行交集运算
与二帧差法的区别:相比相邻两帧差法,三帧差法比较适合对运动速度较快物体的检测,但是仍然会有空洞出现,并且物体移动速度较慢时容易丢失轮廓。

代码实现:(利用GUI界面实现,此代码仅为内部的核心部分,下同)

% --- Executes on button press in pushbutton6.
function pushbutton6_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton6 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
videoName = get(handles.edit1, 'String');
videoSource = vision.VideoFileReader(videoName,...
    'ImageColorSpace', 'RGB', 'VideoOutputDataType', 'uint8');
videoInfo = info(videoSource);
videoRate = videoInfo.VideoFrameRate;
waitTime = 1.0/videoRate;
frame_first = rgb2gray(step(videoSource));
frame = step(videoSource);
global exit_flag;
global pause_flag;
exit_flag = false;
pause_flag = false;
while ~isDone(videoSource) && ~exit_flag
    if pause_flag
        uiwait(handles.figure1);
    end
    frame_second = rgb2gray(frame);
    frame = step(videoSource);%读取图像
    frame_third = rgb2gray(frame);
    frame_diff1 = abs(frame_second - frame_first);%第二帧和第一帧做差
    frame_diff2 = abs(frame_third - frame_second);%第三帧和第二帧做差
    c3= imbinarize(max(frame_diff1,frame_diff2));%对这两个差分图像进行交集运算
   c3 = imopen(c3, strel('rectangle', [3, 3]));
   c3= imfill(c3, 'hole');
    se = strel('disk', 4);
    c3 =  imerode(c3, se);   
    se1 = strel('square', 12);
   c3= imdilate(c3, se1);
   c3=medfilt2(c3);%中值滤波
    [m,n] = size(c3);
%%


3.利用ViBe算法实现动态目标检测

ViBe算法,其原理为通过提取像素点(x, y)周围的像素值及以前的像素值建立像素点的样本集,然后再将另一帧(x,y)处的像素值与样本集中的像素值进行比较,如果其与样本集中的像素值的距离大于某阈值的话,则认为该像素点为前景像素点,否则为背景像素点。

代码如下

% --- Executes on button press in pushbutton9.
function pushbutton9_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton9 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
videoName = get(handles.edit1, 'String');
videoSource = vision.VideoFileReader(videoName,...
    'ImageColorSpace', 'RGB', 'VideoOutputDataType', 'uint8');
videoInfo = info(videoSource);

% 参数设置
sample_num = 10;                % 样本库
match_thres = 20;               % 匹配阈值
match_num = 2;                  % 最小匹配数
update_factor = 1;              % 一开始50帧内采用该更新因
next_update_factor = 5;         % 50帧以后的更新因子
cols = videoInfo.VideoSize(1);  % 图像的宽度
rows = videoInfo.VideoSize(2);  % 图像的高度
fore_thres = 20;                % 前景阈值
frame_count = 0;                % 处理帧数
neighbor = [1, 0, -1, -1, 1, 0, 0, -1, 1];  % 邻域选择
% 外部控制标记
global exit_flag;
global pause_flag;
exit_flag = false;
pause_flag = false;
% 判断是否为第一帧
first_flag = true;
while ~isDone(videoSource) && ~exit_flag
    if pause_flag
        uiwait(handles.figure1);
    end
    
    frame = step(videoSource);
    frame_gray = double(rgb2gray(frame));
    if first_flag
        first_flag = false;
        %% 开始初始化
        samples = cell(1, sample_num);
        % 前两个样本设置初始像素
        samples{1} = frame_gray;
        samples{2} = frame_gray;
        % 剩下的样本初始化
        for i = 3:sample_num
            samples{i} = frame_gray + double(floor(rand(rows, cols) * 20) - 10);
        end
        
        fore_count = uint8(zeros(rows, cols));
        frame_count = frame_count + 1
        % 初始化结束
        continue
    end
    
    %% 前景分割
    fgMask = uint8(ones(rows, cols) * match_num);
    for i = 1:sample_num
        distance = uint8(abs(samples{i} - frame_gray) <= match_thres);
        fgMask = fgMask - distance;
    end
    fgMask = logical(fgMask * 255);
    % 更新前景计数
    for r = 1 : rows
        for c = 1:cols
            if fgMask(r, c) == 1
                fore_count(r, c) = fore_count(r, c) + 1;
                if fore_count(r, c) >= fore_thres
                    fore_count(r,c) = 0;
                    fgMask(r, c) = 0;
                end
            else
                fore_count(r, c) = 0;
            end
        end
    end
    updateMask = fgMask;
    updateMask = imfill(updateMask, 'hole');
    %% 更新样本库
    % 一边更新前景计数,一边更新样本库
    for r = 2:rows-1
        for c = 2:cols-1
            % 为背景时,更新背景样本库
            if updateMask(r, c) == 0
                fore_count(r, c) = 0;
                % 有一定概率更新自身
                if update_factor == 1 || floor(rand() * update_factor) == 0
                    samples{floor(rand() * sample_num) + 1}(r, c) = frame_gray(r, c);
                end                
                % 也有一定概率更新周围像素样本库
                if update_factor == 1 || floor(rand() * update_factor) == 0
                    samples{floor(rand() * sample_num) + 1}(r + neighbor(floor(rand() * 9) + 1), ...
                        c + neighbor(floor(rand() * 9) + 1)) = frame_gray(r, c);
                end
            end
        end
    end  
    frame_count = frame_count + 1
    if frame_count >= 50
        update_factor = next_update_factor;
    end   


4.高斯混合模型法实现动态目标检测

高斯混合模型,其原理为将图像中每一个像素点的颜色值看成是一个随机过程,并假设该点的像素值出现的概率服从高斯分布。每一个像素位置建立多个高斯模型,各个模型中保存该处像素的均值和方差。若新的图片中相应位置的像素值与对应模型中像素的均值的距离小于标准差的λ倍,则该点为背景,否则为前景。

核心代码如下:

% --- Executes on button press in pushbutton8.
function pushbutton8_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton8 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
videoName = get(handles.edit1, 'String');
videoSource = vision.VideoFileReader(videoName,...
    'ImageColorSpace', 'RGB', 'VideoOutputDataType', 'uint8');
videoInfo = info(videoSource);
videoRate = videoInfo.VideoFrameRate;
waitTime = 1.0/videoRate;
global exit_flag;
global pause_flag;
exit_flag = false;
pause_flag = false;

% 参数设置
first_flag = true;
cols = videoInfo.VideoSize(1);
rows = videoInfo.VideoSize(2);
fgMask = zeros(rows, cols);     % 前景矩阵
K = 3;                          % K值为3
D = 2.5;                        % 偏差阈值
alpha = 0.01;                   % 学习速率   
Tframe = 50;                    % 帧数阈值
T = 0.8;                        % 前景阈值
sd_init = 15;                   % 初始标准差
w_init = 0.1;                   % 初始权值
ratio = w_init/sd_init;         % 自适应选择高斯分布
W = zeros(rows, cols, K);       % 权值矩阵
mean = zeros(rows, cols, K);    % 均值矩阵
sd = zeros(rows, cols, K);      % 标准差矩阵
g_num = ones(rows, cols);       % 记录每个像素的高斯分布数
u_dist = zeros(rows, cols, K);  % 新像素值与高斯分布均值的绝对值距离
frame_count = 0;                % 处理的帧数
gframe = 10;                    % 每隔几帧,删除无用高斯分布
disk1 = strel('disk', 1);       % 形态学结构元素
disk2 = strel('disk', 4);       % 形态学结构元素

while ~isDone(videoSource) && ~exit_flag
    if pause_flag
        uiwait(handles.figure1);
    end
    frame = step(videoSource);
    frame_now = double(rgb2gray(frame));
    if first_flag
        first_flag = false;
        % 初始化混合高斯模型
        w_init_m = ones(rows, cols) * 1/K;
        sd_init_m = ones(rows, cols) * sd_init;
        for i = 1:K
            % 均值设为第一帧对应位置的像素
            mean(:, :, i) = frame_now;
            W(:, :, i) = w_init_m;
            sd(:, :, i) = sd_init_m;
        end
        frame_count = frame_count + 1
        g_num = g_num .* 3;
        continue;
    end
    
    if frame_count <= Tframe
        alpha = 1/(2 * frame_count);
    end
    % 前景检测与模型更新
    for i=1:K
        u_dist(:, :, i) = abs(frame_now - mean(:, :, i));
    end
    
    % 自适应选择高斯分布标志
    adapt_flag = false;
    if mod(frame_count, gframe) == 0
        adapt_flag = true;
    end
    
    % 更新每个高斯模型的参数
    for i=1:rows
        for j=1:cols
            match_ground = false;
            match = 0;
            gnum = g_num(i, j);
            for k = 1:gnum
                % 符合,3σ原则,则像素值匹配该高斯模型
                if abs(u_dist(i, j, k)) <= D * sd(i, j, k)
                    match = 1;
                    if ~match_ground && W(i, j, k) >= 0.2
                        match_ground = true;
                    end
                    % 更新权值
                    W(i, j, k) = (1 - alpha) * W(i, j, k) + alpha;
                    p = alpha * normpdf(frame_now(i, j), mean(i, j, k), sd(i, j, k));
                    mean(i, j, k) = (1 - p) * mean(i, j, k) + p * frame_now(i, j);
                    sd(i, j, k) = sqrt((1 - p) * sd(i, j, k)^2 + p * ...
                        (mean(i, j, k) - frame_now(i, j))^2);
                else
                    % 不匹配
                    W(i, j, k) = (1 - alpha) * W(i, j, k);
                end
            end
            
            % 如果全部不匹配,替换最小权值的高斯分布或者添加新的高斯分布
            if match == 0
                if gnum == K
                    % 替换权值最小的高斯分布
                    [~, min_w_index] = min(W(i, j, :));
                    mean(i, j, min_w_index) = double(frame_now(i, j));
                    sd(i, j, min_w_index) = sd_init;
                else
                    % 添加新的高斯分布
                    gnum = gnum + 1;
                    W(i, j, gnum) = w_init;
                    mean(i, j, gnum) = double(frame_now(i, j));
                    sd(i, j, gnum) = sd_init;
                    g_num(i, j) = gnum;
                end
            end
            
            % 权值归一化
            w_sum = sum(W(i, j, :));
            W(i, j, :) = W(i, j, :) ./ w_sum;
            
            % 进行自适应选择高斯分布个数
            if adapt_flag
                rank = W(i, j, :) ./ sd(i, j, :);
                [~, rank_index] = sort(rank, 'descend');
                W_temp = W(i, j, :);
                mean_temp = mean(i, j, :);
                sd_temp = sd(i, j, :);
                udist_temp = u_dist(i, j, :);
                % 根据优先级替换相应的权值,均值和标准差
                for m = 1:gnum
                    index = rank_index(m);
                    W(i, j, m) = W_temp(index);
                    mean(i, j, m) = mean_temp(index);
                    sd(i, j, m) = sd_temp(index);
                    u_dist(i, j, m) = udist_temp(index);
                end
                % 删除无用高斯分布
                for m = gnum:-1:1
                    if W(i, j, m) < w_init && rank(rank_index(m)) < ratio
                        W(i, j, m) = 0;
                        g_num(i, j) = g_num(i, j) - 1;
                    else
                        break;
                    end
                end
                gnum = g_num(i, j);
                
                % 由于部分高斯分布可能被删除,所以需要再进行权值归一化
                w_sum = sum(W(i, j, :));
                W(i, j, :) = W(i, j, :) ./ w_sum;
            end
            
            % 已经匹配,则不需要再进行优先级排序判定
            if match_ground
                fgMask(i, j) = 0;
                continue;
            end
            
            % 优先级排序
            rank = W(i, j, :) ./ sd(i, j, :);
            [~, rank_index] = sort(rank, 'descend');
            
            fgMask(i, j) = 0;
            k = 1;
            temp_T = 0;
            while (match == 0) && (temp_T < T)
                index = rank_index(k);
                if abs(u_dist(i, j, index) <= D * sd(i, j, index))
                    fgMask(i, j) = 0;
                    break;
                else
                    temp_T = temp_T + W(i, j, index);
                    fgMask(i, j) = 255;
                end
                k = k + 1;
            end
        end
    end
        
    % 使用混合高斯背景建模
    fgMask = logical(fgMask);
    fgMask = imdilate(imerode(fgMask, disk1), disk2);
    axes(handles.axes1);
    imshow(frame);
    axes(handles.axes2);
    imshow(fgMask);
    drawnow;   
    frame_count = frame_count + 1
end
release(videoSource);

注意:本方法仅仅是目标跟踪,没有涉及到目标检测的内容,也就是说,只要是视频里面动的东西都会被追踪框起来,并且只能框一个。

完整代码获取请添加QQ 1173953942

备注目标跟踪即可

  • 13
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
基于帧差法Vibe算法实现车辆和行人检测是一种常见的计算机视觉应用。Matlab是一个强大的编程语言和工具包,提供各种算法实现,因此可以方便地实现车辆和行人检测。 使用Matlab实现差法车辆检测的流程大致如下: 1. 读取视频文件 使用Matlab提供的VideoReader函数可以读取视频文件,并获取每一帧像素信息。 2. 转换为灰度图像 将每一帧的像素信息转换为灰度图像,可以减少噪声的影响,并提高检测性能。可以使用Matlab中的rgb2gray函数实现。 3. 进行帧差运算 将当前帧与前一帧进行帧差运算,得到前后两帧之间的像素差值,也就是帧差图像。可以使用Matlab中的imabsdiff函数实现。 4. 二值化图像 将帧差图像进行二值化处理,可以得到前后两帧之间差异处的像素点。根据车辆的颜色和形状等特征,可以排除大部分不是车辆的像素点。常用的二值化方包括Sobel算子、Robert算子等。可以使用Matlab中的im2bw函数实现。 5. 车辆检测 对二值化图像进行一系列形态学操作,如腐蚀、膨胀、开、闭操作等,可以得到车辆区域。可以使用Matlab中的strel函数实现。对车辆区域进行分析,可以得到车辆的轮廓和中心点等信息。 基于Vibe算法实现行人检测的流程类似于帧差法,但是不同之处在于Vibe算法主要使用局部样本更新和背景模型更新来实现目标检测。具体实现细节可以参考相关文献和Matlab示例代码。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值