1. 程式人生 > >Matlab 自動獲取圖片中已經框好的所有矩形的左上角座標和寬高

Matlab 自動獲取圖片中已經框好的所有矩形的左上角座標和寬高

整體效果如下:

座標資訊和矩形寬高放在txt檔案中:

整體思路如下:

1:因為圖中的矩形框是用不同顏色框出來的,我們可以把每一個顏色的所有矩形框提取出來,變成二值影象(只有黑色和白             色)。求出此顏色的每個矩形的資訊。

2:如果按顏色分出來的矩形框只有一個,就可以用[x,y]=find(BW==1); (BW:為提出來的二值影象   find(BW==1):尋找二值                    影象中白色的區域(1為白色,0為黑色))把x,y的座標都求出來,此時min(x),min(y)Matlab可以自動求出。

3:如果按顏色分出來的矩形有多個

,此時就不知道每個矩形的最小最大的xy值了。

     用 L = bwlabel(colorb); (bwlabel:標識所有黑色背景下白色連通區域 (連通區域:封閉的區域) colorb:二值圖片)

         num = max(max(L)); (計算有多少個連通區域

        這兩句語句,把此時圖片的中的每個矩形變成一個一個的單獨矩形了,此時用迴圈用此語句

         [x,y] = find(L == i);  (i代表第幾個連通區) 

4:建立一個矩陣存放這些資訊,在把這些資訊放到txt檔案中(如果不建立矩陣,存放到txt檔案中的內容將都會在第一行第一             列中

分步講解 :

主函式:

1:

rgb=imread('61.jpg');  % 讀取圖片
figure,imshow(rgb);    %顯示圖片   figure:彈出視窗
r = rgb(:,:,1);               %提取彩色影象的紅色分量。
g = rgb(:,:,2);              %提取彩色影象的綠色分量。
b = rgb(:,:,3);              %提取彩色影象的藍色分量。
 

2:

符合紅色,藍色,綠色,橘紅色和紫色的rgb值挑選出來賦給變數red,blue,green,orange,purple 3

red=r>=175&g<36&b<36;        
blue=r<=60&g<135&b>70;
green=(20>r)&(g>80)&(g<100)&(b>20)&(b<=35);
orange=(r>200)&(g<118)&(g>36)&b<50;
purple=(175>r)&(r>97)&g<35&(b>52)&(b<=67);
 

3:

把每一個顏色放到一個數組中,為了方便迴圈呼叫shibie()函式(後面講解)減少程式碼的冗餘。

a{1}=red;     此時取到的就是二值影象
a{2}=blue;
a{3}=green;
a{4}=orange;
a{5}=purple;

4:

迴圈呼叫shibe()函式

yz=300;        %作為bwareaopen函式的引數
for i=1:5
    if i==1
        str='red';
    elseif i==2
        str='blue';
    elseif i==3
        str='green';
    elseif i==4
        str='orange';
    elseif i==5
        str='purple';
    end
                
    shibie(a{i},yz,str)
end

子函式:

1:

function [ ]  = shibie(color,yz,str)
 
       colorb = bwareaopen(color,yz);   %刪除二值影象BW中面積小於P物件  去除雜點!yz:300(主函式傳進的引數)就是把二值影象color中畫素比300小的都刪除了

2:

如果一個顏色中有好多矩形,但是這些矩形有重疊的用顏色把他們分開後,有的矩形顯示不完整,可能會出現中間有間斷

的情況,此時進行連通區域劃分時候會不準,所以在此之前要對圖中的矩形進行擴充線條(膨脹)

      connect_size = 8;
       se = strel('disk',connect_size);
       colorb = imdilate(colorb,se);
       figure;imshow(colorb);
        title('擴充線條');

3:

  使圖片進行連通區域的劃分

      L = bwlabel(colorb); 
       num = max(max(L));

4:

建立一個cell陣列(cell陣列可以裝數字和字元 都可以的)

 B=cell(num,5);

5:

迴圈計每個顏色中連通區域中矩形的座標

for i = 1:num
    [x,y] = find(L == i); 
    minx=min(y);
    maxx=max(y);
    miny=min(x);
    maxy=max(x);
    Width=maxx-minx;
    Hight=maxy-miny;
   
         B{i,1}=str;
         B{i,2}=minx;
         B{i,3}=miny;
         B{i,4}=Width;
         B{i,5}=Hight;
end

6:

把每個連通區域中矩形座標資訊放在txt檔案中

fid=fopen('sun9.txt','a');    
 [m,n]=size(B);
for h=1:1:m
     fprintf(fid,'%s%d:\t ',B{h,1},h); 
    for j=2:1:n
        if j==n          
            fprintf(fid,'%g\r\n',B{h,j});
        else           
            fprintf(fid,'%g\t',B{h,j});
        end
    end
end

整體程式碼:

主函式

rgb=imread('61.jpg');  % 讀取圖片
figure,imshow(rgb);    %顯示圖片   figure:彈出視窗
r = rgb(:,:,1);               %提取彩色影象的紅色分量。
g = rgb(:,:,2);              %提取彩色影象的綠色分量。
b = rgb(:,:,3);              %提取彩色影象的藍色分量。


red=r>=175&g<36&b<36;
blue=r<=60&g<135&b>70;
green=(20>r)&(g>80)&(g<100)&(b>20)&(b<=35);
orange=(r>200)&(g<118)&(g>36)&b<50;
purple=(175>r)&(r>97)&g<35&(b>52)&(b<=67);
a{1}=red;
a{2}=blue;
a{3}=green;
a{4}=orange;
a{5}=purple;
figure;
yz=300;   %作為bwareaopen函式的引數
for i=1:5
    if i==1
        str='red';
    elseif i==2
        str='blue';
    elseif i==3
        str='green';
    elseif i==4
        str='orange';
    elseif i==5
        str='purple';
    end
                
    shibie(a{i},yz,str)
end
    

子函式

function [ ]  = shibie(color,yz,str)
 figure()
   imshow(color);
    
       colorb = bwareaopen(color,yz);  %刪除二值影象BW中面積小於P物件 
       
       connect_size = 8;
       se = strel('disk',connect_size);
       colorb = imdilate(colorb,se);
       figure;imshow(colorb);
        title('擴充線條');
        
       L = bwlabel(colorb); 
       num = max(max(L));
       
       B=cell(num,5);
for i = 1:num
    [x,y] = find(L == i); 
    minx=min(y);
    maxx=max(y);
    miny=min(x);
    maxy=max(x);
    Width=maxx-minx;
    Hight=maxy-miny;
   
         B{i,1}=str;
         B{i,2}=minx;
         B{i,3}=miny;
         B{i,4}=Width;
         B{i,5}=Hight;
end

 fid=fopen('sun9.txt','a');    
 [m,n]=size(B);
for h=1:1:m
     fprintf(fid,'%s%d:\t ',B{h,1},h); 
    for j=2:1:n
        if j==n          
            fprintf(fid,'%g\r\n',B{h,j});
        else           
            fprintf(fid,'%g\t',B{h,j});
        end
    end
end

end

測試獲取的點時候時候正確

採用的方法是:用已經獲取的座標在原來帶有矩形的影象上畫矩形,檢視時候能和原來的矩形重合。

思路:1:讀取圖片

          2:讀取存放座標的txt

           3:在原圖上矩形(用plot()函式) 

img = imread('61.jpg');
filename='sun9.txt';
[data1,data2,data3,data4,data5]=textread(filename,'%s%f%f%f%f',18);

   figure;
   hold on;
   imshow(img);
   hold off
   for i=1:12
       width = data4(i);
       hight = data5(i);
       x1 = data2(i) ;
       x2 = x1 + width;
       y1 =data3(i);
       y2 = y1 + hight;
       hold on;
      rectx = [x1 x2 x2 x1 x1];
      recty = [y1 y1 y2 y2 y1];
      plot(rectx, recty, 'linewidth',2);
   hold off;
   end
   
 

方法二:用滑鼠點選獲取點資訊

函式:

ginput 提供了一個十字游標使我們能更精確的選擇我們所需要的位置,並返回座標值。函式呼叫形式為:

[x,y] = ginput(n),能使你從當前的座標系中讀取n個點,返回這n個點的x,y座標,均為nX1的向量。可以按回車提前結束讀數。
[x,y] = ginput 可以無限的讀取座標直到按下回車鍵。

clc,clear,clear all
image = imread('61.jpg');
figure ,imshow(image)

data = [ ];
image_array = [1,2,3,4,5,6,7,8];
image_array_length = length(image_array);
for i = 1:image_array_length
    [x, y] = ginput(2);
    width = abs(x(2) - x(1));
    height = abs(y(2) -y(1));
    data = [data; image_array(i), x(1), y(1), width, height];
end

用到的函式 

connect_size = 8;
 se = strel('disk',connect_size);
 colorb = imdilate(colorb,se);

strel()

具體用法:SE = strel(shape,parameters)
建立由指定形狀shape對應的結構元素。其中shape的種類有
arbitrary'
'pair'
'diamond'
'periodicline'
'disk'
'rectangle'
'line'
'square'
'octagon
引數parameters一般控制SE的大小。

imdilate()

imdilate函式用於對影象實現膨脹操作。(形態學)

img=imdilate(img,SE) 。引數SE為由strel函式返回的結構元素或者結構元素物件組。

bwareaopen()

功能: 用於從物件中移除小物件。   
用法: BW2 = bwareaopen(BW,P)
           BW2 = bwareaopen(BW,P,CONN)   從二值影象 中移除所有小於P的連通物件。CONN對應鄰域方法,預設為8。

 yz=300;

colorb = bwareaopen(color,yz);

bwlabel()

bwlabel功能:對連通物件進行標註,bwlabel主要對二維二值影象中各個分離部分進行標註.

L = bwlabel(BW,n) :返回一個和BW大小相同的L矩陣,包含了標記了BW中每個連通區域的類別標籤,這些標籤的值為1、2、num(連通區域的個數)。n的值為4或8,表示是按4連通尋找區域,還是8連通尋找,預設為8。

 L = bwlabel(colorb); 

textread()

實際應用中經常要讀取txt檔案,這個時候就需要用到強大的textread函式。
它的基本語法是:
[A,B,C,...] = textread(filename,format)
[A,B,C,...] = textread(filename,format,N)
其中filename就是檔名 format就是要讀取的格式A,B,C就是從檔案中讀取到的資料
中括號裡面變數的個數必須和format中定義的個數相同。 如果每N行相同格式的資料,可採用[A,B,C,...] = textread(filename,format,N)的語法,讀取N次。

[data1,data2,data3,data4,data5]=textread(filename,'%s%f%f%f%f',18);

ginput ()

ginput提供了一個十字游標使我們能更精確的選擇我們所需要的位置,並返回座標值。函式呼叫形式為:

[x,y] = ginput(n),能使你從當前的座標系中讀取n個點,返回這n個點的x,y座標,均為nX1的向量。可以按回車提前結束讀數。
[x,y] = ginput 可以無限的讀取座標直到按下回車鍵。