Python+OpenCV實現sobel邊緣檢測

sobel邊緣檢測即實現對圖像邊緣的提取,輸入爲一幅圖像,輸出爲圖像輪廓。
sobel算法步驟:
(1)將輸入圖像轉爲灰度圖;
(2)對灰度圖進行二值化處理(此過程採用otsu二值化算法,具體otsu算法參看上一篇博客);
(3)定義sobel豎直和水平卷積算子;
(4)遍歷圖像像素點,除邊緣像素點外,每個像素點的領域像素點(共計九個像素點)分別與sobel算子(豎直和水平卷積算子)值相乘累加;
(5)將豎直和水平sobel算子乘積值絕對值之後相加,賦於新的與原圖像相等大小的矩陣中。

import cv2 as cv
import math
import numpy as np

def rgb2gray(img):
    h=img.shape[0]
    w=img.shape[1]
    img1=np.zeros((h,w),np.uint8)
    for i in range(h):
        for j in range(w):
            img1[i,j]=0.144*img[i,j,0]+0.587*img[i,j,1]+0.299*img[i,j,1]
    return img1

def otsu(img):
    h=img.shape[0]
    w=img.shape[1]
    m=h*w   # 圖像像素點總和
    otsuimg=np.zeros((h,w),np.uint8)
    threshold_max=threshold=0   # 定義閾值
    histogram=np.zeros(256,np.int32)   # 初始化各灰度級個數統計參數
    probability=np.zeros(256,np.float32)   # 初始化各灰度級佔圖像中的分佈的統計參數
    for i in range (h):
        for j in range (w):
            s=img[i,j]
            histogram[s]+=1   # 統計灰度級中每個像素在整幅圖像中的個數
    for k in range (256):
        probability[k]=histogram[k]/m   # 統計每個灰度級佔圖像中的分佈
    for i in range (255):
        w0 = w1 = 0  # 定義前景像素點和背景像素點灰度級佔圖像中的分佈
        fgs = bgs = 0  # 定義前景像素點灰度級總和and背景像素點灰度級總和
        for j in range (256):
            if j<=i:   # 當前i爲分割閾值
                w0+=probability[j]   # 前景像素點佔整幅圖像的比例累加
                fgs+=j*probability[j]
            else:
                w1+=probability[j]   # 背景像素點佔整幅圖像的比例累加
                bgs+=j*probability[j]
        u0=fgs/w0   # 前景像素點的平均灰度
        u1=bgs/w1   # 背景像素點的平均灰度
        g=w0*w1*(u0-u1)**2   # 類間方差
        if g>=threshold_max:
            threshold_max=g
            threshold=i
    print(threshold)
    for i in range (h):
        for j in range (w):
            if img[i,j]>threshold:
                otsuimg[i,j]=255
            else:
                otsuimg[i,j]=0
    return otsuimg

def sobel(img):
    h=img.shape[0]
    w=img.shape[1]
    sobelimg=np.zeros((h,w),np.uint8)
    sobelx=[[-1,0,1],
            [-2,0,2],
            [-1,0,1]]
    sobely=[[1,2,1],
            [0,0,0],
            [-1,-2,-1]]
    sobelx=np.array(sobelx)
    sobely=np.array(sobely)
    gx=0   # 垂直方向上的梯度模長
    gy=0   # 水平方向上的梯度模長
    for i in range(1,h-1):
        for j in range(1,w-1):
            edgex=0
            edgey=0
            for k in range(-1,2):
                for l in range(-1,2):
                    edgex+=img[k+i,l+j]*sobelx[1+k,1+l]
                    edgey+=img[k+i,l+j]*sobely[1+k,1+l]
            gx=abs(edgex)
            gy=abs(edgey)
            gramag=gx+gy
            sobelimg[i,j]=gramag
    return sobelimg

image=cv.imread("D:/sobel.png")
grayimage=rgb2gray(image)
otsuimage=otsu(grayimage)
sobelimage=sobel(otsuimage)
cv.imshow("image",image)
cv.imshow("sobelimage",sobelimage)
cv.waitKey(0)
cv.destroyAllWindows()

實驗結果:
在這裏插入圖片描述
通過實驗結果可以看出效果並不好,說明關於源碼編寫仍有不少瑕疵,希望各位可以分享更爲高效的代碼,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章