Matlab实验(二)快速定位限速标志牌算法

初步构思

    变量声明如下:

代码部分

%--------实验项目:快速定位限速标志牌-------%
%%%%%%%%%%    2023年5月31日    %%%%%%%%%%%


%----------------读取图片-------------------%


clc; clear all; close all;
[Name,Path]=uigetfile('*.tif;*.jpg;*.png;*.img;*.gif;','请选择需要识别图像');
RGB=imread([Path,Name]);%读取图片RGB参数

%-------------CLAHE提高对比度---------------%
if length(size(RGB))>2

    %提取RGB中Red、Green、Blue三个颜色的数据
    R=RGB(:,:,1);
    G=RGB(:,:,2);
    B=RGB(:,:,3);


    %使用CLAHE增强图像局部对比度
    %NumTiles:图块数量;ClipLimit:对比度增强限制
    R_CLAHE=adapthisteq(R,'NumTiles', [35 35], 'ClipLimit', 0.015,'Range','original');
    G_CLAHE=adapthisteq(G,'NumTiles', [35 35], 'ClipLimit', 0.015,'Range','original');
    B_CLAHE=adapthisteq(B,'NumTiles', [35 35], 'ClipLimit', 0.015,'Range','original');

    %三个分量重新连接成向量,用于后续绘图
    RGB_CLAHE=cat(3, R_CLAHE, G_CLAHE, B_CLAHE);

    %展示处理前和处理后的的图像
    figure(1)
    subplot(2,4,1)
    imshow(RGB);
    title('1.处理前的原图像','FontSize',12,'FontWeight','bold');

    subplot(2,4,2)
    imshow(RGB_CLAHE);
    title('2.CLAHE处理后的图像','FontSize',12,'FontWeight','bold');

end
%--------------二值化处理----------------%

%对图像进行灰度处理
grayRGB=rgb2gray(RGB);
grayRGB_CLAHE=rgb2gray(RGB_CLAHE);

%对原图像进行反色
grayRGB= imadjust(grayRGB,[0,1],[1,0]);
grayRGB_CLAHE= imadjust(grayRGB_CLAHE,[0,1],[1,0]);

%对原始图像进行Otsu阈值分割
T=graythresh(grayRGB);%阈值
BW=im2bw(grayRGB,T);%二值化
[imgWidth,imgHeight] = size(BW);
%figure,imshow(bwOrignal),title('orginalbw')

%对原始图像进行Otsu阈值分割
T_CLAHE=graythresh(grayRGB_CLAHE);%阈值
BW_CLAHE=im2bw(grayRGB_CLAHE,T_CLAHE);%二值化
%figure,imshow(bwOrignal),title('orginalbw')

%展示处理前和处理后的二值化图像
subplot(2,4,3)
imshow(BW);
title('3.处理前的原灰度图像','FontSize',12,'FontWeight','bold');

subplot(2,4,4)
imshow(BW_CLAHE);
title('4.CLAHE处理后的灰度图像','FontSize',12,'FontWeight','bold');

%将原始的二值图像与CLAHE二值图像相或
BW_final=BW_CLAHE|BW;

%----------------HSV颜色分割提取红色----------------%

HSV=rgb2hsv(RGB);%转换到HSV空间
H=HSV(:,:,1);%H分量
S=HSV(:,:,2);%S分量
V=HSV(:,:,3);%V分量

%尝试提取红色分量数据
HSV_red1=((H<=0.056&H>=0)|(H>=0.740&H<=1.0))&S>=0.169&S<=1.0&V>=0.180&V<=1.0;
subplot(2,4,5);
imshow(HSV_red1);
title('5.原图HSV检测图像',12,'FontWeight','bold');


%--------------------形状分割图像--------------------%

ste2=strel('square',2);%结构元素为2的方形元素
ste3=strel('square',3);%结构元素为3的方形元素
HSV_red2=imdilate(HSV_red1,ste2);%膨胀
BW_HSV=imfill(HSV_red2,'holes');%填充空洞
BW_HSV=imerode(BW_HSV,ste2);%腐蚀
BW_HSV=imopen(BW_HSV,ste3);%开运算
%bw= bwareaopen(bwHsv,50);%对连通区域面积小于50进行排除

[B,L] = bwboundaries(BW_HSV,'noholes');%边界寻找

subplot(2,4,6);
imshow(BW_HSV);
hold on
title('6.填充好圆的图像','FontSize',12,'FontWeight','bold');
hold on


%计算面积
roundness = zeros(size(B,1), 3); %圆度的统计值,将图形中每个分离的连通区域的周长、面积和圆度值记录下来
status = regionprops(L,'Area','Centroid','Circularity','BoundingBox','Perimeter');%获取图像连通域的质心
count=0;%对感兴趣区域进行计数

threshold = 0.77;% 循环处理每个边界,length(B)是闭合图形的个数,即检测到的陶粒对象个数 0.77
BW_region=zeros(imgWidth,imgHeight);
BoundingBox = cat(1,status.BoundingBox);%获取长宽

subplot(2,4,7);
imshow(RGB);
hold on

%--------------------找出候选区域--------------------%

for k = 1:length(B)  % 获取边界坐标
    %     BoundingBox = cat(1,status.BoundingBox);
    %     Perimeter= cat(1,status.Perimeter);
    %     Area=cat(1,status.Area);
    %     Circularity=cat(1,status.Circularity);

    width=BoundingBox(k,3);
    height=BoundingBox(k,4);
    roundness(k,:) = [status(k).Perimeter,status(k).Area,status(k).Circularity];
    Circularity_string = sprintf('%2.2f',status(k).Circularity);  
    % 用一个黑色小圆圈标记圆度大于threshold = 0.77 的对象


    if status(k).Circularity> threshold && status(k).Area >200 && width/height>=0.5 && width/height<=1.5 
    %大于设置的阈值 符合相应的区域宽高比
        Centroid = status(k).Centroid; %获取质心
        Circularity_string = sprintf('%2.2f',min(1,status(k).Circularity));  
        % 用一个黑色小圆圈标记圆度大于threshold = 0.77 的对象
        plot(Centroid(1), Centroid(2),'ko');  %画出质心的位置
        hold on
        text(Centroid(1)+10, Centroid(2),Circularity_string,'Color','r','FontSize',14,'FontWeight','bold');
        %在质心写坐标注释
        boundary = B{k};  % 取出周长轮廓
        plot(boundary(:,2), boundary(:,1), 'b', 'LineWidth', 2)
        %画出感兴趣区域的轮廓
        hold on
        rectangle('position', BoundingBox(k, :), 'EdgeColor', 'g', 'LineWidth', 2);
        %矩形框框出感兴趣区域
        hold on
        count=count+1;%对感兴趣区域进行计数
        BW_region=BW_region+roipoly(BW,boundary(:,2),boundary(:,1));%累计感兴趣区域ROI
    end
end
title('7.圆度识别结果,越圆越接近1,','FontSize',12,'FontWeight','bold');
stx2=strel('disk',2);%结构元素为2的圆形形元素
BW_region=imdilate(BW_region,stx2);%膨胀
BW_interest=BW_region&BW_final;
%与原图像相与获得感兴趣区域的二值化图像
BW_interest=bwareaopen(BW_interest,2);
%从二值图像 BW 中删除少于 P 个像素的所有连通分量(对象)



subplot(2,4,8);
[L,num]=bwlabel(BW_interest);%连通域标记  寻找交通标志所处的行列范围
imshow(BW_interest);hold on;title('8.限速数字提取','FontSize',12,'FontWeight','bold');

stx1=strel('disk',1);%结构元素为1的圆形形元素
while num>100 || (count==num) %如果连通域个数大于100或者连通域区域等于感兴趣区域的个数进行腐蚀
    BW_interest=imerode(BW_interest,stx1);%腐蚀
    [L,num]=bwlabel(BW_interest);%重新标记连通域
end
status1 = regionprops(L,  'Area', 'Boundingbox');
BoundingBox1 = cat(1, status1.BoundingBox);

%----------------排除禁止标志(看连通域)--------------------%
%由连通域的个数可以判别出禁止类标志和限速标志
%对于标志里面含有其他图案的 利用数字的宽高比 占据整个圆的面积比例进行区分
arean=[];%每个连通域对应的面积
for i=1:length(BoundingBox1(:,3))
    arean=[arean;BoundingBox1(i,3)*BoundingBox1(i,4),i];
    %计算每个连通域的面积
end
aream=quicksort(arean);%面积由大到小排列连通域


figure(2)
imshow(RGB);
title('最后检测结果','FontWeight','bold')
hold on
%标识限速标志区域
flag=zeros(1,num);
%标识该连通域是否被判断为数字 对判断为数字的连通域不在循环
for i=1:num
    if flag(i)~=1 %该连通域没有判断为数字
        ax1=BoundingBox1(aream(i,2),1);%获得连通域左上角点的x坐标
        ay1=BoundingBox1(aream(i,2),2);%获得连通域左上角点的y坐标
        aw1=BoundingBox1(aream(i,2),3)+BoundingBox1(aream(i,2),1);%获得连通域右下角点的x坐标
        ah1=BoundingBox1(aream(i,2),4)+BoundingBox1(aream(i,2),2);%获得连通域右下角点的y坐标
        for j=i+1:num
            if flag(j)~=1 %该连通域没有被判断为数字
                ax2=BoundingBox1(aream(j,2),1);
                %获得连通域左上角点的x坐标
                ay2=BoundingBox1(aream(j,2),2);
                %获得连通域左上角点的y坐标
                aw2=BoundingBox1(aream(j,2),3)+BoundingBox1(aream(j,2),1);%获得连通域右下角点的x坐标
                ah2=BoundingBox1(aream(j,2),4)+BoundingBox1(aream(j,2),2);%获得连通域右下角点的y坐标
                if  ax1<=ax2&&ay1<=ay2&&aw2<=aw1&&ah2<=ah1&&(aream(j,1)/aream(i,1))>=0.005&&(BoundingBox1(aream(j,2),3)/BoundingBox1(aream(j,2),4))<1.5&&(BoundingBox1(aream(j,2),3)/BoundingBox1(aream(j,2),4)>=0.2)
                    flag(j)=1;%标记该连通域被判别为数字
                    rectangle('position', BoundingBox1(aream(i,2), :), 'EdgeColor', 'g', 'LineWidth', 2);
                    %画出矩形框
                    rectangle('position', BoundingBox1(aream(j,2), :), 'EdgeColor', 'g', 'LineWidth', 2);
                    %画出矩形框
                    picture_1 =imcrop(RGB,[BoundingBox1(aream(i,2),1),BoundingBox1(aream(i,2),2),BoundingBox1(aream(i,2),3),BoundingBox1(aream(i,2),4)]);  %切割图像,起始坐标点(x1,y1)截取到终止坐标点(x2,y2)
                    name=replace(Name,'.jpg','_FinalScreen');
                    imwrite(picture_1,[cat(2,name,num2str(i)),'.jpg']);%将图片保存在程序所在文件夹中
                end
            end
        end
    end
end
name=replace(name,'_FinalScreen','_DetectionResult');
saveas(2,cat(2,name,'.jpg'));
%--------------------快排函数--------------------%
function result=quicksort(data)
%默认输入的矩阵data,第一列是数据,第二列是序号
temp=[0 0];


num=length(data(:,1));
for i=1:num
    for j=i+1:num
        if data(i,1)<data(j,1)
            temp=data(j,:);
            data(j,:)=data(i,:);
            data(i,:)=temp;
        end
    end
end
result=data;
end

结果展示

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值