sobel_GxGy边缘图_方向梯度直方图

Sobel滤波边缘提取

1、设计能够提取X方向、Y方向的Sobel滤波器,将上述滤波器和图像进行卷积,生成X方向和Y方向边缘图像。

思想:

X方向卷积因子: [ − 1 0 + 1 − 2 0 + 2 − 1 0 + 1 ] \left[ \begin{matrix}-1&0&+1\\ -2&0&+2\\-1&0&+1 \end{matrix} \right] 121000+1+2+1

Y方向卷积因子: [ + 1 + 2 + 1 0 0 0 − 1 − 2 − 1 ] \left[ \begin{matrix} +1&+2&+1\\0&0&0\\-1&-2&-1\\\end{matrix}\right] +101+202+101

G x = [ − 1 0 + 1 − 2 0 + 2 − 1 0 + 1 ] Gx = \left[ \begin{matrix}-1&0&+1\\ -2&0&+2\\-1&0&+1 \end{matrix} \right] Gx=121000+1+2+1*image

G y = [ + 1 + 2 + 1 0 0 0 − 1 − 2 − 1 ] G_y = \left[ \begin{matrix} +1&+2&+1\\0&0&0\\-1&-2&-1\\\end{matrix}\right] Gy=+101+202+101*image

在这里插入图片描述

X方向的Sobel边缘图像

在这里插入图片描述

y方向的Sobel边缘图像
def convolve(img,fill):#彩色图像分为RGB
    rgb_r = img[:,:,0]
    rgb_g = img[:,:,1]
    rgb_b = img[:,:,2]

    pro_rgb_r = pre_convolve(rgb_r,fill)#每层进行卷积操作
    pro_rgb_g = pre_convolve(rgb_g,fill)
    pro_rgb_b = pre_convolve(rgb_b,fill)

    img_pro = np.dstack((pro_rgb_r,pro_rgb_g,pro_rgb_b))#合并三层,返回图像
    return img_pro


def pre_convolve(img,fill):
    fill_height = fill.shape[0]#卷积高
    fill_width = fill.shape[1]#卷积宽

    img_height = img.shape[0]#图像高
    img_width = img.shape[1]#图像宽

    #图像进行卷积后的图像大小
    img_pro_height = img_height - fill_height + 1
    img_pro_width = img_width - fill_width + 1

    pro_rgb = np.zeros((img_pro_height,img_pro_width),dtype='uint8')

    for i in range(img_pro_height):#计算Gx点乘A Gy点乘A
        for j in range(img_pro_width):
            pro_rgb[i][j] = pro_statistic(img[i:i + fill_height,j:j + fill_width],fill)#sobel计算

    return pro_rgb


def pro_statistic(img,fill):
    res = (img * fill).sum()
    if(res > 255):
        res = 255
    elif(res < 0):
        res = abs(res)  # 让负边缘也显现出来
    return res


# 索贝尔算子 边缘检测
#Gx卷积因子
sobel_x = np.array([[-1,0,1],
                    [-2,0,2],
                    [-1,0,1]])
#Gy卷积因子
sobel_y = np.array([[1,2,1],
                    [0,0,0],
                    [-1,-2,-1]])

img = cv2.imread('./1.jpg')
res1 = convolve(img,sobel_x)#提取X方向的Sobel边缘图像
res2 = convolve(img,sobel_y)#提取Y方向的Sobel边缘图像

cv2.imshow('img', res1)
cv2.waitKey(0)

cv2.imshow('img', res2)
cv2.waitKey(0)

2、基于X方向和Y方向的边缘,生成总体梯度幅值(边缘)图和角度相位图。

思想:

利用 G = G x 2 + G y 2 G = \sqrt{G_x^2+G_y^2} G=Gx2+Gy2 生成总体梯度幅值的边缘图

在这里插入图片描述

def fu_zhi(res1,res2):
    #将X方向边缘图分解为为RGB三层
    res1_rgb_r = res1[:,:,0]
    res1_rgb_g = res1[:,:,1]
    res1_rgb_b = res1[:,:,2]
    #将Y方向边缘图分解为为RGB三层
    res2_rgb_r = res2[:,:,0]
    res2_rgb_g = res2[:,:,1]
    res2_rgb_b = res2[:,:,2]
    #获得边缘图的高与宽
    high = res1_rgb_r.shape[0]#图像高
    width = res1_rgb_r.shape[1]#图形宽
    #初始化基于X和Y方向边缘图
    res3_r = np.zeros((high, width),dtype='uint8')
    res3_g = np.zeros((high, width),dtype='uint8')
    res3_b = np.zeros((high, width),dtype='uint8')

    #公式 sqrt(Gx^2 + Gy^2)
    for i in range(high):
        for j in range(width):
            res3_r[i][j] = np.uint8(np.sqrt(pow(res1_rgb_r[i][j], 2) + pow(res2_rgb_r[i][j], 2)))
            res3_g[i][j] = np.uint8(np.sqrt(pow(res1_rgb_g[i][j], 2) + pow(res2_rgb_g[i][j], 2)))
            res3_b[i][j] = np.uint8(np.sqrt(pow(res1_rgb_b[i][j], 2) + pow(res2_rgb_b[i][j], 2)))
            
    res3 = np.dstack((res3_r, res3_g, res3_b))  # 合并三层,返回图像
    return res3

思想:

θ = a r c t a n ( G y G x ) \theta = arctan(\frac{G_y}{G_x}) θ=arctan(GxGy)计算梯度角度,

将[0,180]分为9等分,即[0,20]量化为index0,[20,40]量化为index1,[40,60]量化为index2,[60,80]量化为index3,[80,100]量化为index4,[100,120]量化为index5,[120,140]量化为index6,[140,160]量化为index7,[160,180]量化为index8。

将图像分为N*N个区域(cell),在cell上做出index对应的直方图。

C*C个cell为一个block,对每个block内cell的直方图进行归一化,获得特征值:KaTeX parse error: Got function '\sum' with no arguments as argument to '\sqrt' at position 25: …ac {h(t)}{\sqrt\̲s̲u̲m̲ ̲h(t)+ε}

将得到的h(t)可视化,cell内每个index的方向画一条线,值越大,颜色越白,值越小,颜色越黑。

在这里插入图片描述

方向梯度直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt


#获得直方图
def HOG(img):
    #将图像装换为灰度图
    def BGR2GRAY(img):
        gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
        return gray

    #获得GxGy大小
    def get_gradXY(gray):
        H, W = gray.shape

        #矩阵前后进行padding填充
        gray = np.pad(gray, (1, 1), 'edge')

        #获得Gx
        gx = gray[1:H + 1, 2:] - gray[1:H + 1, :W]
        #获得Gy
        gy = gray[2:, 1:W + 1] - gray[:H, 1:W + 1]
        # replace 0 with
        gx[gx == 0] = 1e-6

        return gx, gy

    #获得梯度大小和方向
    def get_MagGrad(gx, gy):
        # 获得梯度大小
        magnitude = np.sqrt(gx ** 2 + gy ** 2)

        # 获得梯度方向
        gradient = np.arctan(gy / gx)

        gradient[gradient < 0] = np.pi / 2 + gradient[gradient < 0] + np.pi / 2
        return magnitude, gradient

    #梯度
    def quantization(gradient):
        #准备量化表
        gradient_quantized = np.zeros_like(gradient, dtype=np.int)

        #量化单元
        d = np.pi / 9

        #量化
        for i in range(9):#在d*i和d*(i+1)之间定义为i
            gradient_quantized[np.where((gradient >= d * i) & (gradient <= d * (i + 1)))] = i

        return gradient_quantized

    #获得梯度直方图
    def gradient_histogram(gradient_quantized, magnitude, N=8):
        #获得梯度矩阵的高和宽
        H, W = magnitude.shape

        # get cell num
        cell_N_H = H // N# //除完取整
        cell_N_W = W // N
        histogram = np.zeros((cell_N_H, cell_N_W, 9), dtype=np.float32)

        # each pixel
        for y in range(cell_N_H):
            for x in range(cell_N_W):
                for j in range(N):
                    for i in range(N):
                        histogram[y, x, gradient_quantized[y * 4 + j, x * 4 + i]] += magnitude[y * 4 + j, x * 4 + i]

        return histogram

    #直方图均衡化
    def normalization(histogram, C=3, epsilon=1):
        cell_N_H, cell_N_W, _ = histogram.shape
        ## each histogram
        for y in range(cell_N_H):
            for x in range(cell_N_W):
                histogram[y, x] /= np.sqrt(np.sum(histogram[max(y - 1, 0): min(y + 2, cell_N_H),
                                                  max(x - 1, 0): min(x + 2, cell_N_W)] ** 2) + epsilon)

        return histogram

    # 1. BGR -> Gray
    gray = BGR2GRAY(img)

    # 1. Gray -> Gradient x and y
    gx, gy = get_gradXY(gray)

    # 2. get gradient magnitude and angle
    magnitude, gradient = get_MagGrad(gx, gy)

    # 3. Quantization
    gradient_quantized = quantization(gradient)

    # 4. Gradient histogram
    histogram = gradient_histogram(gradient_quantized, magnitude)

    # 5. Histogram normalization
    histogram = normalization(histogram)

    return histogram


# draw HOG
def draw_HOG(img, histogram):
    # Grayscale
    def BGR2GRAY(img):
        gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
        return gray

    def draw(gray, histogram, N=8):
        # get shape
        H, W = gray.shape
        cell_N_H, cell_N_W, _ = histogram.shape

        ## Draw
        out = gray[1: H + 1, 1: W + 1].copy().astype(np.uint8)

        for y in range(cell_N_H):
            for x in range(cell_N_W):
                cx = x * N + N // 2
                cy = y * N + N // 2
                x1 = cx + N // 2 - 1
                y1 = cy
                x2 = cx - N // 2 + 1
                y2 = cy

                h = histogram[y, x] / np.sum(histogram[y, x])
                h /= h.max()

                for c in range(9):
                    # get angle
                    angle = (20 * c + 10) / 180. * np.pi
                    rx = int(np.sin(angle) * (x1 - cx) + np.cos(angle) * (y1 - cy) + cx)
                    ry = int(np.cos(angle) * (x1 - cx) - np.cos(angle) * (y1 - cy) + cy)
                    lx = int(np.sin(angle) * (x2 - cx) + np.cos(angle) * (y2 - cy) + cx)
                    ly = int(np.cos(angle) * (x2 - cx) - np.cos(angle) * (y2 - cy) + cy)

                    # color is HOG value
                    c = int(255. * h[c])

                    # draw line
                    cv2.line(out, (lx, ly), (rx, ry), (c, c, c), thickness=1)

        return out

    # get gray
    gray = BGR2GRAY(img)

    # draw HOG
    out = draw(gray, histogram)

    return out




if __name__ == "__main__":
    # Read image
    img = cv2.imread("1.jpg").astype(np.float32)

    #获得直方图
    histogram = HOG(img)

    #画出直方图
    out = draw_HOG(img, histogram)

    # Save result
    cv2.imwrite("out.jpg", out)
    cv2.imshow("result", out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

St-sun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值