訂閱
糾錯
加入自媒體

使用Python+OpenCV進行圖像處理(二)

梯度(Gradient)

在數(shù)學中,梯度用于幾何地表示多變量函數(shù)圖形的斜率。由于它是一個向量值函數(shù),代表著方向和大小兩種屬性。在這里,我們也可以將同樣的概念引入到圖像的像素值中。圖像梯度表示像素強度或顏色模式的方向變化,因此可以通過梯度來定位邊緣。

# Apply gradient filtering

sobel_x = cv2.Sobel(img, cv2.CV_64F, dx = 1, dy = 0, ksize = 5)

sobel_y = cv2.Sobel(img, cv2.CV_64F, dx = 0, dy = 1, ksize = 5)

blended = cv2.a(chǎn)ddWeighted(src1=sobel_x, alpha=0.5, src2=sobel_y,

beta=0.5, gamma=0)

laplacian = cv2.Laplacian(img, cv2.CV_64F)

Sobel運算同時使用高斯平滑和微分。我們通過cv2.Sobel()函數(shù)使用它,可以定義兩個不同的方向:垂直方向(sobelx)和水平方向(sobely)。dx和dy表示導數(shù)。當dx = 1時,通過計算像素值沿水平方向的導數(shù),從而進行圖像濾波。

通過函數(shù)cv2.a(chǎn)ddWeighted()對sobelx和sobely的兩種過濾器加權(quán)求和,可以實現(xiàn)兩個方向上的梯度求解及圖像濾波。上述代碼中兩種過濾器設定了相同的權(quán)重。

拉普拉斯運算使用的是x和y的二階導數(shù),數(shù)學表達式如下。

讓我們通過下方代碼更直觀的看看這些處理后圖像是什么樣的。

# Plot the images

images = [sobel_x, sobel_y, blended, laplacian]

plt.figure(figsize = (20, 20))

for i in range(4):

plt.subplot(1, 4, i+1)

plt.imshow(images[i], cmap = 'gray')

plt.a(chǎn)xis('off')

plt.show()

如上圖所示,第一幅和第二幅圖像均含有一個方向圖樣。在第一張圖中,我們可以清楚地看到垂直方向上的邊緣。在第二幅圖中,我們可以看到水平線。第三幅和第四幅圖像,兩個方向的邊緣都凸顯出來了。

形態(tài)轉(zhuǎn)換(Morpgological transformations)

通過濾波操作來轉(zhuǎn)換圖像的形態(tài)的技術(shù)稱為形態(tài)變換(morphological transformation)。首先,讓我們了解下腐蝕(erosion)和擴張(dilation)。

腐蝕(Erosion) 是一種縮小圖形形態(tài)的技術(shù),通常被應用在灰度圖上。過濾器的形狀可以是矩形、橢圓和交叉形狀。通過過濾器刪除給定區(qū)域下的全部0值。

代碼實現(xiàn)如下:

img = cv2.imread('simpson.jpg')

# Create erosion kernels

kernel_0 = np.ones((9, 9), np.uint8)

kernel_1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 9))

kernel_2 = cv2.getStructuringElement(cv2.MORPH_CROSS, (9, 9))

kernels = [kernel_0, kernel_1, kernel_2]

# Plot the images

plt.figure(figsize = (20, 20))

for i in range(3):

img_copy = img.copy()

img_copy = cv2.erode(img_copy, kernels[i], iterations = 3)

plt.subplot(1, 3, i+1)

plt.imshow(img_copy)

plt.a(chǎn)xis('off')

plt.show()

上圖形象的展示出不同濾波器下的不同縮放結(jié)果。我們可以看到三張分別使用基礎(方形)濾波器、橢圓形濾波器和交叉濾波器處理過的結(jié)果圖。可以看出其分別以“圓形”、“線性”和“對角線”的方式進行收縮。

擴張(Dilation)與侵蝕是相反的。它是一種對圖形形態(tài)進行放大的操作。其作用也與侵蝕相反。實現(xiàn)代碼如下。

# Apply dilation

kernel = np.ones((9, 9), np.uint8)

img_dilate = cv2.dilate(img, kernel, iterations = 3)

plt.figure(figsize = (20, 10))

plt.subplot(1, 2, 1); plt.imshow(img, cmap="gray")

plt.subplot(1, 2, 2); plt.imshow(img_dilate, cmap="gray")

plt.show()

開閉運算是侵蝕和擴張的混合形式。開運算是指先進行侵蝕,然后對侵蝕結(jié)果進行擴張操作。相對應的,閉運算是指先進行擴張,再進行侵蝕。

正如上圖所示,閉運算一般用于檢測圖形的整體輪廓,開運算用于檢測圖形的子模式(subpatterns)?梢允褂煤瘮(shù)cv2.morphologyEx()來實現(xiàn)這些操作。參數(shù)op用于指定使用哪種運算類型(開/閉)。完整代碼如下所示。

# Apply the operations

kernel = np.ones((9, 9), np.uint8)

img_open = cv2.morphologyEx(img, op= cv2.MORPH_OPEN, kernel)

img_close = cv2.morphologyEx(img, op= cv2.MORPH_CLOSE, kernel)

img_grad = cv2.morphologyEx(img, op= cv2.MORPH_GRADIENT, kernel)

img_tophat = cv2.morphologyEx(img, op= cv2.MORPH_TOPHAT, kernel)

img_blackhat = cv2.morphologyEx(img, op= cv2.MORPH_BLACKHAT, kernel)

# Plot the images

images = [img, img_open, img_close, img_grad,

img_tophat, img_blackhat]

fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (15, 15))

for ind, p in enumerate(images):

ax = axs[ind//3, ind%3]

ax.imshow(p, cmap = 'gray')

ax.a(chǎn)xis('off')

plt.show()

注意,原圖中的手在分別使用開閉操作進行處理時會產(chǎn)生不同的結(jié)果。梯度濾波(MORPHCGRADIENT)運算是計算擴張結(jié)果圖與腐蝕結(jié)果圖之差。頂帽(Top-h(huán)at)運算(MORPHTOPHAT)是計算開運算結(jié)果圖與原始圖像之差,黑帽(Black Hot)運算(MORPH_BLACKHAT)是計算閉運算結(jié)果圖與原始圖像之差。形態(tài)學運算詳細介紹參看(https://homepages.inf.ed.a(chǎn)c.uk/rbf/HIPR2/morops.htm)。

總結(jié)與展望

本篇介紹了OpenCV中幾項比較常用的運算。下篇將介紹輪廓檢測和人臉檢測等檢測技術(shù)。歡迎批評指正。

<上一頁  1  2  
聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權(quán)或其他問題,請聯(lián)系舉報。

發(fā)表評論

0條評論,0人參與

請輸入評論內(nèi)容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續(xù)

暫無評論

暫無評論

    掃碼關(guān)注公眾號
    OFweek人工智能網(wǎng)
    獲取更多精彩內(nèi)容
    文章糾錯
    x
    *文字標題:
    *糾錯內(nèi)容:
    聯(lián)系郵箱:
    *驗 證 碼:

    粵公網(wǎng)安備 44030502002758號