【機器視覺與影象處理】基於MATLAB的角度計算

HustWolfzzb發表於2017-11-28

正文之前

最近新開了一門課,我十分感興趣,或者是說老早就想接觸類似方面的學習,但是一直沒有真正著手,所以說,其實上課還是很有必要的,很多時候你想做的事情但是你根本沒法開始,所以需要一個推動力,當一點點的作業加上完成學分的壓力壓在你的肩頭,配合你早就蓄勢待發的興趣使然,就會爆發很大的熱情去學習。就好比這門,機器視覺與影象處理技術, 我很感興趣,所以昨天坐火車的時候我都在火車上把我們這門課的第一次作業做出來了。

正文

我們的第一次作業,是把下圖中的這個風扇扇葉一個葉片的角度計算出來。

我一開始還苦思冥想,不知道怎麼才能提取出來這個因素,所以很是煩惱不知道該如何是好,但是昨天看了下群裡面的說法,我瞬間就理通了。只要轉變下思維,把影象看成一個二維陣列配上每個元素的大小不同代表著顏色深淺的想法就好了

他已經做到了這一步,剩下的就是不知道如何處理這個圖形的元素,但是,我雖然目前還是個菜雞,但是我好歹也是要念計算機的博士的人啊!!!怎麼會被這種小問題難到??不存在的!!下面請看我的表演:

然後,想法有了。手段也有了。對陣列的處理,尤其是一堆的只是bool量的二維陣列,簡直不要太簡單好麼?都不需要for巢狀了,直接取兩個X座標作為定值定量的檢測這兩行的資料,不就好了?下面是那位同學的想法:

我覺得,這樣是給自己增加了工作量,反而讓matlab變輕鬆了啊。怎麼能這樣呢?不存在的!!所以還是直接讓matlab去計算吧,直接用兩點確定一條直線的方式,給兩條直線分別求出來斜率,然後在視覺的絕對座標系下轉化為角度,最後就得到咯~~:

這之間還發生了一個小插曲,那就是我給我的MATLAB爸爸跪舔的時候,直接被打臉了

這臉打的啪啪響!!

所以,最後這就是我的程式碼咯~~

pic=imread('/Users/zhangzhaobo/program/MATLAB/First_work_angles.jpg'); %讀取照片作為一個物件讀入matlab 而不是簡單的開啟
bw=im2bw(pic); % 我們需要的不是一個RGB影象,而是一個二值化影象就好了。至於什麼是二值化,就是說黑白照咯,一個畫素點,要不就是黑的要不就是白的,所以就很好整!!
bw=edge(bw,'canny');  % 邊緣提取,一個一直困擾我的地方,因為我還沒看到這些點!
%下面的變數分別就是我取點的列數,至於Y1 Y2 就是行數,因為讀取出來的影象有點問題
first_dot1=0;
first_dot2=0;
second_dot1=0;
second_dot1=0;
Y1=400;Y2=450;

% 從400行第一個點到第2440個點,分別取值,為了防止噪聲干擾,我還特意的給了一個範圍以及限制。

for i=1:2440
    if 700<i<1600
        if bw(Y1,i)==1
            if first_dot1>0
                second_dot1=i
            else
                first_dot1=i
            end
        end
    end
end

% 從450行第一個點到第2440個點,分別取值,為了防止噪聲干擾,我還特意的給了一個範圍以及限制。

for i=1:2440
    if 700<i<1600
        if bw(Y2,i)==1
            if first_dot2>0
                second_dot2=i
            else
                first_dot2=i
            end
        end
    end
end

%算出斜率,然後斜率轉為角度,最後角度之差就是葉片的角度啦!

XieLv1=(first_dot1-first_dot2)/(Y1-Y2)
XieLv2=(second_dot1-second_dot2)/(Y1-Y2)
Angle=atan(XieLv1)*180/pi-atan(XieLv2)*180/pi複製程式碼

我知道肯定還有很多可以優化的地方,但是目前來說麼。實現了測試角度就好了麼~~我現在在小妹子這兒的圖書館陪她過雙十一,美滋滋啊,圖書館人好多,但是排插好少,而且燈光是昏黃的,讓人想睡覺!中評吧!

最後得出來的角度是44.4190°

之後我也測試了別的行數的資料,基本是形成了45°左右的正態分佈,至於更大的資料,我就懶得算了,其實也可以寫個小函式,統計下各個行數的時候會形成很多個值,然後求個平均 mean就好了!

還別說,偏差真的很大,我在想要不要真的寫個統計函式,然後畫個圖給老師看?搞不好有加分?

或者把很多點存起來,來個線性迴歸分析???but ,我還是先看書吧,這些都是隨便查得到的東西,就先不玩了!反正還沒到交作業的時候不是。

正文之後

有木有人要資源啊,matlab的或者別的都行哦,我現在看不完了。mmp,感覺自己真是個盜版文化的傳播者,but這些都是老掉牙的東西了。最新的都是2013的書了。再不找點人看估計都會滅絕吧!

書名我都給你準備好了。就怕你搜不到~

MATLAB+R2014a完全自學一本通
MATLAB影象處理.pdf
MATLAB R2016a完全自學一本通附贈電子書.pdf
精通Matlab數字影象處理與識別 [張錚,倪紅霞編著][人民郵電出版社][2013.04]
岡薩雷斯數字影象處理MATLAB版.中文版(第二版)2

(PS:當然,上面都是沒法下載的,只是給你看看簡介而已,要的點了喜歡後評論發郵箱,不過分吧?~~)


=========修改版========

Find_Angle.m

function [y]=Find_Angle(Y1,Y2,bw)
%下面省略的原因是一開始只准備測試一個角度,所以就單純的在一個m檔案裡面匯入物件,後來需要另外封裝下傳入邊緣檢測後的bw物件作為實參
%pic=imread('/Users/zhangzhaobo/program/MATLAB/First_work_angles.jpg');
% bw=im2bw(pic);
% bw=edge(bw,'canny'); 

% 按照我的四點構成兩直線的做法,下面分別是四個點的列數,行數在形參中傳入
first_dot1=0;
first_dot2=0;
second_dot1=0;
second_dot2=0;
% 遍歷給定行所有的item,然後查詢400-1300之間的元素(取點不可能在此範圍外),取兩點
for i=1:1600
    if (400 < i) && (i < 1300)
        if bw(Y1,i)==1
            if first_dot1>0  % 如果已經取過第一個點;那麼就取第二個同一行內的點
                second_dot1=i;
            else
                first_dot1=i; % 如果沒有取過第一個點,那麼就記錄第一個點
            end
        end
    end
end

% 相同步驟取第二行中的資料

for i=1:1600
    if (400 < i) && (i < 1300)
        if bw(Y2,i)==1
            if first_dot2>0
                second_dot2=i;
            else
                first_dot2=i;
            end
        end
    end
end

% 直接兩點求斜率
XieLv1=(first_dot1-first_dot2)/(Y1-Y2);
XieLv2=(second_dot1-second_dot2)/(Y1-Y2);

% 絕對座標系中由斜率算出絕對角度,然後相減得到相對角度
Angle=atan(XieLv1)*180/pi-atan(XieLv2)*180/pi;
% 判斷Angle是否合理,配合呼叫此函式的內容可以進行篩選
if (Angle>49) || (Angle<43)
    y=0;
else
    y=Angle;
end複製程式碼

Average.m

function [angle]=Average(pic) % 此函式用於求同一個扇葉的多次取點求直線夾角的過程
angle=0;  %初始化角度
count=0;  % 計數,用於最後的求平均
for i=(380:450)   % 我取 400行到500行之間的兩行,間隔最小20 最大50 ,間隔步長為2
    for j=(20:2:50)
        if Find_Angle(i,i+j,pic)==0  % 如果求出很大偏差的角度,直接剔除
            continue;
        else
            angle=angle+Find_Angle(i,i+j,pic);
            count=count+1;
        end
    end
end
angle=angle/count;  % 求平均,完成一個扇葉的角度平均 1050次複製程式碼

Find_4_Angles.m

clear; % 這個是總函式,類似於main 所以事前清除其他變數很有必要。
%讀取物件並且進行最有閾值的篩選,二值化,邊緣提取,刪掉邊緣利於旋轉葉片
pic=imread('First_work_angles.jpg');
thresh=graythresh(pic);
bw=im2bw(pic,thresh);
bw=edge(bw,'canny'); 
BW=bw(100:1700,420:2020);
%建立角度陣列,儲存四個葉片的角度
Angle=[0,0,0,0];
%每次求得角度後轉過90°再次求平均值
for i = 0:3
    BW=imrotate(BW,i*90);
    Angle(i+1)=Average(BW);
end
% 精度精確至3位有效陣列,即0.1°
digits(3)
Angles=vpa(Angle,3)複製程式碼

檔案結構如圖:

執行的時候直接輸入Find_4_Angles即可!

相關文章