Python實(shí)現(xiàn)邊緣提取的示例代碼
復(fù)習(xí)
(1)梯度: 梯度的本意是一個(gè)向量(矢量),表示某一函數(shù)在該點(diǎn)處的方向?qū)?shù)沿著該方向取得最大值,即函數(shù)在該點(diǎn)處沿著該方向(此梯度的方向)變化最快,變化率最大(為該梯度的模)
(2)線性濾波 可以說(shuō)是 圖像處理 最基本的方法,它可以允許我們對(duì)圖像進(jìn)行處理,產(chǎn)生很多不同的效果
一、邊緣提取
1、什么是邊緣
圖象的邊緣是指圖象局部區(qū)域亮度變化顯著的部分,該區(qū)域的灰度剖面一般可以看作是一個(gè)階躍,一個(gè)灰度值在很小的緩沖區(qū)域內(nèi)急劇變化到另一個(gè)灰度相差較大的灰度值。
邊緣有正負(fù)之分,就像導(dǎo)數(shù)有正值也有負(fù)值一樣:由暗到亮為正,由亮到暗為負(fù).
求邊緣幅度的算法: sobel、 Roberts、 prewitt、 Laplacian、 Canny算子,Canny算子效果比其他的都要好,但是實(shí)現(xiàn)起來(lái)有點(diǎn)麻煩
2、什么是邊緣提取
邊緣提取,指數(shù)字圖像處理中,對(duì)于圖片輪廓的一個(gè)處理。對(duì)于邊界處,灰度值變化比較劇烈的地方,就定義為邊緣。也就是拐點(diǎn),拐點(diǎn)是指函數(shù)發(fā)生凹凸性變化的點(diǎn)。二階導(dǎo)數(shù)為零的地方。并不是一階導(dǎo)數(shù),因?yàn)橐浑A導(dǎo)數(shù)為零,表示是極值點(diǎn)。
邊緣提?。哼吘墮z測(cè)的基本思想首先是利用邊緣增強(qiáng)算子,突出圖像中的局部邊緣,然后定義象素的“邊緣強(qiáng)度”,通過(guò)設(shè)置閾值的方法提取邊緣點(diǎn)集。由于噪聲和模糊的存在,監(jiān)測(cè)到的邊界可能會(huì)變寬或在某點(diǎn)處發(fā)生間斷。因此,邊界檢測(cè)包括兩個(gè)基本內(nèi)容:
(1)用邊緣算子提取出反映灰度變化的邊緣點(diǎn)集。
(2)在邊緣點(diǎn)集合中剔除某些邊界點(diǎn)或填補(bǔ)邊界間斷點(diǎn),并將這些邊緣連接成完整的線。
邊緣定義:圖像灰度變化率最大的地方(圖像灰度值變化最劇烈的地方)。圖像灰度在表面法向變化的不連續(xù)造成的邊緣。一般認(rèn)為邊緣提取是要保留圖像的灰度變化劇烈的區(qū)域,這從數(shù)學(xué)上看,最直觀的方法就是微分(對(duì)于數(shù)字圖像來(lái)說(shuō)就是差分),在信號(hào)處理的角度來(lái)看,也可以說(shuō)是用高通濾波器,即保留高頻信號(hào)。
邊緣信息包含兩個(gè)方面:
1.像素的坐標(biāo)
2.邊緣的方向
(1)邊緣檢測(cè)
邊緣檢測(cè) 主要 是圖象的灰度變化的度量、檢測(cè)和定位。下邊兩幅圖展現(xiàn)出了邊緣檢測(cè)的效果。
邊緣檢測(cè)的應(yīng)用:語(yǔ)義分割和實(shí)例分割
語(yǔ)義分割:
實(shí)例分割:
(2)高頻信號(hào)&低頻信號(hào)
圖像中的低頻信號(hào)和高頻信號(hào)也叫做低頻分量和高頻分量。
簡(jiǎn)單一點(diǎn)說(shuō),圖像中的高頻分量,指的是圖像強(qiáng)度(亮度/灰度)變化劇烈的地方,也就是邊緣(輪廓);
圖像中的低頻分量,指的是圖像強(qiáng)度(亮度/灰度)變換平緩的地方,也就是大片色塊的地方。
人眼對(duì)圖像中的高頻信號(hào)更為敏感。
(3)邊緣檢測(cè)的原理和步驟
1)濾波:邊緣檢測(cè)的算法主要是基于圖像強(qiáng)度的一階和二階導(dǎo)數(shù),但導(dǎo)數(shù)通常對(duì)噪聲很敏感,因此必須采用濾波器來(lái)改善與噪聲有關(guān)的邊緣檢測(cè)器的性能。常見(jiàn)的濾波方法主要有高斯濾波。
2)增強(qiáng):增強(qiáng)邊緣的基礎(chǔ)是確定圖像各點(diǎn)鄰域強(qiáng)度的變化值。增強(qiáng)算法可以將圖像灰度點(diǎn)鄰域強(qiáng)度值有顯著變化的點(diǎn)凸顯出來(lái)。在具體編程實(shí)現(xiàn)時(shí),可通過(guò)計(jì)算梯度幅值來(lái)確定。
3)檢測(cè):經(jīng)過(guò)增強(qiáng)的圖像,往往鄰域中有很多點(diǎn)的梯度值比較大,而在特定的應(yīng)用中,這些點(diǎn)并不是我們要找的邊緣點(diǎn),所以應(yīng)該采用某種方法來(lái)對(duì)這些點(diǎn)進(jìn)行取舍。實(shí)際工程中,常用的方法是通過(guò)閾值化方法來(lái)檢測(cè)。
檢測(cè)原理:關(guān)于邊緣檢測(cè)的基礎(chǔ)來(lái)自于一個(gè)事實(shí), 即在邊緣部分,像素值出現(xiàn)”跳躍“或者較大的變化。 如果在此邊緣部分求取一階導(dǎo)數(shù),就會(huì)看到極值的出現(xiàn)。而在一階導(dǎo)數(shù)為極值的地方,二階導(dǎo)數(shù)為0,基于這個(gè)原理,就可以進(jìn)行邊緣檢測(cè)。
在邊緣部分求取一階導(dǎo)數(shù),你會(huì)看到極值的出現(xiàn):
如果在邊緣部分求二階導(dǎo)數(shù)會(huì)出現(xiàn)什么情況?
從上例中我們可以推論檢測(cè)邊緣可以通過(guò)定位梯度值大于鄰域的相素的方法找到(或者推廣到大于一個(gè)閥值).從以上分析中,我們推論二階導(dǎo)數(shù)可以用來(lái)檢測(cè)邊緣 。因?yàn)閳D像是 “2維”, 我們需要在兩個(gè)方向求導(dǎo)。
(4)圖像銳化
圖像銳化(image sharpening)是補(bǔ)償圖像的輪廓,增強(qiáng)圖像的邊緣及灰度跳變的部分,使圖像變得清晰。
圖像銳化是為了突出圖像上的物的邊緣、輪廓,或某些線性目標(biāo)要素的特征。這種濾波方法提高了地物邊緣與周圍像元之間的反差,因此也被稱為邊緣增強(qiáng)。
圖像銳化常使用的是拉普拉斯變換核函數(shù):
圖中右邊的模板它是根據(jù)上下左右四個(gè)90度方向的像素值來(lái)計(jì)算二階導(dǎo)的。如果想要加入斜對(duì)角上的像素來(lái)計(jì)算,可使用左邊的模板。
(5)圖像平滑
圖像平滑是指用于突出圖像的寬大區(qū)域、低頻成分、主干部分或抑制圖像噪聲和干擾高頻成分的圖像處理方法,目的是使圖像亮度平緩漸變,減小突變梯度,改善圖像質(zhì)量。
用Gx來(lái)卷積下面這張圖的話,就會(huì)在中間黑白邊界獲得比較大的值。
二、Sobel算子
Sobel算子是典型的基于一階導(dǎo)數(shù)的邊緣檢測(cè)算子,由于該算子中引入了類似局部平均的運(yùn)算,因此對(duì)噪聲具有平滑作用,能很好的消除噪聲的影響。Sobel算子對(duì)于像素的位置的影響做了加權(quán),因此與Prewitt算子相比效果更好。
Sobel算子包含兩組3x3的矩陣,分別為橫向及縱向模板,將之與圖像作平面卷積,即可分別得出橫向及縱向的亮度差分近似值。實(shí)際使用中,常用如下兩個(gè)模板來(lái)檢測(cè)圖像邊緣
缺點(diǎn)是Sobel算子并沒(méi)有將圖像的主題與背景嚴(yán)格地區(qū)分開(kāi)來(lái),換言之就是Sobel算子并沒(méi)有基于圖像灰度進(jìn)行處理,由于Sobel算子并沒(méi)有嚴(yán)格地模擬人的視覺(jué)生理特征,所以提取的圖像輪廓有時(shí)并不能令人滿意。
噪聲和邊緣都是灰度變化劇烈的地方,所以本質(zhì)相同,濾波不能過(guò)度,否則邊緣就減損了
Prewitt算子是一種一階微分算子的邊緣檢測(cè),利用像素點(diǎn)上下、左右鄰點(diǎn)的灰度差,在邊緣處達(dá)到極值檢測(cè)邊緣,去掉部分偽邊緣,對(duì)噪聲具有平滑作用 。其原理是在圖像空間利用兩個(gè)方向模板與圖像進(jìn)行鄰域卷積來(lái)完成的,這兩個(gè)方向模板一個(gè)檢測(cè)水平邊緣,一個(gè)檢測(cè)垂直邊緣。其原理與sobel算子一樣
三、Canny邊緣檢測(cè)算法
Canny是目前最優(yōu)秀的邊緣檢測(cè)算法( 在傳統(tǒng)的人工智能中不包括深度學(xué)習(xí) ),其目標(biāo)為找到一個(gè)最優(yōu)的邊緣,其最優(yōu)邊緣的定義為:
1、好的檢測(cè):算法能夠盡可能的標(biāo)出圖像中的實(shí)際邊緣
2、好的定位:標(biāo)識(shí)出的邊緣要與實(shí)際圖像中的邊緣盡可能接近
3、最小響應(yīng):圖像中的邊緣只能標(biāo)記一次
1、算法步驟
1. 對(duì)圖像進(jìn)行灰度化
2. 對(duì)圖像進(jìn)行高斯濾波:
根據(jù)待濾波的像素點(diǎn)及其鄰域點(diǎn)的灰度值按照一定的參數(shù)規(guī)則進(jìn)行加權(quán)平均。這樣
可以有效濾去理想圖像中疊加的高頻噪聲。
3. 檢測(cè)圖像中的水平、垂直和對(duì)角邊緣(如Prewitt, Sobel算子等)。
4. 對(duì)梯度幅值進(jìn)行非極大值抑制
5. 用雙閾值算法檢測(cè)和連接邊緣
2、高斯平滑
高斯平滑水平和垂直方向呈現(xiàn)高斯分布,更突出了中心點(diǎn)在像素平滑后的權(quán)重,相比于均值濾波而言,有著更好的平滑效果。
重要的是需要理解, 高斯卷積核大小的選擇將影響Canny檢測(cè)器的性能:尺寸越大,檢測(cè)器對(duì)噪聲的敏感度越低,但是邊緣檢測(cè)的定位誤差也將略有增加。 一般5x5是一個(gè)比較不錯(cuò)的trade off
3、非極大值抑制
非極大值抑制,簡(jiǎn)稱為NMS算法,英文為Non-Maximum Suppression。其思想是搜素局部最大值,抑制非極大值。NMS算法在不同應(yīng)用中的具體實(shí)現(xiàn)不太一樣,但思想是一樣的。
為什么要采用非極大值抑制?以目標(biāo)檢測(cè)為例:目標(biāo)檢測(cè)的過(guò)程中在同一目標(biāo)的位置上會(huì)產(chǎn)生大量的候選框,這些候選框相互之間可能會(huì)有重疊,此時(shí)我們需要利用非極大值抑制找到最佳的目標(biāo)邊界框,消除冗余的邊界框。
對(duì)于重疊的候選框,計(jì)算他們的重疊部分,若大于規(guī)定閾值,則刪除;低于閾值則保留。對(duì)于無(wú)重疊的候選框,都保留。
非極大值抑制:通俗意義上是指尋找像素點(diǎn)局部最大值,將非極大值點(diǎn)所對(duì)應(yīng)的灰度值置為0,這樣可以剔除掉一大部分非邊緣的點(diǎn)。
1) 將當(dāng)前像素的梯度強(qiáng)度與沿正負(fù)梯度方向上的兩個(gè)像素進(jìn)行比較。
2) 如果當(dāng)前像素的梯度強(qiáng)度與另外兩個(gè)像素相比最大,則該像素點(diǎn)保留為邊緣點(diǎn),否則該像素點(diǎn)將被抑制(灰度值置為0)。
dTmp1和dTmp2是兩個(gè)虛擬像素,也有稱亞像素點(diǎn),其由像素點(diǎn)通過(guò)雙線性插值算法求得的。
4、雙閾值檢測(cè)
用雙閾值算法檢測(cè)(滯后閾值):完成非極大值抑制后,會(huì)得到一個(gè)二值圖像,非邊緣的點(diǎn)灰度值均為0,可能為邊緣的局部灰度極大值點(diǎn)可設(shè)置其灰度為128(或其他)。這樣一個(gè)檢測(cè)結(jié)果還是包含了很多由噪聲及其他原因造成的假邊緣。因此還需要進(jìn)一步的處理。
• 如果邊緣像素的梯度值高于高閾值,則將其標(biāo)記為強(qiáng)邊緣像素;
• 如果邊緣像素的梯度值小于高閾值并且大于低閾值,則將其標(biāo)記為弱邊緣像素;
• 如果邊緣像素的梯度值小于低閾值,則會(huì)被抑制。
大于高閾值為強(qiáng)邊緣,小于低閾值不是邊緣。介于中間是弱邊緣。閾值的選擇取決于給定輸入圖像的內(nèi)容,也無(wú)法指定確定的值,只能去調(diào)試得到效果比較好的閾值。
抑制孤立低閾值點(diǎn):到目前為止,被劃分為強(qiáng)邊緣的像素點(diǎn)已經(jīng)被確定為邊緣,因?yàn)樗鼈兪菑膱D像中的真實(shí)邊緣中提取出來(lái)的。然而,對(duì)于弱邊緣像素,將會(huì)有一些爭(zhēng)論,因?yàn)檫@些像素可以從真實(shí)邊緣提取也可以是因噪聲或顏色變化引起的。
為了獲得準(zhǔn)確的結(jié)果,應(yīng)該抑制由后者引起的弱邊緣:
• 通常,由真實(shí)邊緣引起的弱邊緣像素將連接到強(qiáng)邊緣像素,而噪聲響應(yīng)未連接。
• 為了跟蹤邊緣連接,通過(guò)查看弱邊緣像素及其8個(gè)鄰域像素,只要其中一個(gè)為強(qiáng)邊緣像素,則該弱邊緣點(diǎn)就可以保留為真實(shí)的邊緣。
四、相關(guān)代碼
1、canny_detail.py
import numpy as np import matplotlib.pyplot as plt import math if __name__ == '__main__': pic_path = 'lenna.png' img = plt.imread(pic_path) if pic_path[-4:] == '.png': # .png圖片在這里的存儲(chǔ)格式是0到1的浮點(diǎn)數(shù),所以要擴(kuò)展到255再計(jì)算 img = img * 255 # 還是浮點(diǎn)數(shù)類型 img = img.mean(axis=-1) # 取均值就是灰度化了 # 1、高斯平滑 #sigma = 1.52 # 高斯平滑時(shí)的高斯核參數(shù),標(biāo)準(zhǔn)差,可調(diào) sigma = 0.5 # 高斯平滑時(shí)的高斯核參數(shù),標(biāo)準(zhǔn)差,可調(diào) dim = int(np.round(6 * sigma + 1)) # round是四舍五入函數(shù),根據(jù)標(biāo)準(zhǔn)差求高斯核是幾乘幾的,也就是維度 if dim % 2 == 0: # 最好是奇數(shù),不是的話加一 dim += 1 Gaussian_filter = np.zeros([dim, dim]) # 存儲(chǔ)高斯核,這是數(shù)組不是列表了 tmp = [i-dim//2 for i in range(dim)] # 生成一個(gè)序列 n1 = 1/(2*math.pi*sigma**2) # 計(jì)算高斯核 n2 = -1/(2*sigma**2) for i in range(dim): for j in range(dim): Gaussian_filter[i, j] = n1*math.exp(n2*(tmp[i]**2+tmp[j]**2)) Gaussian_filter = Gaussian_filter / Gaussian_filter.sum() dx, dy = img.shape img_new = np.zeros(img.shape) # 存儲(chǔ)平滑之后的圖像,zeros函數(shù)得到的是浮點(diǎn)型數(shù)據(jù) tmp = dim//2 img_pad = np.pad(img, ((tmp, tmp), (tmp, tmp)), 'constant') # 邊緣填補(bǔ) for i in range(dx): for j in range(dy): img_new[i, j] = np.sum(img_pad[i:i+dim, j:j+dim]*Gaussian_filter) plt.figure(1) plt.imshow(img_new.astype(np.uint8), cmap='gray') # 此時(shí)的img_new是255的浮點(diǎn)型數(shù)據(jù),強(qiáng)制類型轉(zhuǎn)換才可以,gray灰階 plt.axis('off') # 2、求梯度。以下兩個(gè)是濾波求梯度用的sobel矩陣(檢測(cè)圖像中的水平、垂直和對(duì)角邊緣) sobel_kernel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) sobel_kernel_y = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]) img_tidu_x = np.zeros(img_new.shape) # 存儲(chǔ)梯度圖像 img_tidu_y = np.zeros([dx, dy]) img_tidu = np.zeros(img_new.shape) img_pad = np.pad(img_new, ((1, 1), (1, 1)), 'constant') # 邊緣填補(bǔ),根據(jù)上面矩陣結(jié)構(gòu)所以寫1 for i in range(dx): for j in range(dy): img_tidu_x[i, j] = np.sum(img_pad[i:i+3, j:j+3]*sobel_kernel_x) # x方向 img_tidu_y[i, j] = np.sum(img_pad[i:i+3, j:j+3]*sobel_kernel_y) # y方向 img_tidu[i, j] = np.sqrt(img_tidu_x[i, j]**2 + img_tidu_y[i, j]**2) img_tidu_x[img_tidu_x == 0] = 0.00000001 angle = img_tidu_y/img_tidu_x plt.figure(2) plt.imshow(img_tidu.astype(np.uint8), cmap='gray') plt.axis('off') # 3、非極大值抑制 img_yizhi = np.zeros(img_tidu.shape) for i in range(1, dx-1): for j in range(1, dy-1): flag = True # 在8鄰域內(nèi)是否要抹去做個(gè)標(biāo)記 temp = img_tidu[i-1:i+2, j-1:j+2] # 梯度幅值的8鄰域矩陣 if angle[i, j] <= -1: # 使用線性插值法判斷抑制與否 num_1 = (temp[0, 1] - temp[0, 0]) / angle[i, j] + temp[0, 1] num_2 = (temp[2, 1] - temp[2, 2]) / angle[i, j] + temp[2, 1] if not (img_tidu[i, j] > num_1 and img_tidu[i, j] > num_2): flag = False elif angle[i, j] >= 1: num_1 = (temp[0, 2] - temp[0, 1]) / angle[i, j] + temp[0, 1] num_2 = (temp[2, 0] - temp[2, 1]) / angle[i, j] + temp[2, 1] if not (img_tidu[i, j] > num_1 and img_tidu[i, j] > num_2): flag = False elif angle[i, j] > 0: num_1 = (temp[0, 2] - temp[1, 2]) * angle[i, j] + temp[1, 2] num_2 = (temp[2, 0] - temp[1, 0]) * angle[i, j] + temp[1, 0] if not (img_tidu[i, j] > num_1 and img_tidu[i, j] > num_2): flag = False elif angle[i, j] < 0: num_1 = (temp[1, 0] - temp[0, 0]) * angle[i, j] + temp[1, 0] num_2 = (temp[1, 2] - temp[2, 2]) * angle[i, j] + temp[1, 2] if not (img_tidu[i, j] > num_1 and img_tidu[i, j] > num_2): flag = False if flag: img_yizhi[i, j] = img_tidu[i, j] plt.figure(3) plt.imshow(img_yizhi.astype(np.uint8), cmap='gray') plt.axis('off') # 4、雙閾值檢測(cè),連接邊緣。遍歷所有一定是邊的點(diǎn),查看8鄰域是否存在有可能是邊的點(diǎn),進(jìn)棧 lower_boundary = img_tidu.mean() * 0.5 high_boundary = lower_boundary * 3 # 這里我設(shè)置高閾值是低閾值的三倍 zhan = [] for i in range(1, img_yizhi.shape[0]-1): # 外圈不考慮了 for j in range(1, img_yizhi.shape[1]-1): if img_yizhi[i, j] >= high_boundary: # 取,一定是邊的點(diǎn) img_yizhi[i, j] = 255 zhan.append([i, j]) elif img_yizhi[i, j] <= lower_boundary: # 舍 img_yizhi[i, j] = 0 while not len(zhan) == 0: temp_1, temp_2 = zhan.pop() # 出棧 a = img_yizhi[temp_1-1:temp_1+2, temp_2-1:temp_2+2] if (a[0, 0] < high_boundary) and (a[0, 0] > lower_boundary): img_yizhi[temp_1-1, temp_2-1] = 255 # 這個(gè)像素點(diǎn)標(biāo)記為邊緣 zhan.append([temp_1-1, temp_2-1]) # 進(jìn)棧 if (a[0, 1] < high_boundary) and (a[0, 1] > lower_boundary): img_yizhi[temp_1 - 1, temp_2] = 255 zhan.append([temp_1 - 1, temp_2]) if (a[0, 2] < high_boundary) and (a[0, 2] > lower_boundary): img_yizhi[temp_1 - 1, temp_2 + 1] = 255 zhan.append([temp_1 - 1, temp_2 + 1]) if (a[1, 0] < high_boundary) and (a[1, 0] > lower_boundary): img_yizhi[temp_1, temp_2 - 1] = 255 zhan.append([temp_1, temp_2 - 1]) if (a[1, 2] < high_boundary) and (a[1, 2] > lower_boundary): img_yizhi[temp_1, temp_2 + 1] = 255 zhan.append([temp_1, temp_2 + 1]) if (a[2, 0] < high_boundary) and (a[2, 0] > lower_boundary): img_yizhi[temp_1 + 1, temp_2 - 1] = 255 zhan.append([temp_1 + 1, temp_2 - 1]) if (a[2, 1] < high_boundary) and (a[2, 1] > lower_boundary): img_yizhi[temp_1 + 1, temp_2] = 255 zhan.append([temp_1 + 1, temp_2]) if (a[2, 2] < high_boundary) and (a[2, 2] > lower_boundary): img_yizhi[temp_1 + 1, temp_2 + 1] = 255 zhan.append([temp_1 + 1, temp_2 + 1]) for i in range(img_yizhi.shape[0]): for j in range(img_yizhi.shape[1]): if img_yizhi[i, j] != 0 and img_yizhi[i, j] != 255: img_yizhi[i, j] = 0 # 繪圖 plt.figure(4) plt.imshow(img_yizhi.astype(np.uint8), cmap='gray') plt.axis('off') # 關(guān)閉坐標(biāo)刻度值 plt.show()
2、借助opencv庫(kù)實(shí)現(xiàn)的:canny.py
#!/usr/bin/env python # encoding=gbk import cv2 import numpy as np ''' cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]]) 必要參數(shù): 第一個(gè)參數(shù)是需要處理的原圖像,該圖像必須為單通道的灰度圖; 第二個(gè)參數(shù)是滯后閾值1; 第三個(gè)參數(shù)是滯后閾值2。 ''' img = cv2.imread("lenna.png", 1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imshow("canny", cv2.Canny(gray, 200, 300)) cv2.waitKey() cv2.destroyAllWindows()
3、優(yōu)化后的程序:canny_track.py
#!/usr/bin/env python # encoding=gbk ''' Canny邊緣檢測(cè):優(yōu)化的程序 ''' import cv2 import numpy as np def CannyThreshold(lowThreshold): detected_edges = cv2.GaussianBlur(gray,(3,3),0) #高斯濾波 detected_edges = cv2.Canny(detected_edges, lowThreshold, lowThreshold*ratio, apertureSize = kernel_size) #邊緣檢測(cè) # just add some colours to edges from original image. dst = cv2.bitwise_and(img,img,mask = detected_edges) #用原始顏色添加到檢測(cè)的邊緣上 cv2.imshow('canny demo',dst) lowThreshold = 0 max_lowThreshold = 100 ratio = 3 kernel_size = 3 img = cv2.imread('lenna.png') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #轉(zhuǎn)換彩色圖像為灰度圖 cv2.namedWindow('canny demo') #設(shè)置調(diào)節(jié)杠, ''' 下面是第二個(gè)函數(shù),cv2.createTrackbar() 共有5個(gè)參數(shù),其實(shí)這五個(gè)參數(shù)看變量名就大概能知道是什么意思了 第一個(gè)參數(shù),是這個(gè)trackbar對(duì)象的名字 第二個(gè)參數(shù),是這個(gè)trackbar對(duì)象所在面板的名字 第三個(gè)參數(shù),是這個(gè)trackbar的默認(rèn)值,也是調(diào)節(jié)的對(duì)象 第四個(gè)參數(shù),是這個(gè)trackbar上調(diào)節(jié)的范圍(0~count) 第五個(gè)參數(shù),是調(diào)節(jié)trackbar時(shí)調(diào)用的回調(diào)函數(shù)名 ''' cv2.createTrackbar('Min threshold','canny demo',lowThreshold, max_lowThreshold, CannyThreshold) CannyThreshold(0) # initialization if cv2.waitKey(0) == 27: #wait for ESC key to exit cv2 cv2.destroyAllWindows()
到此這篇關(guān)于Python實(shí)現(xiàn)邊緣提取的示例代碼的文章就介紹到這了,更多相關(guān)Python邊緣提取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python?AutoViz庫(kù)一行代碼實(shí)現(xiàn)可視化數(shù)據(jù)集
這篇文章主要介紹了python?AutoViz庫(kù)一行代碼實(shí)現(xiàn)可視化數(shù)據(jù)集實(shí)例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01簡(jiǎn)介Python設(shè)計(jì)模式中的代理模式與模板方法模式編程
這篇文章主要介紹了Python設(shè)計(jì)模式中的代理模式與模板方法模式編程,文中舉了兩個(gè)簡(jiǎn)單的代碼片段來(lái)說(shuō)明,需要的朋友可以參考下2016-02-02Python集成開(kāi)發(fā)環(huán)境Pycharm的使用及技巧
本文詳細(xì)講解了Python集成開(kāi)發(fā)環(huán)境Pycharm的使用及技巧,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06

Python打開(kāi)指定網(wǎng)頁(yè)使用requests模塊爬蟲示例詳解