初步构思
变量声明如下:
代码部分
%--------实验项目:快速定位限速标志牌-------% %%%%%%%%%% 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)结果展示