1.代码实现及逐层解析
1.1核心代码
clc; % 清除命令窗口。
clear; % 清除工作区中的所有变量。
% 导入图像
Img = imread("car.png"); % 读取图像文件 "car.png"。
figure, imshow(Img), title('原图'); % 显示原始图像,并设置标题为 "原图"。
% 图像增强,调整对比度
j = imadjust(Img, stretchlim(Img)); % 调整图像对比度,使用拉伸限制范围的方法。
% 灰化图像
grayImage = rgb2gray(j); % 将增强后的图像转换为灰度图。
figure, imshow(grayImage);
title('经过灰化后的图像'); % 显示灰度图,并设置标题为 "经过灰化后的图像"。
% 平滑处理 - 使用高斯滤波减少噪声
smoothedImage = imgaussfilt(grayImage, 2); % 高斯滤波,标准差为 2。
figure, imshow(smoothedImage), title('平滑处理后的图像'); % 显示平滑后的图像。
% 锐化处理 - 使用拉普拉斯算子增强边缘
sharpenedImage = imsharpen(smoothedImage, 'Radius', 2, 'Amount', 1);
% 锐化图像,半径为 2,增强强度为 1。
figure, imshow(sharpenedImage), title('锐化处理后的图像'); % 显示锐化后的图像。
% 边缘检测
edgeImage = imbinarize(sharpenedImage); % 对锐化后的图像进行二值化。
[e1, s1] = edge(edgeImage, 'sobel', 0.03, 'both');
% 使用 Sobel 算子进行边缘检测,阈值为 0.03,检测双边缘。
figure, imshow(e1), title('经过边缘检测后的图像'); % 显示边缘检测后的图像。
% 形态学处理
se1 = [1; 1; 1]; % 定义腐蚀操作的结构元素(线性结构)。
erodedImage = imerode(e1, se1); % 腐蚀操作,去除细小噪声。
figure, imshow(erodedImage), title('经过腐蚀后的图像'); % 显示腐蚀后的图像。
se2 = strel('rectangle', [15, 45]); % 定义闭操作的矩形结构元素(15×45)。
closedImage = imclose(erodedImage, se2); % 使用闭操作填补间隙。
figure, imshow(closedImage), title('经过闭合的图像'); % 显示闭合后的图像。
% 提取车牌区域
stats = regionprops(closedImage, 'all');
% 提取闭合图像中每个区域的属性(包括面积和边界框等)。
areas = [stats.Area]; % 获取所有区域的面积。
[idx, max_area] = max(areas); % 找到面积最大的区域的索引和面积。
cropped_image = imcrop(sharpenedImage, stats(max_area).BoundingBox);
% 根据面积最大的区域的边界框裁剪图像,提取车牌区域。
figure, imshow(cropped_image);
title('定位到的车牌'); % 显示裁剪出的车牌区域。
% 二值化车牌图像
binaryPlate = imbinarize(cropped_image, 'adaptive'); % 自适应阈值二值化车牌图像。
figure, imshow(binaryPlate), title('二值化车牌'); % 显示二值化的车牌。
% 字符分割
characterRegions = regionprops(binaryPlate, 'BoundingBox', 'Area');
% 获取车牌中每个字符区域的边界框和面积属性。
characterRegionsTable = struct2table(characterRegions);
% 将字符区域的结构体转换为表格。
boundingBoxes = characterRegionsTable.BoundingBox; % 提取表格中 BoundingBox 列。
xCoordinates = boundingBoxes(:, 1); % 获取每个区域的 x 坐标。
characterRegionsTable.x = xCoordinates; % 在表格中添加 x 坐标列。
sortedRegions = sortrows(characterRegionsTable, 'x', 'ascend');
% 按 x 坐标升序排列字符区域。
characterImages = {}; % 初始化存储分割字符图像的单元数组。
for i = 1:height(sortedRegions)
charBBox = table2array(sortedRegions(i, 'BoundingBox'));
% 获取当前字符的边界框。
charArea = table2array(sortedRegions(i, 'Area'));
% 获取当前字符的面积。
if charArea > 500 % 忽略面积小于 500 的噪声区域。
charImage = imcrop(binaryPlate, charBBox);
% 根据边界框裁剪字符图像。
charImage = imresize(charImage, [20 20]);
% 将字符图像调整为 20×20 的固定大小。
characterImages{end+1} = charImage; % 保存分割的字符图像。
figure, imshow(charImage), title(['分割的字符 ' num2str(i)]);
% 显示当前分割的字符图像。
end
end
% 字符识别
templates = loadTemplates(); % 加载字符模板(假设已实现模板加载函数)。
plateNumber = ''; % 初始化车牌号字符串。
for i = 1:length(characterImages)
charImage = characterImages{i}; % 获取当前字符图像。
recognizedChar = matchCharacter(charImage, templates);
% 使用模板匹配方法识别字符。
plateNumber = [plateNumber recognizedChar];
% 将识别出的字符拼接到车牌号字符串中。
end
disp(['车牌号为: ', plateNumber]); % 输出识别出的车牌号。
1.2字符集模版代码
function templates = loadTemplates()
% 定义模板字符集,可以包括字母和数字
chars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ...
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
% 创建一个结构数组来存储模板
templates = struct();
% 为每个字符加载对应的模板
for i = 1:length(chars)
filename = ['templates/' chars(i) '.jpg']; % 假设模板图片以字符命名
if exist(filename, 'file')
templates(i).char = chars(i);
templates(i).image = imread(filename);
else
warning('模板文件 %s 不存在!', filename);
end
end
end
1.3匹配字符代码
function recognizedChar = matchCharacter(charImage, templates)
bestMatchScore = -Inf; % 初始化匹配分数
recognizedChar = ''; % 初始化识别结果
% 将 charImage 转换为灰度图像(如果它是彩色图像)
if size(charImage, 3) == 3
charImage = rgb2gray(charImage);
end
% 转换为 double 类型,以便 normxcorr2 可以正确处理
charImage = im2double(charImage);
% 遍历所有模板进行匹配
for i = 1:length(templates)
templateImage = templates(i).image; % 获取模板图像
% 如果模板图像是彩色的,则转换为灰度图像
if size(templateImage, 3) == 3
templateImage = rgb2gray(templateImage);
end
% 转换为 double 类型
templateImage = im2double(templateImage);
% 使用归一化互相关计算匹配度
corrScore = normxcorr2(templateImage, charImage);
% 查找相关性矩阵中的最大值,表示最匹配的位置
maxScore = max(corrScore(:));
if maxScore > bestMatchScore
bestMatchScore = maxScore;
recognizedChar = templates(i).char; % 记录当前最匹配的字符
end
end
end
2.一些重要函数的作用及解释
2.1函数 stretchlim
的作用
stretchlim
用于计算图像亮度范围(即灰度值)的上下限,用于对比度拉伸。它会忽略一部分极小的像素值(通常是极暗或极亮的像素),避免这些像素过度影响调整结果。
语法:
limits = stretchlim(Img, tol)
Img
: 输入图像,可以是灰度图或 RGB 图像。tol
: 阈值范围,表示忽略的低端和高端像素比例(默认为[0.01, 0.99]
,即忽略最暗 1% 和最亮 1% 的像素)。limits
: 返回两值的向量[low, high]
,即被认为有效的灰度范围。
例如,对于灰度图像,[low, high]
表示仅保留灰度值在 low
和 high
之间的像素范围,超出范围的像素会被压缩。
2.2函数 imadjust
的作用
imadjust
是 MATLAB 中常用的对比度调整函数,可以将图像的灰度值拉伸到指定范围。
语法:
adjustedImg = imadjust(Img, [low_in high_in], [low_out high_out])
[low_in high_in]
: 输入图像的灰度范围(由stretchlim
提供)。[low_out high_out]
: 输出图像的灰度范围(通常是[0, 1]
,即全灰度动态范围)。
它将灰度值线性映射到新范围,增强图像对比度。
2.3函数 imgaussfilt的作用
专用函数 imgaussfilt
,可以轻松实现高斯滤波。高斯滤波(Gaussian Filtering) 是一种利用高斯函数分布的权重对图像进行平滑处理的滤波方法,常用于减少图像中的噪声,同时保留边缘细节信息。其核心思想是:
- 赋予中心像素较高的权重,周围像素较低的权重。
- 去除局部的快速变化(如噪声),使图像平滑。
语法:
smoothedImage = imgaussfilt(Img, sigma);
Img
:输入图像。sigma
:高斯分布的标准差,控制模糊程度(较大的值会导致更强的模糊效果)。
通过调节 sigma
的值,可以控制噪声去除的程度和图像模糊程度。
2.4函数 imsharpen的作用
MATLAB 提供了 imsharpen
函数,用于对图像进行锐化处理,内部实现可以基于拉普拉斯算子。拉普拉斯算子(Laplacian Operator) 是一种常用的边缘增强方法。它通过计算图像像素的二阶导数,边缘区域的像素变化较大,因此二阶导数值高,可以用来检测边缘。突出图像中的高频部分(如边缘和细节),从而达到增强边缘的效果。
拉普拉斯算子主要用于:
- 增强边缘:突出图像中的边缘区域。
- 抑制平滑区域:平坦的区域由于像素值变化小,会被弱化。
代码解析:
sharpenedImage = imsharpen(smoothedImage, 'Radius', 2, 'Amount', 1);
figure, imshow(sharpenedImage), title('锐化处理后的图像');
参数说明:
smoothedImage
:输入图像(通常是经过平滑处理后的图像)。'Radius'
:锐化时的影响半径(决定边缘增强的范围)。'Amount'
:增强强度,数值越高,边缘越明显。
拉普拉斯算子能突出图像中的细节和边缘,直接通过卷积操作即可完成。 如果图像噪声未被平滑处理,噪声也会被增强,对原始图像的平滑程度要求较高。
2.5函数imbinarize的作用
自动二值化函数imbinarize
内部会根据图像特性选择合适的阈值。二值化(Binarization) 是图像处理中将图像像素值转换为两个值(通常是 0 和 1 或黑白)的操作。边缘检测中的二值化是将边缘提取结果转换为清晰的二值边界图像,便于后续处理(如形态学操作、目标区域提取等)。
代码解析:
edgeImage = imbinarize(sharpenedImage); % 对锐化后的图像进行二值化
[e1, s1] = edge(edgeImage, 'sobel', 0.03, 'both'); % 使用 Sobel 算子进行边缘检测
-
imbinarize
:- 自动二值化函数,根据图像像素值分布动态计算阈值。
- 将锐化后的图像(灰度图)转化为二值图像。
-
edge
:- 采用 Sobel 算子进行边缘检测。
- 参数说明:
'sobel'
:指定使用 Sobel 算子。0.03
:边缘检测的阈值,越低会检测更多边缘。'both'
:检测图像水平和垂直方向的边缘。
2.6函数edge的作用
MATLAB 中的 edge
函数用于 边缘检测。它可以检测图像中灰度值变化剧烈的区域,这些区域通常是图像的边缘部分。edge
支持多种边缘检测方法(如 Sobel、Canny、Prewitt 等),适用于不同的应用场景。
语法:
BW = edge(I, method, threshold, direction)
参数解释
-
I
:- 输入图像,可以是灰度图像或二值图像。
- 如果是彩色图像,需先转换为灰度图(使用
rgb2gray
)。
-
method
:- 指定边缘检测算法。支持以下方法:
'Sobel'
(默认):基于图像梯度计算的经典边缘检测方法。'Prewitt'
:类似于 Sobel,但对噪声的抑制能力稍弱。'Roberts'
:适用于检测快速变化的边缘。'Canny'
:常用的边缘检测方法,结合噪声抑制和精确边缘检测。'log'
:基于拉普拉斯高斯算子的边缘检测。'zerocross'
:检测图像二阶导数的零交叉点。
- 指定边缘检测算法。支持以下方法:
-
threshold
(可选):- 边缘检测的阈值(通常是梯度值)。默认为自动计算。
- 单一值:所有大于该值的像素被认为是边缘。
- 两个值(仅对
'Canny'
有效):分别表示低阈值和高阈值,用于双阈值检测。
-
direction
(可选):- 指定检测的方向。适用于 Sobel、Prewitt 和 Roberts 算子:
'horizontal'
:只检测水平方向的边缘。'vertical'
:只检测垂直方向的边缘。'both'
(默认):同时检测水平方向和垂直方向的边缘。
- 指定检测的方向。适用于 Sobel、Prewitt 和 Roberts 算子:
2.7函数imerode的作用
腐蚀(Erosion)是图像形态学中的一种基本操作,主要用于缩小目标区域,去除噪声,或分离目标。它通常用于二值图像处理,但也可以扩展到灰度图像。腐蚀操作通过一个称为结构元素(Structuring Element, SE)的窗口,对图像进行像素值的最小值运算。
二值图像中的腐蚀:
- 结构元素在目标图像上滑动。
- 如果结构元素的所有白色像素都完全被图像中的白色像素覆盖,则输出对应位置像素为白(值为 1);否则为黑(值为 0)。
- 结果是:目标区域的边界被“侵蚀”,目标变得更小。
语法:
erodedImage = imerode(inputImage, se);
inputImage
:输入图像(通常是二值图像)。se
:结构元素(可以通过strel
函数生成)。erodedImage
:腐蚀后的输出图像。
腐蚀操作的优缺点:
优点:简单高效,适用于噪声去除和目标区域分离;可以灵活调整结构元素,适应不同应用场景。
缺点:会导致目标区域的尺寸缩小,可能丢失重要信息;对细小目标或弱边缘有较大影响。
2.8 函数imclose的作用
MATLAB 提供了 imclose
函数,用于实现闭操作。闭操作(Closing)是形态学处理中一种常见的操作,它是**膨胀操作(Dilation)和腐蚀操作(Erosion)**的组合。具体来说:闭操作 = 先膨胀,后腐蚀。
语法:
closedImage = imclose(inputImage, se);
inputImage
:输入的二值图像。se
:结构元素(可以使用strel
函数定义)。closedImage
:闭操作后的输出图像。
结构元素(se
)在闭操作中非常重要,它决定了处理效果:
- 大小:
- 较小的结构元素只会处理细小的孔洞或间隙。
- 较大的结构元素会影响更大的区域。
- 形状:
- 圆形(
disk
):适合处理光滑边界的目标。 - 方形(
square
):适合处理直边目标。 - 线性(
line
):适合连接特定方向的断开区域。
- 圆形(
闭操作的优缺点:
优点:填补目标区域中的孔洞,连接断裂区域;平滑目标边界,适合目标分割后的预处理。
缺点:如果结构元素过大,可能会过度填补,导致目标形状失真;不适合去除孤立的噪声点(需要用开操作)。
2.9函数regionprops的作用
regionprops
是 MATLAB 中用于分析图像区域的强大函数,它可以提取图像中连通区域的各种属性,如面积、边界框、质心等。该函数常用于二值图像中目标区域的特征提取。
在车牌识别中,regionprops
被用来提取车牌区域的属性,例如面积(用于选择最大区域)和边界框(用于裁剪车牌区域)。
语法:
stats = regionprops(BW, properties)
BW
:输入的二值图像。properties
:需要提取的属性列表stats
:输出为一个结构体数组,每个结构体代表一个连通区域及其属性。