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

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