【答题卡识别】基于hough变换答题卡判定与成绩统计含Matlab源码
【答题卡识别】基于hough变换答题卡判定与成绩统计含Matlab源码
TT_Matlab
博主简介:擅长智能优化算法、神经网络预测、信号处理、元胞自动机、图像处理、路径规划、无人机等多种领域的Matlab仿真,完整matlab代码或者程序定制加qq1575304183。
1 简介
本文实现一个基于 MATLAB的答题卡识别。MATLAB是一款商业数学软件,可用于科学计算和工程绘图,具有相应的功能函数,可以对图像进行标注和打印,还可以对指定的图像处理光照、色度等。而基于M ATLAB 的答题卡处理,首先,对答题卡进行归一化、平滑处理、灰度化、二值化的预处理,再运用 M ATALB 中的 Hough变换函数对答题卡进行直线检测,对答题卡直线定位,以便后续对答题卡进行矫正、滤波、分割区域、画网格线、标记,最后再通过一个图形用户界面显示答题卡上的填涂选项和答题卡分数。
2 部分代码
function [score,I4,I5] = SimplePaper_Inspection( filename)
%输入参数:
%filenames——包含需要判定的答题卡文件名
%读取图像
I = imread(filename);
%预处理
I1 = Image_Normalize(I,
1
);
%平滑处理,模板尺寸[
3
3
],sigma角
0
.
5
,平滑方式:高斯滤波
hsize = [
3
3
];
sigma =
0
.
5
;
I2 = Image_Smooth(I1, hsize, sigma,
1
);
%灰度化
I3 = Gray_Convert(I2,
1
);
%二值化
bw2 = Image_Binary(I3,
1
);
%hough变换
[~, ~, xy_long] = Hough_Process(bw2, I1,
1
);
%变换斜率
angle = Compute_Angle(xy_long);
%图像旋转
[I4, bw3] = Image_Rotate(I1, bw2, angle*
1.8
,
1
);
%形态学滤波
[bw4, Loc1] = Morph_Process(bw3,
1
);
%hough检测区域分界线
[Len, XYn, xy_long] = Hough_Process(bw4, I4,
1
);
%区域分割
[bw5, bw6] = Region_Segmation(XYn, bw4, I4,
1
);
%区域标记
[stats1, stats2, Line] = Location_Label(bw5, bw6, I4, XYn, Loc1,
1
);
%区域分析
[Dom, Aom, Answer, Bn] = Analysis(stats1, stats2, Line, I4);
savefigure12img(
’t.jpg’
);
I5=imread(
’t.jpg’
);
%成绩判定
score=jieguo(bw5);
fprintf(
’选择题得分为%d’
,score);%在command窗口输出成
%将答题卡图片转存到results文件夹
Write_Results();
function I1 = Image_Normalize(I, flag)
if
nargin <
2
flag =
1
;
end
if
size(I,
1
) >
2000
I = imresize(I,
0
.
2
,
’bilinear’
);
end
I1 = imadjust(I, [
0
0
.
6
], [
0
1
]);
if
flag
figure(
1
);
subplot(
2
,
1
,
1
); imshow(I, []); title(
’原图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
1
,
2
); imshow(I1, []); title(
’归一化图像’
,
’FontWeight’
,
’Bold’
);
end
end
function I2 = Image_Smooth(I1, hsize, sigma, flag)
if
nargin <
4
flag =
1
;
end
if
nargin <
2
hsize = [
3
3
];
sigma =
0
.
5
;
end
h = fspecial(
’gaussian’
, hsize, sigma);
I2 = imfilter(I1, h,
’replicate’
);
if
flag
figure(
2
);
subplot(
2
,
1
,
1
); imshow(I1, []); title(
’平滑前图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
1
,
2
); imshow(I2, []); title(
’平滑后图像’
,
’FontWeight’
,
’Bold’
);
end
end
function I1 = Gray_Convert(I, flag)
if
nargin <
2
flag =
1
;
end
if
ndims(I) ==
3
I1 = rgb2gray(I);
else
I1 = I;
end
if
flag
figure(
3
);
subplot(
2
,
1
,
1
); imshow(I, []); title(
’RGB图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
1
,
2
); imshow(I1, []); title(
’灰度图像’
,
’FontWeight’
,
’Bold’
);
end
end
function bw2 = Image_Binary(I, flag)
if
nargin <
2
flag =
1
;
end
bw1 = imbinarize(I, graythresh(I));
bw2 = ~bw1;
if
flag
figure(
4
);
subplot(
1
,
3
,
1
); imshow(I, []); title(
’待处理图像’
,
’FontWeight’
,
’Bold’
);
subplot(
1
,
3
,
2
); imshow(bw1, []); title(
’二值化图像’
,
’FontWeight’
,
’Bold’
);
subplot(
1
,
3
,
3
); imshow(bw2, []); title(
’二值化反色图像’
,
’FontWeight’
,
’Bold’
);
end
end
function [Len, XYn, xy_long] = Hough_Process(bw, Img, flag)
if
nargin <
3
flag =
1
;
end
[H, T, R] = hough(bw);
P = houghpeaks(H,
4
,
’threshold’
, ceil(
0
.
3
*max(H(
:
))));
lines = houghlines(bw, T, R, P,
’FillGap’
,
50
,
’MinLength’
,
7
);
max_len =
0
;
for
k =
1
: length(lines)
xy = [lines(k).point1; lines(k).point2];
len = norm(lines(k).point1-lines(k).point2);
Len(k) = len;
if
len > max_len
max_len = len;
xy_long = xy;
end
XY{k} = xy; % 存储信息
end
[Len, ind] = sort(Len(
:
),
’descend’
); % 按长度排序
% 直线信息排序
for
i =
1
: length(ind)
XYn{i} = XY{ind(i)};
end
xy_long = XYn{
1
};
x = xy_long(
:
,
1
);
y = xy_long(
:
,
2
);
if
abs(diff(x)) < abs(diff(y))
x = [mean(x); mean(x)];
else
y = [
0
.
7
*y(
1
)+
0
.
3
*y(
2
);
0
.
3
*y(
1
)+
0
.
7
*y(
2
)];
end
xy_long = [x y];
if
flag
figure(
5
);
subplot(
1
,
2
,
1
); imshow(bw); title(
’二值图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
2
,
2
); imshow(H, [],
’XData’
, T,
’YData’
, R,
’InitialMagnification’
,
’fit’
);
xlabel(
’ heta’
); ylabel(
’ho’
);
axis on; axis normal; title(
’霍夫变换域’
,
’FontWeight’
,
’Bold’
)
figure(
6
);
subplot(
1
,
2
,
1
); imshow(Img); title(
’原图像’
,
’FontWeight’
,
’Bold’
);
subplot(
1
,
2
,
2
); imshow(Img); title(
’区域标识图像’
,
’FontWeight’
,
’Bold’
);
hold on;
plot(xy_long(
:
,
1
), xy_long(
:
,
2
),
’LineWidth’
,
2
,
’Color’
,
’r’
);
end
end
function angle = Compute_Angle(xy_long)
x1 = xy_long(
:
,
1
);
y1 = xy_long(
:
,
2
);
K1 = -(y1(
2
)-y1(
1
))/(x1(
2
)-x1(
1
));
angle = atan(K1)*
180
/pi;
end
function [I1, bw1] = Image_Rotate(I, bw, angle, flag)
if
nargin <
4
flag =
1
;
end
I1 = imrotate(I, -
90
-angle,
’bilinear’
);
bw1 = imrotate(bw, -
90
-angle,
’bilinear’
);
if
flag
figure(
7
);
subplot(
2
,
2
,
1
); imshow(I, []); title(
’原图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
2
,
3
); imshow(bw, []); title(
’原二值图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
2
,
2
); imshow(I1, []); title(
’校正图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
2
,
4
); imshow(bw1, []); title(
’校正二值图像’
,
’FontWeight’
,
’Bold’
);
end
end
function [bw2, Loc] = Morph_Process(bw1, flag)
if
nargin <
2
flag =
1
;
end
bw2 = bwareaopen(bw1, round(
0
.
005
*numel(bw1)/
100
));
bws = sum(bw2);
inds = find(bws>round(sum(bw2(
:
))*
0
.
015
));
Loc = inds(
1
)-
5
;
bw2(
:
,
Loc:
end
) =
0
;
bw2 = bwareaopen(bw2, round(
0
.
005
*numel(bw1)/
100
));
if
flag
figure(
8
);
subplot(
1
,
2
,
1
); imshow(bw1, []); title(
’待操作图像’
,
’FontWeight’
,
’Bold’
);
subplot(
1
,
2
,
2
); imshow(bw2, []); title(
’滤波图像’
,
’FontWeight’
,
’Bold’
);
end
end
function [bw1, bw2] = Region_Segmation(XY, bw, Img, flag)
if
nargin <
4
flag =
1
;
end
for
i =
1
:
2
xy = XY{i};
XY{i} = [
1
xy(
1
,
2
); size(bw,
2
) xy(
2
,
2
)];
ri(i) = round(mean([xy(
1
,
2
) xy(
2
,
2
)]));
end
minr = min(ri);
maxr = max(ri);
bw1 = bw; bw2 = bw;
bw1(
1
:minr+
5
,
:
) =
0
;
bw1(maxr-
5
:end
,
:
) =
0
;
bw2(minr-
5
:end
,
:
) =
0
;
bw2(
1
:round
(minr*
0
.
5
),
:
) =
0
;
if
flag
figure(
9
);
subplot(
2
,
2
,
1
); imshow(Img, []); title(
’原图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
2
,
2
); imshow(bw, []); title(
’原二值图像’
,
’FontWeight’
,
’Bold’
);
hold on;
for
i =
1
:
2
xy = XY{i};
plot(xy(
:
,
1
), xy(
:
,
2
),
’r-’
,
’LineWidth’
,
2
);
end
hold off;
subplot(
2
,
2
,
3
); imshow(bw1, []); title(
’下区域图像’
,
’FontWeight’
,
’Bold’
);
subplot(
2
,
2
,
4
); imshow(bw2, []); title(
’上区域图像’
,
’FontWeight’
,
’Bold’
);
end
end
function [stats1, stats2, Line] = Location_Label(bw1, bw2, Img, XYn, Loc1, flag)
if
nargin <
6
flag =
1
;
end
[L1, num1] = bwlabel(bw1);
stats1 = regionprops(L1);
[L2, num2] = bwlabel(bw2);
stats2 = regionprops(L2);
Line1 = XYn{
1
};
Line2 = XYn{
2
};
if
mean(Line2(
:
,
2
)) < mean(Line1(
:
,
2
))
Line1 = XYn{
2
};
Line2 = XYn{
1
};
end
[r1, c1] = find(bw1);
[r2, c2] = find(bw2);
Loc2 = min([min(c1), min(c2)])-
5
;
Line1 = [
1
mean(Line1(
:
,
2
)); size(Img,
2
) mean(Line1(
:
,
2
))];
Line2 = [
1
mean(Line2(
:
,
2
)); size(Img,
2
) mean(Line2(
:
,
2
))];
Line3 = [Loc2
1
; Loc2 size(Img,
1
)];
Line4 = [Loc1
1
; Loc1 size(Img,
1
)];
Line{
1
} = Line1;
Line{
2
} = Line2;
Line{
3
} = Line3;
Line{
4
} = Line4;
if
flag
figure(
10
);
imshow(Img, []); title(
’标记图像’
,
’FontWeight’
,
’Bold’
);
hold on;
for
i =
1
: num1
temp = stats1(i).Centroid;
plot(temp(
1
), temp(
2
),
’r.’
);
end
hold off;
set(gcf);
end
end
function [Dom, Aom, Answer, Bn] = Analysis(stats1, stats2, Line, Img, flag)
if
nargin <
5
flag =
1
;
end
Line1 = Line{
1
};
Line2 = Line{
2
};
Line3 = Line{
3
};
Line4 = Line{
4
};
yn1 = round(Line1(
1
,
2
) +
0
.
18
*(Line2(
1
,
2
)-Line1(
1
,
2
)));
yn2 = round(Line1(
1
,
2
) +
0
.
34
*(Line2(
1
,
2
)-Line1(
1
,
2
)));
yn3 = round(Line1(
1
,
2
) +
0
.
50
*(Line2(
1
,
2
)-Line1(
1
,
2
)));
Linen1_1 = [Line1(
1
,
1
) yn1; Line1(
2
,
1
) yn1];
Linen2_1 = [Line1(
1
,
1
) yn2; Line1(
2
,
1
) yn2];
Linen3_1 = [Line1(
1
,
1
) yn3; Line1(
2
,
1
) yn3];
% 定位竖直网格分割线
xn1 = round(Line3(
1
,
1
) +
0
.
22
*(Line4(
1
,
1
)-Line3(
1
,
1
)));
xn2 = round(Line3(
1
,
1
) +
0
.
26
*(Line4(
1
,
1
)-Line3(
1
,
1
)));
xn3 = round(Line3(
1
,
1
) +
0
.
48
*(Line4(
1
,
1
)-Line3(
1
,
1
)));
xn4 = round(Line3(
1
,
1
) +
0
.
52
*(Line4(
1
,
1
)-Line3(
1
,
1
)));
xn5 = round(Line3(
1
,
1
) +
0
.
73
*(Line4(
1
,
1
)-Line3(
1
,
1
)));
xn6 = round(Line3(
1
,
1
) +
0
.
77
*(Line4(
1
,
1
)-Line3(
1
,
1
)));
xn7 = round(Line3(
1
,
1
) +
0
.
98
*(Line4(
1
,
1
)-Line3(
1
,
1
)));
Linen1_2 = [xn1 Line3(
1
,
2
); xn1 Line3(
2
,
2
)];
Linen2_2 = [xn2 Line3(
1
,
2
); xn2 Line3(
2
,
2
)];
Linen3_2 = [xn3 Line3(
1
,
2
); xn3 Line3(
2
,
2
)];
Linen4_2 = [xn4 Line3(
1
,
2
); xn4 Line3(
2
,
2
)];
Linen5_2 = [xn5 Line3(
1
,
2
); xn5 Line3(
2
,
2
)];
Linen6_2 = [xn6 Line3(
1
,
2
); xn6 Line3(
2
,
2
)];
Linen7_2 = [xn7 Line3(
1
,
2
); xn7 Line3(
2
,
2
)];
ym1_1 = round(Line1(
1
,
2
) +
0
.
32
*(Linen1_1(
1
,
2
)-Line1(
1
,
2
)));
ym2_1 = round(Line1(
1
,
2
) +
0
.
5
*(Linen1_1(
1
,
2
)-Line1(
1
,
2
)));
end
3 仿真结果
4 参考文献
[1]罗朝阳, 张鹏超, 姚晋晋,等. 基于Hough变换的答题卡识别[J]. 计算机应用与软件, 2020, 37(3):6.
博主简介:擅长智能优化算法、神经网络预测、信号处理、元胞自动机、图像处理、路径规划、无人机等多种领域的Matlab仿真,相关matlab代码问题可私信交流。
部分理论引用网络文献,若有侵权联系博主删除。
-
2023年血糖新标准公布,不是3.9-6.1,快来看看你的血糖正常吗? 2023-02-07
-
2023年各省最新电价一览!8省中午执行谷段电价! 2023-01-03
-
GB 55009-2021《燃气工程项目规范》(含条文说明),2022年1月1日起实施 2021-11-07
-
PPT导出高分辨率图片的四种方法 2022-09-22
-
2023年最新!国家电网27家省级电力公司负责人大盘点 2023-03-14
-
全国消防救援总队主官及简历(2023.2) 2023-02-10
-
盘点 l 中国石油大庆油田现任领导班子 2023-02-28
-
我们的前辈!历届全国工程勘察设计大师完整名单! 2022-11-18
-
关于某送变电公司“4·22”人身死亡事故的快报 2022-04-26
