基于matlab的复杂情况下的车牌识别系统
主要实现功能如下:
1、系统通过以打开文件的形式,选取要识别的车牌的图像,实现对车牌的自动识别和分割,再通过进行灰度处理、二值化、腐蚀膨胀、边缘锐化等对图片进行处理,对车牌文字进行定位、分割。
2、再通过模板匹配法、建立样本库进行字符的识别。
3、对车牌上的文字识别显示。其中包括图像预处理,基于车牌颜色特征的定位方法,车牌倾斜校正,字符分割,字符识别五个部分,对所设计的识别系统进行仿真,并得到较为准确的识别结果,内含样图大概50张左右,各省基本都有涉及。
以下文字及示例代码仅供参考
基于MATLAB的复杂情况下的车牌识别系统
以下是一个基于MATLAB的车牌识别系统的实现代码。这个系统包括图像预处理、车牌定位、车牌倾斜校正、字符分割和字符识别等主要部分。
% 基于MATLAB的车牌识别系统
% 主要功能函数列表:
% 1. image_preprocessing: 图像预处理
% 2. locate_plate: 车牌定位
% 3. correct_tilt: 车牌倾斜校正
% 4. segment_characters: 字符分割
% 5. recognize_characters: 字符识别
% 6. main: 主程序
function license_plate_recognition_system()
% 主函数,协调整个车牌识别过程
% 获取用户选择的图像文件
[filename, pathname] = uigetfile({'*.jpg;*.png;*.bmp;*.tif', 'Image Files'}, 'Select an Image File');
if isequal(filename,0)
disp('User selected Cancel')
return
else
fullpathname = fullfile(pathname, filename);
original_image = imread(fullpathname);
end
% 显示原始图像
figure;
subplot(2,3,1);
imshow(original_image);
title('原始图像');
% 图像预处理
preprocessed_image = image_preprocessing(original_image);
subplot(2,3,2);
imshow(preprocessed_image);
title('预处理后的图像');
% 车牌定位
plate_candidate = locate_plate(original_image, preprocessed_image);
subplot(2,3,3);
imshow(plate_candidate);
title('定位的车牌区域');
% 车片倾斜校正
corrected_plate = correct_tilt(plate_candidate);
subplot(2,3,4);
imshow(corrected_plate);
title('倾斜校正后的车牌');
% 字符分割
characters = segment_characters(corrected_plate);
% 字符识别
recognized_text = recognize_characters(characters);
% 显示最终识别结果
fprintf('识别的车牌号码为: %s\n', recognized_text);
title(['识别结果: ', recognized_text], 'FontSize', 14);
end
function preprocessed_image = image_preprocessing(original_image)
% 图像预处理函数
% 包括灰度化、直方图均衡化、高斯滤波等
% 如果是彩色图像,先转换为灰度图像
if size(original_image, 3) == 3
gray_image = rgb2gray(original_image);
else
gray_image = original_image;
end
% 直方图均衡化以增强对比度
eq_image = histeq(gray_image);
% 高斯滤波去噪
gauss_filtered = imgaussfilt(eq_image, 2);
% Sobel边缘检测
sobel_filtered = edge(gauss_filtered, 'Sobel');
% 形态学操作 - 先膨胀后腐蚀 (闭运算)
se = strel('rectangle', [15 15]);
morph_image = imdilate(sobel_filtered, se);
morph_image = imerode(morph_image, se);
preprocessed_image = morph_image;
end
function plate_candidate = locate_plate(original_image, preprocessed_image)
% 车牌定位函数
% 使用连通区域分析和几何特征来定位车牌
% 查找所有连通区域
cc = bwconncomp(preprocessed_image, 8);
% 获取每个连通区域的属性
stats = regionprops(cc, 'BoundingBox', 'MajorAxisLength', 'MinorAxisLength', 'Area', 'Eccentricity');
% 初始化候选区域
candidate_regions = false(size(preprocessed_image));
% 根据长宽比、面积等几何特征筛选可能的车牌区域
for i = 1:length(stats)
bb = stats(i).BoundingBox;
aspect_ratio = bb(3)/bb(4); % 宽高比
area = stats(i).Area;
eccentricity = stats(i).Eccentricity;
% 车牌通常具有特定的宽高比 (约3:1到5:1),面积适中,离心率较高
if aspect_ratio > 2 && aspect_ratio < 6 && area > 500 && area < 10000 && eccentricity > 0.8
idx = [round(bb(2)):round(bb(2)+bb(4)), round(bb(1)):round(bb(1)+bb(3))];
[rows, cols] = meshgrid(idx{2}, idx{1});
linear_idx = sub2ind(size(preprocessed_image), cols(:), rows(:));
candidate_regions(linear_idx) = true;
end
end
% 提取包含候选区域的边界框
cc_candidates = bwconncomp(candidate_regions, 8);
stats_candidates = regionprops(cc_candidates, 'BoundingBox');
% 在原图上显示候选区域
figure;
imshow(original_image);
hold on;
for i = 1:length(stats_candidates)
rectangle('Position', stats_candidates(i).BoundingBox, 'EdgeColor', 'r', 'LineWidth', 2);
end
title('车牌候选区域');
hold off;
% 这里我们假设第一个候选区域就是正确的车牌区域
if ~isempty(stats_candidates)
final_box = stats_candidates(1).BoundingBox;
plate_candidate = original_image(round(final_box(2)):round(final_box(2)+final_box(4)), ...
round(final_box(1)):round(final_box(1)+final_box(3)), :);
else
error('未找到有效的车牌候选区域');
end
end
function corrected_plate = correct_tilt(plate_candidate)
% 车牌倾斜校正
% 使用霍夫变换检测直线并计算倾斜角度
% 将车牌图像转换为灰度图像
if size(plate_candidate, 3) == 3
gray_plate = rgb2gray(plate_candidate);
else
gray_plate = plate_candidate;
end
% 边缘检测
edges = edge(gray_plate, 'Canny');
% 霍夫变换检测直线
[H, theta, rho] = hough(edges);
peaks = houghpeaks(H, 10);
lines = houghlines(edges, theta, rho, peaks);
% 计算主要方向的角度
angles = zeros(length(lines), 1);
for i = 1:length(lines)
dx = lines(i).point2(1) - lines(i).point1(1);
dy = lines(i).point2(2) - lines(i).point1(2);
angles(i) = atan2(dy, dx) * 180 / pi;
end
% 忽略接近水平或垂直的线条(可能是边框)
valid_angles = angles(abs(angles) > 5 & abs(angles) < 85);
if ~isempty(valid_angles)
% 计算平均角度作为倾斜角度
tilt_angle = median(valid_angles);
else
tilt_angle = 0;
end
% 执行仿射变换进行校正
tform = affine2d([1 0 0; 0 1 0; -tilt_angle 0 1]);
corrected_plate = imwarp(rgb2gray(plate_candidate), tform, 'OutputView', imref2d(size(plate_candidate)));
% 显示倾斜校正结果
figure;
subplot(1,2,1);
imshow(gray_plate);
title(sprintf('原始车牌 (倾斜 %.2f°)', tilt_angle));
subplot(1,2,2);
imshow(corrected_plate);
title('倾斜校正后的车牌');
end
function characters = segment_characters(corrected_plate)
% 字符分割
% 对校正后的车牌图像进行字符分割
% 灰度化
if size(corrected_plate, 3) == 3
gray_plate = rgb2gray(corrected_plate);
else
gray_plate = corrected_plate;
end
% 二值化
level = graythresh(gray_plate);
binary_plate = imbinarize(gray_plate, level);
% 反色,使字符为白色
binary_plate = 1 - binary_plate;
% 形态学操作去除小对象
binary_plate = bwareaopen(binary_plate, 50);
% 寻找连通区域
cc = bwconncomp(binary_plate, 4);
stats = regionprops(cc, 'BoundingBox', 'Area', 'Centroid');
% 按照x坐标排序
[~, idx] = sort([stats.Centroid], 2);
% 提取字符
characters = cell(1, length(stats));
for i = 1:length(stats)
bb = stats(idx(i)).BoundingBox;
char_img = binary_plate(round(bb(2)):round(bb(2)+bb(4)), ...
round(bb(1)):round(bb(1)+bb(3)));
% 调整大小至统一尺寸
char_img_resized = imresize(char_img, [40 40]);
% 存储字符图像
characters{i} = char_img_resized;
% 显示分割出的字符
figure;
subplot(1,length(stats),i);
imshow(char_img_resized);
title(sprintf('字符 %d', i));
end
end
function recognized_text = recognize_characters(characters)
% 字符识别
% 使用模板匹配方法识别字符
% 创建示例字符模板库
templates = create_template_library();
% 初始化识别结果
recognized_text = '';
% 对每个字符进行识别
for i = 1:length(characters)
current_char = characters{i};
% 初始化最佳匹配信息
best_match_char = '?';
best_match_score = -inf;
% 在模板库中寻找最佳匹配
for char_key = keys(templates)
char_str = char_key{1};
for j = 1:length(templates(char_str))
template = templates(char_str)(j);
% 计算归一化互相关
res = normxcorr2(current_char, template);
[max_row, max_col] = find(res == max(res(:)));
score = res(max_row(1), max_col(1));
if score > best_match_score
best_match_score = score;
best_match_char = char_str;
end
end
end
% 添加当前识别字符到结果
recognized_text = [recognized_text best_match_char];
% 显示匹配过程
fprintf('字符 %d 识别为 "%s",匹配得分 %.2f\n', i, best_match_char, best_match_score);
end
end
function templates = create_template_library()
% 创建字符模板库
% 因为实际情况下没有真实的模板数据库,这里我们创建一个简单的模拟库
% 初始化模板结构体
templates = struct();
% 添加数字模板(简单生成)
digits = '0123456789';
for i = 1:length(digits)
char_str = digits(i);
templates.(char_str) = cell(1, 3);
for j = 1:3
templates.(char_str){j} = generate_simple_character_template(char_str);
end
end
% 添加字母模板(简单生成)
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for i = 1:length(letters)
char_str = letters(i);
templates.(char_str) = cell(1, 3);
for j = 1:3
templates.(char_str){j} = generate_simple_character_template(char_str);
end
end
% 添加中文字符模板(简单生成)
chinese_chars = {'京','沪','津','渝','冀','晋','蒙','辽','吉','黑','苏','浙','皖','闽','赣','鲁', ...
'豫','鄂','湘','粤','桂','琼','川','贵','云','藏','陕','甘','青','宁','新'};
for i = 1:length(chinese_chars)
char_str = chinese_chars{i};
templates.(char_str) = cell(1, 3);
for j = 1:3
templates.(char_str){j} = generate_simple_character_template(char_str);
end
end
end
function template = generate_simple_character_template(char)
% 生成简单的字符模板图像
% 实际应用中应使用真实采集的模板
% 创建空白图像
template_size = [40 40];
template = false(template_size);
% 为了简化,只生成随机形状作为示例
% 在实际应用中应该使用真实的字符图像
num_shapes = randi([3 6]);
for i = 1:num_shapes
shape_type = randi([1 3]);
switch shape_type
case 1 % 圆形
radius = randi([3 8]);
center = randi([radius+1 template_size(1)-radius], 1, 2);
[X,Y] = meshgrid(1:template_size(2), 1:template_size(1));
template = template | ((X-center(2)).^2 + (Y-center(1)).^2 <= radius^2);
case 2 % 矩形
width = randi([4 12]);
height = randi([4 12]);
pos = randi([1 template_size(1)-height, 1 template_size(2)-width], 1, 2);
template(pos(1):pos(1)+height, pos(2):pos(2)+width) = true;
case 3 % 线条
angle = randi([0 180]);
length = randi([8 20]);
thickness = randi([1 3]);
center = randi([thickness+floor(length/2) template_size(1)-thickness-floor(length/2)], 1, 2);
% 生成线条
for d = -thickness:thickness
x_coords = round(center(2) + (-length/2:length/2));
y_coords = round(center(1) + tand(angle)*(-length/2:length/2) + d);
valid_idx = y_coords >= 1 & y_coords <= template_size(1) & x_coords >= 1 & x_coords <= template_size(2);
template(sub2ind(template_size, y_coords(valid_idx), x_coords(valid_idx))) = true;
end
end
end
% 确保至少有一些白色像素
if sum(template(:)) < 50
template(randi(numel(template), 1, 50)) = true;
end
end
示例用法说明
要使用此系统,请在MATLAB环境中运行license_plate_recognition_system()
函数。然后会弹出文件选择对话框,可以选择您想要识别的车牌图片。
系统特点
- 完整的车牌识别流程:从图像预处理到最终字符识别的完整流程。
- 多步骤图像处理:包括灰度化、直方图均衡化、滤波、边缘检测和形态学操作。
- 先进的车牌定位算法:利用几何特征和连通区域分析来准确定位车牌。
- 自动倾斜校正:通过霍夫变换检测并校正倾斜的车牌。
- 灵活的字符分割:基于连通区域分析和字符特征的字符分割方法。
- 模板匹配识别:使用模板匹配方法进行字符识别。
注意事项
- 此代码是为了演示目的而设计的简化版本,在实际应用中需要更复杂的算法和更大的模板库。
- 本代码中的模板库是模拟生成的,在实际应用中应该使用真实采集的字符样本。
- 由于车牌识别是一个复杂的计算机视觉任务,实际应用中可能需要根据具体场景调整参数和算法。
这是一个基本的车牌识别系统框架,可以根据具体需求进一步扩展和优化。