天天看點

圖像梯度算子的本質

前面我們介紹過圖像的梯度,其定義是根據微積分的定義在二維離散函數中推導出來的。但是,我們需要了解,梯度隻是一個工具,方法,核心目的是得到像素點與其相鄰像素的灰階值變化情況,并通過這種變化來增強圖像。這種原始定義的梯度隻是這種灰階值變化情況的度量工具。

我們再回顧一下,假設某像素與其8領域用如下矩陣表示:

圖像梯度算子的本質

那麼,根據圖像梯度的定義:

gx = z8 - z5

gy = z6 - z5

上面提到,這種原始定義的梯度隻是這種灰階值變化情況的度量工具,這種度量工具隻有這一種嗎?顯然不是的!

z9-z5算不算灰階值的變化?z1-z5呢?z7-z5呢?z4-z5呢?z3-z5呢?

我們利用梯度的本質目的,是要找到某像素與其相鄰像素的灰階內插補點,并放大這種內插補點,進而用于圖像增強。而原始定義的梯度計算方法隻是灰階內插補點計算方法中的一種,還可以有其它計算方法來度量這種變化。

為簡化起見,我們把這些計算方法統稱為梯度算子。根據不同的相鄰像素內插補點計算得到的效果可能有所不同,但基本原理是一緻的。

例如羅伯特(Roberts)交叉梯度算子,定義的是:

gx = z9-z5

gy = z8-z6

為什麼名字中有“交叉”,看看下圖就知道了。

圖像梯度算子的本質

我們可以看到,不管是原始梯度也好,Roberts算子也好,都隻是利用了z5,z6,z8,z9的像素值,那麼可不可以擴充到8領域呢,當然是可以的。

例如,你可以自己定義一個:

gx = (z7+z8+z9)-(z1+z2+z3)

gy = (z3+z6+z9)-(z1+z4+z7)

圖像梯度算子的本質

事實上,這個你自定義的算子和著名的Sobel算子非常接近了,隻是Sobel算子增加了距離權重而已。Sobel算子的定義如下(與中心點Z5更近的點Z3,Z4,Z6,Z8的權重為2,其它對角線上的權重為1):

gx = (z7+2*z8+z9)-(z1+2*z2+z3)

gy = (z3+2*z6+z9)-(z1+2*z4+z7)

關于Sobel算子後面還會再重點介紹,下面用Roberts交叉算子來看看圖像增強的效果。

import cv2
import numpy as np

moon = cv2.imread("moon.tif", )
row, column = moon.shape
moon_f = np.copy(moon)
moon_f = moon_f.astype("float")

Roberts = np.zeros((row, column))

for x in range(row - ):
    for y in range(column - ):
        gx = abs(moon_f[x + , y + ] - moon_f[x, y])
        gy = abs(moon_f[x + , y] - moon_f[x, y + ])
        Roberts[x, y] = gx + gy

sharp = moon_f + Roberts
sharp = np.where(sharp < , , np.where(sharp > , , sharp))
sharp = sharp.astype("uint8")

cv2.imshow("moon", moon)
cv2.imshow("Roberts_sharp", sharp)
cv2.waitKey()
           

輸出結果:

圖像梯度算子的本質
再看看用上面自定義算子的情況:
user_defined = np.zeros((row, column))

for x in range(, row - ):
    for y in range(, column - ):
        gx = abs((moon_f[x + , y - ] + moon_f[x + , y] + moon_f[x + , y + ]) - (
            moon_f[x - , y - ] + moon_f[x - , y] + moon_f[x - , y + ]))
        gy = abs((moon_f[x - , y + ] + moon_f[x, y + ] + moon_f[x + , y + ]) - (
            moon_f[x - , y - ] + moon_f[x, y - ] + moon_f[x + , y - ]))

        user_defined[x, y] = gx + gy

sharp = moon_f + user_defined
sharp = np.where(sharp < , , np.where(sharp > , , sharp))
sharp = sharp.astype("uint8")

cv2.imshow("moon", moon)
cv2.imshow("defined_sharp", sharp)
cv2.waitKey()
           

輸出結果:

圖像梯度算子的本質