本节主要介绍了FPGA图像处理中常用的图像二值化算法,包括全局阈值二值化算法、局部阈值二值化算法、Sobel边缘检测算法、二值化腐蚀膨胀算法、帧间差及运动检测算法,以及它们的MATLAB与FPGA实现。
图像二值化的目的
- 图像二值化是后续图像处理的基础, 首先从彩色或者灰度图像上, 获得二值化图像, 然后在后续的图像算法中进行进一步的处理分析。 因此, 图像二值化提取的质量, 很大程度上决定了后续算法的效果与性能
- 图像二值化算法是后续各种算法的基础。 一个优秀的图像二值化算法, 能极大程度地降低后续算法的处理难度, 也能提高检测的准确率。
全局阈值二值化算法
顾名思义, 针对的是整幅图像, 采用一个统一的阈值, 对明暗一致性较好的图像, 选择合适的阈值可以得到不错的效果, 其算法实现相对也比较简单(OTSU寻找最优阈值比较复杂, 如果是固定的阈值, 则非常简单)
图像的像素值是8bit, 0表示黑色, 255表示白色, 那么128就是我们的中点——中性灰。 如果图像均匀分布在0~255像素值, 那么采用128阈值能获得预期的二值化图像。整体偏暗或者偏亮的图像, 采用中值直接进行阈值分割效果很糟糕。
阈值与图像整体亮度相关,那么用均值作为阈值时:对于一致性较好的松鼠测试图, 采用均值作为阈值的效果不理想; 对于整体偏暗的冈萨雷斯测试图, 效果有很大改善
图像全局阈值二值化的核心就是阈值的计算 。采用128阈值不具有通用性, 受图像整体亮度的影响较大, 尝试采用均值作为阈值计算, 效果仍然不够理想。
可采用业内较为出名的OTSU(大津法) 提取阈值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20clear all; close all; clc;
% -------------------------------------------------------------------------
% Read PC image to Matlab
IMG1 = imread('../../0_images/Scart.jpg'); % 读取jpg图像
IMG1 = rgb2gray(IMG1);
% IMG1 = imread('../../0_images/gsls_test1.tif');
h = size(IMG1,1); % 读取图像高度
w = size(IMG1,2); % 读取图像宽度
subplot(131);imshow(IMG1);title('【1】原图');
% -------------------------------------------------------------------------
IMG2 = global_bin_user(IMG1,128);
subplot(132);imshow(IMG2);title('【2】Global二值化-128');
% -------------------------------------------------------------------------
thresh = floor(graythresh(IMG1)*256);
IMG3 = global_bin_user(IMG1, thresh);
subplot(133);imshow(IMG3);title('【3】Global二值化-OTSU');由于FPGA的流水线特性, 我们通常采用流水线(pipeline) 的方式进行加速。 而OTSU不仅需要提前计算得到直方图的概率分布, 还需要继续进行256次迭代计算类间方差 g , 并且每次迭代还涉及256个概率数据的浮点乘法(计算u0、 u1) , 其计算量非常大, 不适合采用FPGA进行加速。
局部阈值二值化算法
为了对黑色像素进行二值化, 我们需要知道黑色像素邻域的阈值。 假设采用5×5邻域块计算窗口内像素的阈值, 根据阈值对黑色像素进行二值化。
如何计算窗口内像素的阈值, 便成了局部阈值二值化的核心,引入一个参数, 适当对阈值进行缩小
1.局部阈值二值化的MATLAB实现
将数值累加后计算均值, 再乘以一个缩小的参数, 得到最后n*n窗口内的阈值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31% 灰度图像布局自动二值化实现
% IMG为输入的灰度图像
% n为求阈值的窗口大小,为奇数
% p为阈值的缩放
function Q=region_bin_auto(IMG,n,p)
[h,w] = size(IMG);
Q = zeros(h,w);
win = zeros(n,n);
bar = waitbar(0,'Speed of auto region binarization process...'); %创建进度条
for i=1 : h
for j=1:w
if(i<(n-1)/2+1 || i>h-(n-1)/2 || j<(n-1)/2+1 || j>w-(n-1)/2)
Q(i,j) = 255; %边缘像素不计算,直接赋255
else
win = IMG(i-(n-1)/2:i+(n-1)/2, j-(n-1)/2:j+(n-1)/2); %n*n窗口的矩阵
thresh = floor( sum(sum(win))/(n*n) * p);
% thresh = floor(sum(win,'all')/(n*n) * p);
if(win((n-1)/2+1,(n-1)/2+1) < thresh)
Q(i,j) = 0;
else
Q(i,j) = 255;
end
end
end
waitbar(i/h);
end
close(bar); % Close waitbar.
Q=uint8(Q);
2.局部阈值二值化的FPGA实现
局部阈值二值化计算分为以下几个步骤
计算$5\times 5$窗口中每行5个像素的累加和
$$
data_sum1=matrix_p11+matrix_p12+matrix_p13+matrix_p14+matrix_p15\
data_sum2=matrix_p21+matrix_p22+matrix_p23+matrix_p24+matrix_p25\
data_sum3=matrix_p31+matrix_p32+matrix_p33+matrix_p34+matrix_p35\
data_sum4=matrix_p41+matrix_p42+matrix_p43+matrix_p44+matrix_p45\
data_sum5=matrix_p51+matrix_p52+matrix_p53+matrix_p54+matrix_p55\
$$计算$5\times 5$窗口中所有25个像素的累加和
$$
data_sum=data_sum1+data_sum2+data_sum3+data_sum4+data_sum5
$$计算$5\times 5$窗口内的像素均值,乘以系数0.9后取整作为二值化阈值
$$
thresh = floor(\frac{data_sum}{25}\times 0.9)
$$$$
thresh = floor[data_sum\times round(\frac{0.9}{25}\times 2^{24})]=floor(data_sum\times 603980 >> 24)
$$当data_sum∈ [0, 255×5] 时, 两个公式是等价的,$mult_result = data_sum\times 603980$,$mult_result[31:24]$为整数部分、$mult_result[23:0]$为小数部分,对$mult_result$取整得到二值化阈值,即$thresh = mult_result[31:24]$
将$5\times 5$窗口中心像素matrix_p33与thresh比较。 如果matrix_p33小于thresh, 则输出0作为二值化阈值的结果, 否则输出255作为二值化阈值的结果
此外, 还需要判断5×5窗口的中心像素是否位于图像边界, 即中心像素是否处于图像上边界两行、 下边界两行、 左边界两列、 右边界两列的范围。 如果中心像素位于图像边界, 则输出255作为二值化阈值的结果。
仿真结果:
Sobel边缘检测算法
二值化算法主要对图像在一定区域内的灰度阈值进行分割, 而边缘检测算法则更关注图像的边缘细节
Sobel边缘检测算子(简称Sobel算子) 、 Robert边缘检测算子(简称Robert算子) 等为典型的一阶微分算子, 能够较好地捕捉图像灰度变化的边缘。
3×3窗口的Sobel边缘检测2个方向的算子( I 为原图) :
$$
G_x = \begin{bmatrix}
-1 & 0 & 1\
-2 & 0 & 2\
-1 & 0 & 1\
\end{bmatrix}\times I\quad
G_y = \begin{bmatrix}
-1 & -2 & -1\
0 & 0 &0\
1 & 2 & 1\
\end{bmatrix}\times I
\
G = \sqrt{G_x^2 + G_y^2}
$$- 其中的$\times$代表点乘后再相加
计算得到梯度数据后,与设定的梯度阈值做比较,决定当前像素是否按照轮廓处理,如果G大于阈值,则为边缘,反之,则丢弃
1.Sobel边缘检测的MATLAB实现
MATLAB代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39function Q=sobel_detector(IMG,thresh)
[h,w] = size(IMG);
Q = ones(h,w);
% -------------------------------------------------------------------------
% Gx Gy Pixel
% [ -1 0 +1 ] [ -1 -2 -1 ] [ P1 P2 P3 ]
% [ -2 0 +2 ] [ 0 0 0 ] [ P4 P5 P6 ]
% [ -1 0 +1 ] [ +1 +2 +1 ] [ P7 P8 P9 ]
Sobel_X = [-1, 0, 1, -2, 0, 2, -1, 0, 1]; % Weight x
Sobel_Y = [-1,-2,-1, 0, 0, 0, 1, 2, 1]; % Weight y
IMG_Gray = double(IMG);
IMG_Sobel = ones(h,w);
n=3;
for i=1 : h
for j=1:w
if(i<(n-1)/2+1 || i>h-(n-1)/2 || j<(n-1)/2+1 || j>w-(n-1)/2)
IMG_Sobel(i,j) = 0; %边缘像素不处理
else
temp1 = Sobel_X(1) * IMG_Gray(i-1,j-1) + Sobel_X(2) * IMG_Gray(i-1,j) + Sobel_X(3) * IMG_Gray(i-1,j+1) +...
Sobel_X(4) * IMG_Gray(i,j-1) + Sobel_X(5) * IMG_Gray(i,j) + Sobel_X(6) * IMG_Gray(i,j+1) +...
Sobel_X(7) * IMG_Gray(i+1,j-1) + Sobel_X(8) * IMG_Gray(i+1,j) + Sobel_X(9) * IMG_Gray(i+1,j+1);
temp2 = Sobel_Y(1) * IMG_Gray(i-1,j-1) + Sobel_Y(2) * IMG_Gray(i-1,j) + Sobel_Y(3) * IMG_Gray(i-1,j+1) +...
Sobel_Y(4) * IMG_Gray(i,j-1) + Sobel_Y(5) * IMG_Gray(i,j) + Sobel_Y(6) * IMG_Gray(i,j+1) +...
Sobel_Y(7) * IMG_Gray(i+1,j-1) + Sobel_Y(8) * IMG_Gray(i+1,j) + Sobel_Y(9) * IMG_Gray(i+1,j+1);
temp3 = sqrt(temp1^2 + temp2^2);
if(uint8(temp3) > thresh)
IMG_Sobel(i,j) = 1;
else
IMG_Sobel(i,j) = 0;
end
end
end
end
Q=IMG_Sobel;Sobel边缘检测效果的好坏, 不仅取决于两个方向的3×3窗口的算子, 还跟阈值的大小有一定的关系。如果阈值设定越小(64) , 则越容易引起脏点, 但是边缘相对保持较粗; 反之, 如果阈值设定越大(96) , 则能屏蔽一些梯度较小的点, 但边缘相应会变得更细。
2.Sobel边缘检测的FPGA实现
Sobel边缘检测计算分解为以下几步
分别计算水平方向梯度$Gx_data$和垂直防线梯度$Gy_data$
将水平方向梯度$Gx_data$和垂直方向梯度$Gy_data$合并并取模得到最终的梯度$G_data$
$$
G_data = \sqrt{Gx_data^2 + Gy_data^2}
$$将梯度$G_data$与$thresh$进行比较,如果$G_data$大于$thresh$,则输出1作为Sobel边缘检测的结果,否则输出0作为Sobel边缘检测的结果
还需判断$3\times 3$窗口的中心像素是否位于图像边界。如果位于图像边界,则输出0作为Sobel边缘检测的结果
仿真结果
二值化腐蚀、膨胀算法
腐蚀是指在周围介质作用下产生损耗与破坏的过程, 如生锈、 腐烂等。 而腐蚀算法也类似是一种能够产生损坏, 抹去部分像素的算法
膨胀指当物体受热使粒子运动速度加快, 从而占据了额外空间的过程, 如面包的发酵过程。 而膨胀算法也类似是一种能够扩大有效数据, 补全部分像素的算法
所以这两个算法, 一个能够消除部分像素; 另一个则是能够补全部分像素
腐蚀算法计算公式:
$$
P=P1 ,,& ,,P2 ,,& ,,P3 ,,& ,,P4 ,,&,, P5 ,,&,, P6 ,,&,, P7 ,,&,, P8 ,,&,, P9
$$膨胀算法计算公式:
$$
P=P1 ,,| ,,P2 ,,| ,,P3 ,,| ,,P4 ,,|,, P5 ,,|,, P6 ,,|,, P7 ,,|,, P8 ,,|,, P9
$$腐蚀算法和膨胀算法是二值化、 边缘检测算法后的二次优化操作, 两者结合具有能够腐蚀脏点, 又保留重要像素的作用
基本的腐蚀与膨胀算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63clear all; close all; clc;
% -------------------------------------------------------------------------
% Read PC image to Matlab
IMG1 = imread('../../0_images/shade_text2_bin.tif');
% IMG1 = imread('../../0_images/gsls_rice.tif');
h = size(IMG1,1); % 读取图像高度
w = size(IMG1,2); % 读取图像宽度
IMG1 = ~im2bw(IMG1,0.5);%首先将输入的 图像转成了二值化图像 (tif本身为8bit图像) ; 然后为了匹配腐蚀、 膨胀算法中1表示有效, 0表示无效的做法, 将原先的结果取反
subplot(131);imshow(IMG1);title('【1】原图');
% -------------------------------------------------------------------------
IMG2 = bin_erosion(IMG1);
subplot(132);imshow(IMG2);title('【2】3*3腐蚀运算');
% -------------------------------------------------------------------------
IMG3 = bin_dilation(IMG2);
subplot(133);imshow(IMG3);title('【3】3*3膨胀运算');
% -------------------------------腐蚀函数---------------------------------
function Q=bin_erosion(IMG)
[h,w] = size(IMG);
IMG_Erosion = ones(h,w);
% -------------------------------------------------------------------------
n=3;
for i=1:h
for j=1:w
if(i<(n-1)/2+1 || i>h-(n-1)/2 || j<(n-1)/2+1 || j>w-(n-1)/2)
IMG_Erosion(i,j) = 0; %边缘像素不处理
else
IMG_Erosion(i,j) = IMG(i-1,j-1) & IMG(i-1,j) & IMG(i-1,j+1) &...
IMG(i,j-1) & IMG(i,j) & IMG(i,j+1) &...
IMG(i+1,j-1) & IMG(i+1,j) & IMG(i+1,j+1);
end
end
end
Q = IMG_Erosion;
% -------------------------------膨胀函数---------------------------------
function Q=bin_dialtion(IMG)
[h,w] = size(IMG);
IMG_Dilation = ones(h,w);
% -------------------------------------------------------------------------
n=3;
for i=1 : h
for j=1:w
if(i<(n-1)/2+1 || i>h-(n-1)/2 || j<(n-1)/2+1 || j>w-(n-1)/2)
IMG_Dilation(i,j) = 0; %边缘像素不处理
else
IMG_Dilation(i,j) = IMG(i-1,j-1) | IMG(i-1,j) | IMG(i-1,j+1) |...
IMG(i,j-1) | IMG(i,j) | IMG(i,j+1) |...
IMG(i+1,j-1) | IMG(i+1,j) | IMG(i+1,j+1);
end
end
end
Q = IMG_Dilation;
1.二值化腐蚀膨胀的MATLAB实现
在腐蚀算法中,只要3×3窗口内有1个0,则其结果为0;膨胀算法也是如此,只要3×3窗口内有1个1,则其结果为1,这样会造成过度的腐蚀、膨胀,从而引起人为的异常。
如果考虑1个强度,则应该是当窗口中有 n 个1的时候,结果才为1,否则就为0。这样不仅可以调节腐蚀算法、膨胀算法的强度,同时两个运算也可以通过1个阈值的比较,合二为一。
matlab代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26function Q=bin_compare(IMG, thresh)
%thresh 为1的个数
[h,w] = size(IMG);
IMG_Comp = ones(h,w);
% -------------------------------------------------------------------------
n=3;
for i=1:h
for j=1:w
if(i<(n-1)/2+1 || i>h-(n-1)/2 || j<(n-1)/2+1 || j>w-(n-1)/2)
IMG_Comp(i,j) = 0; %边缘像素不处理
else
temp = IMG(i-1,j-1) + IMG(i-1,j) + IMG(i-1,j+1) +...
IMG(i,j-1) + IMG(i,j) + IMG(i,j+1) +...
IMG(i+1,j-1) + IMG(i+1,j) + IMG(i+1,j+1);
if(temp >= thresh )
IMG_Comp(i,j) = 1;
else
IMG_Comp(i,j) = 0;
end
end
end
end
Q = IMG_Comp;当阈值等于9时, 只有3×3窗口内所有像素都为1, 结果才为1, 这是独立 腐蚀算法 ; 当阈值等于1时, 只要3×3窗口内有1个像素为1, 其结果就为1, 这是独立 膨胀算法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19clear all; close all; clc;
% -------------------------------------------------------------------------
% Read PC image to Matlab
IMG1 = imread('../../0_images/shade_text2_bin.tif');
% IMG1 = imread('../../0_images/gsls_rice.tif');
h = size(IMG1,1); % 读取图像高度
w = size(IMG1,2); % 读取图像宽度
IMG1 = ~im2bw(IMG1,0.5);
subplot(131);imshow(IMG1);title('【1】原图');
% -------------------------------------------------------------------------
IMG2 = bin_compare(IMG1,9);
subplot(132);imshow(IMG2);title('【2】阈值9比较');
% -------------------------------------------------------------------------
IMG3 = bin_compare(IMG2,1);%%%先腐蚀后膨胀
subplot(133);imshow(IMG3);title('【3】阈值1比较');如果我们稍加调节阈值参数, 在进行腐蚀运算的时候, 窗口内像素少于6个1就全部腐蚀掉; 在进行膨胀运算的时候, 窗口内多于3个1就膨胀为1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19clear all; close all; clc;
% -------------------------------------------------------------------------
% Read PC image to Matlab
IMG1 = imread('../../0_images/shade_text2_bin.tif');
% IMG1 = imread('../../0_images/gsls_rice.tif');
h = size(IMG1,1); % 读取图像高度
w = size(IMG1,2); % 读取图像宽度
IMG1 = ~im2bw(IMG1,0.5);
subplot(131);imshow(IMG1);title('【1】原图');
% -------------------------------------------------------------------------
IMG2 = bin_compare(IMG1,6);
subplot(132);imshow(IMG2);title('【2】阈值6比较');
% -------------------------------------------------------------------------
IMG3 = bin_compare(IMG2,3);%%%先腐蚀后膨胀
subplot(133);imshow(IMG3);title('【3】阈值3比较');相比独立腐蚀、 膨胀算法, 采用1个数阈值比较算法的方法, 实现更灵活, 在效果上,也更多地保持了原图的边缘, 防止了像素丢失。
2.二值化腐蚀膨胀的FPGA实现
腐蚀膨胀的运算过程可以分为以下几步:
计算$3\times 3$窗口中每行3个像素的累加和
$$
data_sum1=matrix_p11+matrix_p12+matrix_p13\
data_sum2=matrix_p21+matrix_p22+matrix_p23\
data_sum3=matrix_p31+matrix_p32+matrix_p33
$$计算$3\times 3$窗口中所有9个像素的累加和
$$
data_sum=data_sum1+data_sum2+data_sum3
$$将$data_sum$与$thresh$进行比较。如果$data_sum$大于等于$thresh$,则输出1作为腐蚀/膨胀算法的结果,否则输出0作为腐蚀/膨胀算法的结果
还需判断$3\times 3$窗口的中心像素是否位于图像边界,如果位于图像边界,则输出0作为腐蚀/膨胀算法的结果
仿真结构:(先腐蚀后膨胀)
仿真结果:
帧间差算法及运动检测算法
运动目标检测的方法有很多种, 根据背景是否复杂、 摄像机是否运动等因素进行选择, 相关算法之间也有很大的差别。 其中最常用的三类算法是帧间差算法、 背景减算法、 光流场算法。
帧间差算法是对时间上连续的两帧或三帧图像进行差分运算,将不同帧对应的像素点一一相减,得到灰度差的绝对值,当灰度差的绝对值超过一定阈值时, 即可判断为运动目标, 从而实现目标的检测功能
简单的基于两帧的帧间差算法matlab实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19clear all; close all; clc;
% -------------------------------------------------------------------------
% Read PC image to Matlab
frame1 = imread('../../0_images/nezha1.jpg'); % 读取jpg图像
frame2 = imread('../../0_images/nezha2.jpg'); % 读取jpg图像
subplot(221);imshow(frame1);title('前一帧');
subplot(222);imshow(frame2);title('当前帧');
%双帧间差
frame1 = rgb2gray(frame1);
frame2 = rgb2gray(frame2);
frame_diff = abs(frame1-frame2);
subplot(223);imshow(frame_diff);title('差值帧');
%阈值处理
frame_2dim = global_bin_user(frame_diff, 32);
subplot(224);imshow(frame_2dim);;title('阈值32处理');基于帧间差法的目标检测方法:
- 对两帧的灰度差进行二值化处理
- 块内像素统计:以$80\times 80$图像为例,统计块内的运动像素个数(直接将块内的二值化图像累加起来即可)
- 块内阈值滤波:舍弃运动像素过少的块,消除干扰(设定一个块内阈值,小于这个阈值的块就置为0)
- 运动目标边界检索:根据运动块的位置,计算运动目标的边界,在原图中画框(从左到右搜索非0值寻找左边界, 相应地通过从右到左、 从上到下、 从下到上搜索右边界、 上边界、 下边界, MATLAB采用while() 循环实现)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111clear all; close all; clc;
DIFF_THRESH = 20; %帧间差的阈值
BLOCK_THRESH = 32; %有效块的阈值
% -------------------------------------------------------------------------
% Read PC image to Matlab
frame1 = imread('../../0_images/nezha1.jpg'); % 读取jpg图像
frame2 = imread('../../0_images/nezha2.jpg'); % 读取jpg图像
% subplot(221);imshow(frame1);title('前一帧');
subplot(221);imshow(frame2);title('当前帧');
%双帧间差
frame1 = rgb2gray(frame1);
frame2 = rgb2gray(frame2);
frame_diff = abs(frame1-frame2);
subplot(222);imshow(frame_diff);title('差分帧');
%阈值处理
frame_2dim = global_bin_user(frame_diff, DIFF_THRESH);
% subplot(223);imshow(frame_2dim);;title('阈值处理');
% -------------------------------------------------------------------------
% 在帧间差图上叠加80*80的框
grid_image = frame_2dim;
dim = size(grid_image); %读取图像高度、宽度
for i=1:dim(1)
for j=1:dim(2)
if((mod(i,80) == 0) || (mod(j,80) == 0))
grid_image(i,j,:) =255;
% else
% frame2(i,j,:) = frame1(i,j,:);
end
end
end
imwrite(grid_image,'grid_image.jpg');
figure;imshow(grid_image);title('阈值处理');
% -------------------------------------------------------------------------
% 1)统计80*80块内有效运动像素数量
[h,w] = size(frame_2dim);
sum_block =zeros(ceil(h/80), ceil(w/80));
for i=1:h
for j=1:w
sum_block(ceil(i/80), ceil(j/80)) = sum_block(ceil(i/80), ceil(j/80)) + uint16(frame_2dim(i,j)/255);
end
end
% -------------------------------------------------------------------------
% 2)去除运动较少的块
for i=1:ceil(h/80)
for j=1:ceil(w/80)
if(sum_block(i,j) < BLOCK_THRESH)
sum_block(i,j) = 0;
else
sum_block(i,j) = sum_block(i,j);
end
end
end
% -------------------------------------------------------------------------
% 3)获取目标的上下左右边界
% by_start坐标搜索
i=1;
while(sum_block(i,:) == 0)
i=i+1;end
by_start = i;
% by_end坐标搜索
i=ceil(h/80);
while(sum_block(i,:) == 0)
i=i-1;end
by_end = i;
% bx_start坐标搜索
j=1;
while(sum_block(:,j) == 0)
j=j+1;end
bx_start = j;
% bx_end坐标搜索
j=ceil(w/80);
while(sum_block(:,j) == 0)
j=j-1;end
bx_end = j;
% -------------------------------------------------------------------------
%原图运动目标边界计算
if(by_start == 1)
py_start = 1;
else
py_start = (by_start - 1)*80;
end
py_end = (by_end - 0)*80;
if(bx_start == 1)
px_start =1;
else
px_start = (bx_start - 1)*80;
end
px_end = (bx_end - 0)*80;
% -------------------------------------------------------------------------
% 原图中画运动目标的边界框
frame2(py_start:py_end, px_start,:) = 255;
frame2(py_start:py_end, px_end,:) = 255;
frame2(py_start, px_start:px_end,:) = 255;
frame2(py_end, px_start:px_end,:) = 255;
figure;imshow(frame2);title('阈值处理');
imwrite(frame2,'frame2_motion.jpg');帧间差二值化后的块划分
运动目标检测结果
Reference
- 《基于MATLAB与FPGA的图像处理教程》图书及其配套资料
- 数字图像处理(13): 形态学处理——图像开运算与图像闭运算-CSDN博客
- 开运算:先腐蚀后膨胀
- 闭运算:先膨胀后腐蚀