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

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

先上效果图:

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

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

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

实现流程

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

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

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

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

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

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

对差分后的图像进行二值化处理并中值滤波去噪处理后,将其叠加在原图像上
数字图像处理拓展题目——利用Matlab实现动态目标检测 二帧差法、ViBe法、高斯混合模型法,可应用于学生递东西行为检测_第7张图片

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

对差分后的图像填充图形区域和空洞,并进行中值滤波实现图形的去噪,利用形态学知识,对图像进行腐蚀和膨胀,实现进一步去噪和细化图形中的目标
数字图像处理拓展题目——利用Matlab实现动态目标检测 二帧差法、ViBe法、高斯混合模型法,可应用于学生递东西行为检测_第8张图片

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

对图形的每一行进行行扫描,找出每一行白色区域的临界端点,并将中间的区域填充为白色,实现目标的区域填充
数字图像处理拓展题目——利用Matlab实现动态目标检测 二帧差法、ViBe法、高斯混合模型法,可应用于学生递东西行为检测_第9张图片
数字图像处理拓展题目——利用Matlab实现动态目标检测 二帧差法、ViBe法、高斯混合模型法,可应用于学生递东西行为检测_第10张图片

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

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

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

备注目标跟踪即可

你可能感兴趣的:(数字图像处理,算法,opencv,计算机视觉)