STATS = regionprops(L,properties)

本文介绍Matlab中regionprops函数的使用,该函数用于度量图像中被标记区域的多种属性,如面积、质心、边界框等。适用于图像处理与计算机视觉领域的研究与应用。

regionprops(英文get the properties of region)是Matlab中用来度量图像区域属性的函数。
功能:regionprops(get the properties of region)度量图像区域属性的函数.
常用来统计被标记的区域的面积分布,显示区域总数。
语法:STATS = regionprops(L,properties)
描 述:测量标注矩阵 L中每一个标注区域的一系列属性。L 中不同的正整数元素对应不同的区域, 例如:L 中等于整数1的元素对应区域1;L 中等于整数2的元素对应区域2。
返回值STATS 是一个长度为 max(L(?)的结构数组,结构数组的相应域定义了每一个区域相应属性下的度量。 properties 可以是由逗号分割的字符串列表,包含字符串的单元数组,单个字符串 ‘all’ 或者 ‘basic’。如果 properties 等于字符串 ‘all’,则所有下述字串列表中的度量数据都将被计算,如果properties 没有指定或者等于 ‘basic’,则属性 ‘Area’、‘Centroid’ 和’BoundingBox’ 将被计算。
'Area’图像各个区域中像素总个数
  ‘BoundingBox’ 包含相应区域的最小矩形
  ‘Centroid’ 每个区域的质心(重心)
  ‘MajorAxisLength’ 与区域具有相同标准二阶中心矩的椭圆的长轴长度(像素意义下)
  ‘MinorAxisLength’ 与区域具有相同标准二阶中心矩的椭圆的短轴长度(像素意义下)
  ‘Eccentricity’ 与区域具有相同标准二阶中心矩的椭圆的离心率(可作为特征)
  ‘Orientation’ 与区域具有相同标准二阶中心矩的椭圆的长轴与x轴的交角(度)
  ‘Image’ 与某区域具有相同大小的逻辑矩阵
  ‘FilledImage’ 与某区域具有相同大小的填充逻辑矩阵
  ‘FilledArea’ 填充区域图像中的on像素个数
  ‘ConvexHull’ 包含某区域的最小凸多边形
  ‘ConvexImage’ 画出上述区域最小凸多边形
  ‘ConvexArea’ 填充区域凸多边形图像中的on像素个数
  ‘EulerNumber’ 几何拓扑中的一个拓扑不变量——欧拉数
  ‘Extrema’ 八方向区域极值点
  ‘EquivDiameter’ 与区域具有相同面积的圆的直径
  ‘Solidity’ 同时在区域和其最小凸多边形中的像素比例
  ‘Extent’ 同时在区域和其最小边界矩形中的像素比例
  ‘PixelIdxList’ 存储区域像素的索引下标
  ‘PixelList’ 存储上述索引对应的像素坐标
  ‘Perimeter’ 图像各个区域边界地区的周长

classdef wufafuzhi < matlab.apps.AppBase % 属性定义 properties (Access = public) UIFigure matlab.ui.Figure ProcessButton matlab.ui.control.Button ImageAxes matlab.ui.control.UIAxes LoadImageButton matlab.ui.control.Button StatusLabel matlab.ui.control.Label ResultLabel matlab.ui.control.Label LicensePlateAxes matlab.ui.control.UIAxes ThresholdSlider matlab.ui.control.Slider ThresholdLabel matlab.ui.control.Label CharacterAxes matlab.ui.control.UIAxes end properties (Access = private) originalImage uint8 % 原始图像 licensePlateImage uint8 % 车牌图像 processedImage uint8 % 处理后的图像 plateNumber string % 识别的车牌号码 thresholdValue double % 阈值 end methods (Access = private) % 加载图像回调函数 function LoadImageButtonPushed(app, event) [fileName, filePath] = uigetfile({'*.jpg;*.jpeg;*.png;*.bmp', '图像文件 (*.jpg, *.jpeg, *.png, *.bmp)'}); if isequal(fileName, 0) || isequal(filePath, 0) return; end % 读取图像 app.originalImage = imread(fullfile(filePath, fileName)); % 显示原始图像 cla(app.ImageAxes); imshow(app.originalImage, 'Parent', app.ImageAxes); title(app.ImageAxes, '原始图像'); % 更新状态 app.StatusLabel.Text = '图像已加载'; app.ProcessButton.Enable = 'on'; end % 处理图像回调函数 function ProcessButtonPushed(app, event) if isempty(app.originalImage) app.StatusLabel.Text = '请先加载图像'; return; end try % 显示处理中状态 app.StatusLabel.Text = '处理中...'; drawnow; % 车牌定位 app.licensePlateImage = locateLicensePlate(app, app.originalImage); % 车牌字符分割与识别 app.plateNumber = recognizeLicensePlate(app, app.licensePlateImage); % 显示结果 cla(app.LicensePlateAxes); imshow(app.licensePlateImage, 'Parent', app.LicensePlateAxes); title(app.LicensePlateAxes, '车牌区域'); title(app.LicensePlateAxes, '车牌区域'); % 更新状态和结果 app.StatusLabel.Text = '处理完成'; app.ResultLabel.Text = "识别结果: " + app.plateNumber; catch e app.StatusLabel.Text = "处理出错: " + e.message; end end % 车牌定位函数 function plateImage = locateLicensePlate(app, img) % 转换为灰度图 grayImage = rgb2gray(img); % 高斯模糊 blurredImage = imgaussfilt(grayImage, 1); % 边缘检测 edgeImage = edge(blurredImage, 'Canny', [0.05 0.15]); % 形态学操作 - 闭运算 se = strel('rectangle', [5, 5]); closedImage = imclose(edgeImage, se); % 查找轮廓 stats = regionprops(closedImage, 'BoundingBox', 'Area'); % 筛选可能的车牌区域 plateRegions = []; for i = 1:length(stats) bb = stats(i).BoundingBox; area = stats(i).Area; % 筛选条件: 宽高比和面积 aspectRatio = bb(3) / bb(4); if aspectRatio > 2 && aspectRatio < 6 && area > 1000 && area < 50000 plateRegions = [plateRegions; i]; end end % 如果找到多个候选区域,选择面积最大的 if ~isempty(plateRegions) [~, maxIdx] = max([stats(plateRegions).Area]); plateBB = stats(plateRegions(maxIdx)).BoundingBox; % 提取车牌区域 plateImage = imcrop(img, plateBB); else % 如果没有找到符合条件的区域,返回原图的一个裁剪区域 plateImage = imcrop(img, [size(img, 2)/3, size(img, 1)/2, size(img, 2)/3, size(img, 1)/4]); warning('未找到符合条件的车牌区域,返回默认裁剪区域'); end end % 车牌字符识别函数 function plateNumber = recognizeLicensePlate(app, plateImage) % 转换为灰度图 grayPlate = rgb2gray(plateImage); % 二值化 threshold = app.ThresholdSlider.Value; binaryPlate = imbinarize(grayPlate, threshold); % 形态学操作 se = strel('rectangle', [2, 2]); binaryPlate = imopen(binaryPlate, se); binaryPlate = imclose(binaryPlate, se); % 显示处理后的车牌 app.processedImage = binaryPlate; cla(app.LicensePlateAxes); imshow(binaryPlate, 'Parent', app.LicensePlateAxes); title(app.LicensePlateAxes, '处理后的车牌'); % 字符分割 charImages = segmentCharacters(app, binaryPlate); % 显示分割的字符 cla(app.CharacterAxes); if ~isempty(charImages) % 创建字符拼接图像 charHeight = size(charImages{1}, 1); charWidth = size(charImages{1}, 2); combinedChars = zeros(charHeight, charWidth * length(charImages)); for i = 1:length(charImages) combinedChars(:, (i-1)*charWidth+1:i*charWidth) = charImages{i}; end imshow(combinedChars, 'Parent', app.CharacterAxes); title(app.CharacterAxes, '分割的字符'); end % 字符识别 (这里使用简单的模板匹配示例) % 在实际应用中,建议使用训练好的OCR模型 plateNumber = recognizeCharacters(app, charImages); end % 字符分割函数 function charImages = segmentCharacters(app, binaryPlate) % 计算垂直投影 verticalProjection = sum(binaryPlate, 1); % 寻找字符边界 threshold = max(verticalProjection) * 0.1; isCharacter = verticalProjection > threshold; % 寻找连续的字符区域 charRegions = []; inCharacter = false; startCol = 0; for col = 1:length(isCharacter) if isCharacter(col) && ~inCharacter % 开始一个新字符 inCharacter = true; startCol = col; elseif ~isCharacter(col) && inCharacter % 结束一个字符 inCharacter = false; endCol = col - 1; % 忽略过小的区域 if endCol - startCol > 5 charRegions = [charRegions; [startCol, endCol]]; end end end % 提取字符图像 charImages = cell(1, size(charRegions, 1)); for i = 1:size(charRegions, 1) startCol = charRegions(i, 1); endCol = charRegions(i, 2); % 扩展边界以获取完整字符 startRow = max(1, floor(size(binaryPlate, 1) * 0.1)); endRow = min(size(binaryPlate, 1), ceil(size(binaryPlate, 1) * 0.9)); charImages{i} = binaryPlate(startRow:endRow, startCol:endCol); end % 只保留6-8个字符(中国车牌标准) if length(charImages) >= 6 && length(charImages) <= 8 % 正常情况,直接返回 elseif length(charImages) > 8 % 太多字符,尝试合并或筛选 charImages = charImages(1:8); elseif length(charImages) < 6 && ~isempty(charImages) % 太少字符,尝试扩展或补充 % 这里简单处理,用空图像补充 while length(charImages) < 6 charImages{end+1} = zeros(size(charImages{1})); end else % 无法分割字符,返回空 charImages = {}; end end % 字符识别函数 function plateNumber = recognizeCharacters(~, charImages) % 这里使用简单的模板匹配方法 % 在实际应用中,建议使用深度学习OCR模型 % 预设字符模板 (简化示例,实际应用需要更多字符) characterTemplates = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ... 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', ... 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', ... 'W', 'X', 'Y', 'Z', '京', '津', '沪', '渝', '冀', ... '晋', '辽', '吉', '黑', '苏', '浙', '皖', '闽', '赣', ... '鲁', '豫', '鄂', '湘', '粤', '琼', '川', '贵', '云', ... '陕', '甘', '青', '宁', '新'}; % 初始化车牌号码 plateNumber = ""; % 对每个字符进行识别 for i = 1:length(charImages) if isempty(charImages{i}) plateNumber = plateNumber + "?"; continue; end % 第一个字符通常是省份简称 if i == 1 % 只匹配省份简称 provinceTemplates = characterTemplates(35:end); bestMatch = matchCharacter(charImages{i}, provinceTemplates); plateNumber = plateNumber + bestMatch; else % 其他字符匹配数字和字母 alnumTemplates = characterTemplates(1:34); bestMatch = matchCharacter(charImages{i}, alnumTemplates); plateNumber = plateNumber + bestMatch; end end % 辅助函数:字符匹配 function bestMatch = matchCharacter(~, templates) % 简单的模板匹配实现 bestMatch = "?"; bestScore = 0; % 这里应该有实际的模板匹配代码 % 简化示例,随机返回一个字符 if ~isempty(templates) bestMatch = templates{randi(length(templates))}; end end end % 阈值滑块值改变回调 function ThresholdSliderValueChanged(app, event) app.thresholdValue = app.ThresholdSlider.Value; app.ThresholdLabel.Text = "二值化阈值: " + num2str(round(app.thresholdValue, 2)); % 如果已经处理过图像,使用新阈值重新处理 if ~isempty(app.licensePlateImage) app.StatusLabel.Text = '重新处理中...'; drawnow; % 重新识别车牌 app.plateNumber = recognizeLicensePlate(app, app.licensePlateImage); % 更新结果 app.StatusLabel.Text = '处理完成'; app.ResultLabel.Text = "识别结果: " + app.plateNumber; end end end % 构建和配置GUI methods (Access = private) function createComponents(app) % 创建主窗口 app.UIFigure = uifigure('Visible', 'off'); app.UIFigure.Position = [100, 100, 1000, 600]; app.UIFigure.Name = '车牌识别系统'; app.UIFigure.Resize = 'on'; % 创建加载图像按钮 app.LoadImageButton = uibutton(app.UIFigure, 'push'); app.LoadImageButton.ButtonPushedFcn = @(btn, event) LoadImageButtonPushed(app, event); app.LoadImageButton.Position = [20, 520, 150, 30]; app.LoadImageButton.Text = '加载图像'; % 创建处理按钮 app.ProcessButton = uibutton(app.UIFigure, 'push'); app.ProcessButton.ButtonPushedFcn = @(btn, event) ProcessButtonPushed(app, event); app.ProcessButton.Position = [180, 520, 150, 30]; app.ProcessButton.Text = '处理图像'; app.ProcessButton.Enable = 'off'; % 创建状态标签 app.StatusLabel = uilabel(app.UIFigure); app.StatusLabel.Position = [350, 520, 200, 30]; app.StatusLabel.Text = '请加载图像'; % 创建结果标签 app.ResultLabel = uilabel(app.UIFigure); app.ResultLabel.Position = [570, 520, 400, 30]; app.ResultLabel.FontSize = 14; app.ResultLabel.Text = '识别结果: '; % 创建原始图像显示区域 app.ImageAxes = uiaxes(app.UIFigure); app.ImageAxes.Position = [20, 20, 300, 480]; app.ImageAxes.Title.String = '原始图像'; % 创建车牌区域显示区域 app.LicensePlateAxes = uiaxes(app.UIFigure); app.LicensePlateAxes.Position = [340, 20, 300, 230]; app.LicensePlateAxes.Title.String = '车牌区域'; % 创建字符显示区域 app.CharacterAxes = uiaxes(app.UIFigure); app.CharacterAxes.Position = [340, 260, 300, 240]; app.CharacterAxes.Title.String = '分割的字符'; % 创建阈值滑块 app.ThresholdSlider = uislider(app.UIFigure); app.ThresholdSlider.ValueChangedFcn = @(src, event) ThresholdSliderValueChanged(app, event); app.ThresholdSlider.Position = [660, 420, 300, 22]; app.ThresholdSlider.Limits = [0.1, 0.9]; app.ThresholdSlider.Value = 0.4; % 创建阈值标签 app.ThresholdLabel = uilabel(app.UIFigure); app.ThresholdLabel.Position = [660, 450, 300, 22]; app.ThresholdLabel.Text = '二值化阈值: 0.40'; % 初始化属性 app.thresholdValue = 0.4; end end % 应用程序构造函数 methods (Access = public) function app = wufafuzhi % 创建并配置组件 createComponents(app); % 显示主窗口 app.UIFigure.Visible = 'on'; end end end
最新发布
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值