echarts怎么控制一个点沿着折线移动_计算机怎么识别图像中的直线?
1
直線檢測(cè)問題
在紙上畫一條直線,用手機(jī)拍下照片,把照片交給計(jì)算機(jī)識(shí)別。
計(jì)算機(jī)是如何知道這張照片中的這條直線的?
存在直線嗎?
直線在哪里?
點(diǎn)、線、面是基本的幾何元素。
歐幾里得在《幾何原本》中寫道:
直線是點(diǎn)朝一個(gè)方向以及反方向的無限平鋪。
一條直線在圖像中,每個(gè)人一眼就能看出來。
我們不僅能夠說出圖像中存在一條直線,還可以說出直線經(jīng)過哪個(gè)點(diǎn),以及直線的方向。
如果有多條直線,我們還能說出直線之間的關(guān)系,相交還是(近似)平行,交點(diǎn)在哪里……
計(jì)算機(jī)怎么識(shí)別圖像中的直線?
計(jì)算機(jī)的常規(guī)方法是提取邊緣點(diǎn),之后檢測(cè)直線。
2
灰度矩陣與直線的灰度特征
計(jì)算機(jī)接收到一張照片,獲得一個(gè)對(duì)應(yīng)圖像的灰度矩陣。
矩陣是一格一格的,一格稱為一個(gè)像素(pixel)。
矩陣的橫、縱坐標(biāo)是離散化的。
矩陣中的元素是量化的值,從0到255,該值稱為灰度。
灰度,也稱亮度,是該點(diǎn)受到光照亮度的對(duì)應(yīng)數(shù)字。
如果是彩色的照片,對(duì)于計(jì)算機(jī)來說就是3張灰度圖,即3個(gè)灰度矩陣。
按順序分別是紅的、綠的和藍(lán)的灰度圖。
因?yàn)樵跀z像機(jī)成像元件(CCD或CMOS)前面嵌有拜爾濾鏡(如下圖所示),使得三種顏色(即波長)的光進(jìn)入到不同的灰度圖中。
顯示時(shí),三種顏色同時(shí)顯示,由于紅、綠、藍(lán)挨得很近,遠(yuǎn)處看就是彩色的。
1975年柯達(dá)美國分公司申請(qǐng)了拜爾濾鏡發(fā)明專利(US3971065),1976年獲得授權(quán)。
下面是一張灰度圖:
計(jì)算機(jī)的數(shù)據(jù)用Matlab軟件顯示出來:
白色直線——灰度呈山峰形貌(黑色直線——灰度呈裂縫形貌)。
下面是兩塊鋼板拼在一起的灰度圖,中間有條直線(接縫),如何進(jìn)行識(shí)別直線?
3
邊緣檢測(cè)原理
首先對(duì)灰度矩陣進(jìn)行邊緣提取。
邊緣就是圖像中灰度值變化大的點(diǎn),凡是差值大于一定程度就當(dāng)作邊緣點(diǎn)。
在灰度矩陣中沿著水平方向從左到右移動(dòng)當(dāng)前位置,
從第二個(gè)像素開始,將該位置左右兩個(gè)像素作差分,后者減去前者的灰度差存在另一個(gè)結(jié)果矩陣中對(duì)應(yīng)當(dāng)前位置處,直到倒數(shù)第二個(gè)像素為止,這樣就獲得了水平方向的邊緣點(diǎn)差分結(jié)果矩陣。
沿著垂直方向也如此,獲得垂直方向的邊緣點(diǎn)差分結(jié)果矩陣。
有人覺得這樣還不能精準(zhǔn)找到邊緣點(diǎn),所以在上述思想上進(jìn)行了修正,給出了索貝爾(Sobel)方法。
Sobel方法是將如下的左邊小矩陣扣到灰度矩陣上,將上下對(duì)應(yīng)項(xiàng)相乘再相加,得數(shù)就是這個(gè)中間位置處的水平差分結(jié)果,放入到水平差分結(jié)果矩陣中存儲(chǔ),然后移動(dòng)該小矩陣向右,直到一行都完成這樣的運(yùn)算,再下移一行進(jìn)行……直到全部算完,獲得水平結(jié)果矩陣。
下方的右邊小矩陣如法炮制,可以獲得垂直結(jié)果矩陣。
這是在圖像上進(jìn)行計(jì)算的典型做法——鄰域計(jì)算,鄰域計(jì)算所用到的上述小矩陣被稱為“算子”。
上面給出的是Sobel算子,分為x方向和y方向兩種算子。
算子不同,得到的處理不同。
下面是Sobel算子與Prewitt算子對(duì)比:
在邊緣檢測(cè)領(lǐng)域,有roberts算子、canny算子、log算子、laplacian算子……
用不同的算子會(huì)得到不同的結(jié)果。
如果邊緣點(diǎn)的方向是傾斜的(既不水平也不垂直),在上述兩個(gè)矩陣中就容易不明顯,為了找到這些邊緣點(diǎn),還需要將上述兩個(gè)矩陣進(jìn)行一個(gè)整合。
整合辦法是:
將上述兩個(gè)矩陣的對(duì)應(yīng)元素平方和、相加,再開根號(hào),
這樣就得到了全方向的邊緣點(diǎn)差分結(jié)果矩陣。
整合公式:
包括了任意方向的灰度差分結(jié)果矩陣。
該差分結(jié)果矩陣將邊緣點(diǎn)凸顯出來。
接著進(jìn)行二值化:
將上述邊緣點(diǎn)差分結(jié)果矩陣進(jìn)行二值化:
凡是邊緣點(diǎn)差分大于某個(gè)事先預(yù)定的值(稱為閾值)就當(dāng)作邊緣點(diǎn),設(shè)其值為1,非邊緣點(diǎn)設(shè)值為0。
從而獲得一個(gè)元素值只有1或0的黑白圖像。
下圖為采用Sobel方法進(jìn)行邊緣提取得到的黑白圖像。
閾值的取值需要慎重:
如果閾值取得過小,會(huì)將大量不是邊緣的點(diǎn)當(dāng)作邊緣點(diǎn)。
如果閾值取得過大,會(huì)將大量是邊緣的點(diǎn)忽略掉。
閾值取得過小的結(jié)果:
4
最小二乘法
接下來的任務(wù)是:
在上述邊緣點(diǎn)黑白圖像中識(shí)別出直線。
有一種方法是用于找到多個(gè)點(diǎn)的擬合直線的,叫做最小二乘法。
最小二乘法就是找到一條直線,該直線到各點(diǎn)的距離之和最短。
但是這種方法不適用于邊緣點(diǎn)黑白圖中識(shí)別直線,
原因是邊緣點(diǎn)有不少存在錯(cuò)誤,即存在噪點(diǎn),
一個(gè)偏離直線很遠(yuǎn)的點(diǎn)可能被錯(cuò)認(rèn)為是邊緣點(diǎn),
而且在直線兩側(cè)的點(diǎn)的數(shù)量也不一樣多,
都會(huì)導(dǎo)致最小二乘法找不出正確的直線。
噪點(diǎn)存在的原因是多方面的,很難沒有一個(gè)噪點(diǎn):
1)光線總是或多或少的照進(jìn)攝像機(jī);
2)鏡頭畸變,弧面精度有限,玻璃材質(zhì)均勻程度偏差導(dǎo)致折射率有變化;
3)攝像機(jī)電路干擾、電磁影響;
4)邊緣點(diǎn)提取時(shí)閾值選擇不當(dāng)會(huì)帶來大量噪點(diǎn)……
因此最小二乘法無法在存在大量錯(cuò)誤點(diǎn)的情況下找到直線。
5
哈夫變換
大量采用的直線檢測(cè)的方法是哈夫變換。
哈夫變換(Hough Transform, 簡稱HT,又譯作霍夫變換)可以找到經(jīng)過點(diǎn)最多的直線。
在計(jì)算機(jī)視覺和圖像處理領(lǐng)域,哈夫變換作為一種形狀分析技術(shù)被廣泛應(yīng)用。
哈夫變換是1959年由Paul Hough申請(qǐng)的美國發(fā)明專利技術(shù),1962年獲得授權(quán)。
Hough發(fā)明專利的名稱為:
Method and Means for Recognizing Complex Patterns(用于識(shí)別復(fù)雜圖案的方法和手段)
拿穿羊肉串打個(gè)比方,就是要找到羊肉穿得最多的竹簽。
經(jīng)過邊緣點(diǎn)最多的直線就是要找的直線。
這個(gè)方法可以有效克服噪點(diǎn)的影響,
因?yàn)樵朦c(diǎn)往往不在直線上,噪點(diǎn)的數(shù)量一般是少于經(jīng)過直線上的點(diǎn)的。
如果噪點(diǎn)的數(shù)量多于經(jīng)過直線上的點(diǎn),是什么情況?
就是人眼也分辨不出該直線了,
這種情況出現(xiàn)在前面的邊緣點(diǎn)提取環(huán)節(jié),灰度跳變的閾值選小了。
哈夫變換方法怎么做的呢?
哈夫變換方法是:
利用直線參數(shù)方程:
建立一個(gè)對(duì)應(yīng)的哈夫空間。
哈夫空間的橫坐標(biāo)是直線相對(duì)于坐標(biāo)橫軸的角度,
而縱坐標(biāo)是坐標(biāo)原點(diǎn)到直線的垂足長度。
這樣一來,每個(gè)直角坐標(biāo)空間的點(diǎn)都對(duì)應(yīng)哈夫空間中的一條正弦曲線,
反之,每個(gè)哈夫空間中的點(diǎn)都對(duì)應(yīng)直角坐標(biāo)空間中的一條直線。
這個(gè)變換稱為哈夫變換。
哈夫變換就是直角坐標(biāo)空間(也稱為笛卡爾空間)與極坐標(biāo)空間的變換。
哈夫變換將每個(gè)邊緣點(diǎn)換算成為哈夫空間的正弦曲線,
多個(gè)邊緣點(diǎn)就有多條正弦曲線,
哈夫空間中的這些正弦曲線的交點(diǎn),
對(duì)應(yīng)于經(jīng)過了最多點(diǎn)的一條直線。
下圖為哈夫變換得到的哈夫空間結(jié)果:
存在一個(gè)高聳的塔尖,塔尖這一點(diǎn)的高度就是投票數(shù),說明有最多的點(diǎn)在對(duì)應(yīng)該點(diǎn)的直線上,塔尖這一點(diǎn)在哈夫空間中的角度值、垂足距離值可以首先得到,用參數(shù)方程就得到了對(duì)應(yīng)的直線。
在原來邊緣點(diǎn)圖像中找直線的任務(wù),就轉(zhuǎn)換成在對(duì)應(yīng)的哈夫空間中找最多正弦曲線的交點(diǎn)的任務(wù)。
計(jì)算機(jī)善于找最大值或最小值,
模模糊糊、大約多少的事情計(jì)算機(jī)不擅長。
如何找最多曲線的交點(diǎn)?
計(jì)算機(jī)采用投票的方式,
哈夫空間中,正弦曲線經(jīng)過的每個(gè)小格子里都會(huì)投上一票,
當(dāng)所有的邊緣點(diǎn)對(duì)應(yīng)的正弦曲線都畫完,則投票結(jié)束,
數(shù)數(shù)得票數(shù),就找到了得票最多的那個(gè)點(diǎn)。
有了這個(gè)點(diǎn),其對(duì)應(yīng)的直線參數(shù)也就找到了,
直線也就識(shí)別出來了。
直線識(shí)別的結(jié)果(白線)疊加在原圖上:
之所以劃分很多格子,
是因?yàn)橛?jì)算機(jī)只能做量化計(jì)算。
每個(gè)格子的邊長稱為步長(或周期)。
一個(gè)是直線角度的步長,
另一個(gè)是垂足距離的步長。
步長越小,計(jì)算得越精確,
但是耗時(shí)間就越長。
不僅直線可以通過哈夫變換來檢測(cè),圓也可以通過哈夫變換來識(shí)別。
凡是能夠有確定的解析式的曲線,也都可以使用哈夫變換的方法來檢測(cè)。
哈夫變換還可以識(shí)別多條直線、多個(gè)圓弧。
哈夫變換是圖像處理中從圖像中識(shí)別幾何形狀的基本方法之一。
哈夫變換的基本原理在于利用點(diǎn)與線的對(duì)偶性,將原始圖像空間的給定的曲線通過曲線表達(dá)形式變?yōu)閰?shù)空間的一個(gè)點(diǎn),從而把原始圖像中給定曲線的檢測(cè)問題轉(zhuǎn)化為尋找參數(shù)空間中的峰值問題。可以適用于直線、橢圓、圓等。
6
哈夫變換教程視頻
來看看哈夫變換的教程視頻:
7
哈夫變換的不足
哈夫變換方法存在一個(gè)問題:效率低。
因?yàn)楣蜃儞Q方法需要將每個(gè)點(diǎn)對(duì)應(yīng)的正弦曲線畫在哈夫空間中,
一個(gè)點(diǎn)就要畫出179根線(如果是步長為1度的話),
每個(gè)點(diǎn)都這樣做一遍,
計(jì)算量比較大,程序運(yùn)行耗時(shí)長。
因此哈夫變換方法也被人取了一個(gè)綽號(hào):咖啡方法。
一杯咖啡慢悠悠地喝完了,
哈夫變換的計(jì)算結(jié)果才姍姍來遲。
8
哈夫變換改進(jìn)方法
人們針對(duì)哈夫變換方法提出了多種改進(jìn)措施,
于是產(chǎn)生了隨機(jī)哈夫變換、快速哈夫變換、隨機(jī)快速哈夫變換等。
在產(chǎn)生了這些改進(jìn)的哈夫變換后,
原來的哈夫變換就被定義為:
標(biāo)準(zhǔn)哈夫變換。
隨機(jī)哈夫變換方法是隨機(jī)找邊緣點(diǎn)來進(jìn)行哈夫變換,
在不斷運(yùn)行的過程中,就會(huì)找到交于一點(diǎn)的直線數(shù)量逐漸上升,
當(dāng)直線數(shù)量達(dá)到預(yù)設(shè)的一個(gè)數(shù)值時(shí),就終止程序,
認(rèn)為此時(shí)已經(jīng)找到了該直線。
這個(gè)方法有一定的風(fēng)險(xiǎn)性,
只要交于一點(diǎn)的直線數(shù)量足夠的大就好,
風(fēng)險(xiǎn)雖然仍然存在,但是已經(jīng)很小。
快速哈夫變換方法是將兩個(gè)點(diǎn)一同拿來做哈夫變換。
因?yàn)閮牲c(diǎn)有且僅有一條直線,
因此用該直線在哈夫空間去繪制一個(gè)點(diǎn),
這樣計(jì)算量就大大降低了。
原來標(biāo)準(zhǔn)哈夫變換方法需要畫出整條正弦曲線,
兩個(gè)點(diǎn)就是兩條正弦曲線,
現(xiàn)在只用在哈夫空間畫出兩個(gè)點(diǎn)所在直線的一個(gè)點(diǎn)即可。
8
哈夫變換Matlab程序
事先拍攝一張照片,存為灰度圖像,名為a1.bmp,將其放在下面的程序同一個(gè)文件夾中。打開Matlab,將下面的程序新建一個(gè)腳本文件,運(yùn)行該文件。
%Hough detection
clear;? ? ? ? ? %清除上次運(yùn)行的所有變量
close all;? ? ?%關(guān)閉上次運(yùn)行的子窗口
%=====下面讀取原圖并顯示
I1 = imread('a1.bmp');? ? ?%事先有張灰度圖,名為a1.bmp
figure(1),imshow(I1)? ? ? ? ?%將圖像顯示出來
I2 = im2double(I1);? ? ? ? ? %將圖片的數(shù)據(jù)類型從unit8變?yōu)閐ouble型,只有這樣回?cái)⒉拍苓M(jìn)行處理
%=====下面進(jìn)行Sobel方法的邊緣提取并顯示
I_edge = edge(I2,'sobel');? %邊緣提取,采用Sobel方法
figure(2),imshow(I_edge)? ?%將結(jié)果圖像顯示出來
%=====輸入源圖像大小
image_y_max=570;
image_x_max = 760;
%=====輸入搜索初始角度
alpha_initial = 100;
%=====輸入搜索步長角度
thelta_step = 1;
%=====輸入搜索總角度范圍
total_angle_for_search = 180;
m = round(total_angle_for_search/thelta_step+1);
%=====初始化hough投票矩陣,未防止計(jì)算的lamda距離超出矩陣,設(shè)置一個(gè)大的矩陣
n=2000;
M_hough=zeros(n,m);
%=====防止距離為負(fù)
lamda_initial =round(n/2);
%=====對(duì)每個(gè)像素操作
for x = 1 : image_x_max - 1
? ? for y = 1 : image_y_max - 1?
%=====轉(zhuǎn)換為矩陣下標(biāo)的坐標(biāo)系
? ? ? ? u = -y + image_y_max;
? ? ? ? v=x;
%=====如果有點(diǎn),就投票
? ? ? ? if I_edge(u,v) == 1
? ? ? ? %======循環(huán)m次,直線旋轉(zhuǎn)投票
? ? ? ? ? ? for k = 1 : m-1
%=====計(jì)算角度
? ? ? ? ? ? ? ? alpha1 = alpha_initial + k*thelta_step;
? ? ? ? ? ? ? ? alpha1 = round(alpha1);
%=====計(jì)算距離
? ? ? ? ? ? ? ? lamda1 = x*cos(alpha1*pi/180)+y*sin(alpha1*pi/180);
? ? ? ? ? ? ? ? lamda1 = round(lamda1);? ? ?
? ? ? ? ? ? ?M_hough(lamda_initial + lamda1,k) = M_hough(lamda_initial + lamda1,k) + 1;
? ? ? ? ? ? end
? ? ? ? end
? ? end
end
%=====顯示M_hough矩陣
figure(5),mesh(M_hough);
%======取出最大值所在的行、列
[rm,km]=find(M_hough == max(max(M_hough)))
%=====計(jì)算該點(diǎn)原距離
rm = rm - lamda_initial;
%draw the line
%=====計(jì)算該點(diǎn)原角度
alpha_line = alpha_initial + km*thelta_step
alpha_line_rad = alpha_line*pi/180;
lamda_line = rm/sin(alpha_line_rad);
%=====在原圖像上重疊畫出該直線
for x=1:image_x_max-1
?%=====直線方程式
? ? y = -x*(1/tan(alpha_line_rad))+lamda_line;
?%=====只畫在圖像中的直線
? ? if y <= image_y_max - 1
? ? ? ? if y >= 1
? ? ? ? ? ? v = x;
? ? ? ? ? ? u = -y + image_y_max;
? ? ? ? ? ? u = round(u);
? ? ? ? ? ? I2(u,v) = 255;
? ? ? ? end
? ? end
end
%=====顯示檢測(cè)結(jié)果
figure(6),imshow(I2);
關(guān)于圖像上的直線檢測(cè),你是否還有更好的辦法呢?
總結(jié)
以上是生活随笔為你收集整理的echarts怎么控制一个点沿着折线移动_计算机怎么识别图像中的直线?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 子类实例化基类 基类使用不了子类的
- 下一篇: three.js加载3d模型_可加载5亿