图像处理:python实现canny算子
生活随笔
收集整理的這篇文章主要介紹了
图像处理:python实现canny算子
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、Canny邊緣提取步驟
文中用python實現canny算子,Canny算子的步驟為:
- 1)圖像灰度預處理
- 2)對每個像素求梯度
- 3)求每個點處最大梯度的編碼
- 4)非極大值抑制,保證梯度編碼的唯一性。
- 5)通過閾值,將邊緣像素抽取出來;
二、高斯平滑算子代碼
? ? ? 在jupyter-notebook下,通過下列代碼學習,可以了解canny算子全過程;并按自己的理解進行修改學習:?
import numpy as np import math import matplotlib as mpl import matplotlib.pyplot as plt import seaborn as sns import cv2img = plt.imread('d:/images/mchine.jpg')%matplotlib inline sigma1 = sigma2 = 1 sum = 0 gaussian = np.zeros([5, 5]) for i in range(5):for j in range(5):gaussian[i, j] = math.exp(-1 / 2 * (np.square(i - 2) / np.square(sigma1) # 生成二維高斯分布矩陣+ (np.square(j - 2) / np.square(sigma2)))) / (2 * math.pi * sigma1 * sigma2)sum = sum + gaussian[i, j]gaussian = gaussian / sum sns.heatmap( gaussian )plt.show()顯示高斯平滑算子的熱圖。?
三、三通道圖轉換成灰度圖
def rgb2gray(rgb):return np.dot(rgb[..., :3], [0.299, 0.587, 0.114]) gray = rgb2gray(img) W, H = gray.shape sns.heatmap( gray )灰度變換后,圖像的熱圖:
?
四、生成梯度圖
new_gray = cv2.GaussianBlur(gray, (5, 5), 0) # step2.增強 通過求梯度幅值 W1, H1 = new_gray.shape dx = np.zeros([W1 - 1, H1 - 1]) dy = np.zeros([W1 - 1, H1 - 1]) d = np.zeros([W1 - 1, H1 - 1]) for i in range(W1 - 1):for j in range(H1 - 1):dx[i, j] = new_gray[i, j + 1] - new_gray[i, j]dy[i, j] = new_gray[i + 1, j] - new_gray[i, j]d[i, j] = np.sqrt(np.square(dx[i, j]) + np.square(dy[i, j])) # 圖像梯度幅值作為圖像強度值 sns.heatmap( d)梯度圖:?
?
五、非極大值抑制
5.1 canny算子的雙閾值原理
1) canny算子設定有兩個閾值,低閾值 和 高閾值
2) canny算子使每個像素點位置上能夠算出一個梯度值,稱為“實際梯度”
3)當 “實際梯度 > 高閾值” 該點被錄取為“邊緣點”
4)當 “實際梯度 <?低閾值” 該點被錄取為“非邊緣點(也叫背景點)”
5)當? ? “低閾值< 實際梯度低< 高閾值 ”? 情況復雜了,需要判別
? ? ? ? ? ? 如果周圍相鄰的點都沒有大于低閾值,該點被錄取為背景點(非邊緣點)。
? ? ? ? ? ??如果周圍相鄰的點都有大于低閾值的,就比較那個相鄰點和該點梯度,凡梯度大者被錄取為邊緣點。
( 不知以上敘述是否清楚?下圖,因為所有梯度都取絕對值,因此,梯度最小為0 )
?程序如下:
W2, H2 = d.shape NMS = np.copy(d) NMS[0, :] = NMS[W2 - 1, :] = NMS[:, 0] = NMS[:, H2 - 1] = 0 for i in range(1, W2 - 1):for j in range(1, H2 - 1):if d[i, j] == 0:NMS[i, j] = 0else:gradX = dx[i, j]gradY = dy[i, j]gradTemp = d[i, j]# 如果Y方向幅度值較大if np.abs(gradY) > np.abs(gradX):weight = np.abs(gradX) / np.abs(gradY)grad2 = d[i - 1, j]grad4 = d[i + 1, j]# 如果x,y方向梯度符號相同if gradX * gradY > 0:grad1 = d[i - 1, j - 1]grad3 = d[i + 1, j + 1]# 如果x,y方向梯度符號相反else:grad1 = d[i - 1, j + 1]grad3 = d[i + 1, j - 1]# 如果X方向幅度值較大else:weight = np.abs(gradY) / np.abs(gradX)grad2 = d[i, j - 1]grad4 = d[i, j + 1]# 如果x,y方向梯度符號相同if gradX * gradY > 0:grad1 = d[i + 1, j - 1]grad3 = d[i - 1, j + 1]# 如果x,y方向梯度符號相反else:grad1 = d[i - 1, j - 1]grad3 = d[i + 1, j + 1]gradTemp1 = weight * grad1 + (1 - weight) * grad2gradTemp2 = weight * grad3 + (1 - weight) * grad4if gradTemp >= gradTemp1 and gradTemp >= gradTemp2:NMS[i, j] = gradTempelse:NMS[i, j] = 0# plt.imshow(NMS, cmap = "gray")# step4. 雙閾值算法檢測、連接邊緣 W3, H3 = NMS.shape DT = np.zeros([W3, H3]) # 定義高低閾值 TL = 0.31 * np.max(NMS) TH = 0.4 * np.max(NMS)for i in range(1, W3 - 1):for j in range(1, H3 - 1):if (NMS[i, j] < TL):DT[i, j] = 0elif (NMS[i, j] > TH):DT[i, j] = 255elif ((NMS[i - 1, j - 1:j + 1] < TH).any() or (NMS[i + 1, j - 1:j + 1]).any()or (NMS[i, [j - 1, j + 1]] < TH).any()):DT[i, j] = 255 # newDT = DT.astype(np.uint8)cv2.imshow( "gray",DT) cv2.waitKey(0) cv2.destroyAllWindows() cv2.imwrite("parts4.jpg",DT)三、結果展示?
總結
以上是生活随笔為你收集整理的图像处理:python实现canny算子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 语音识别:时间序列的匹配算法(Needl
- 下一篇: 基因序列算法:编辑距离( Levensh