画像エッジ検出pythonコード

19253 ワード

1、Robersアルゴリズム
import numpy as np
import cv2
from scipy import signal
def roberts(I,_boundary='fill',_fillvalue=0):
    H1,W1=I.shape[0:2]
    H2,W2=2,2
    R1=np.array([[1,0],[0,-1]],np.float32)
    kr1,kc1=0,0
    IconR1=signal.convolve2d(I,R1,mode='full',boundary=_boundary,fillvalue=_fillvalue)
    IconR1=IconR1[H2-kr1-1:H1+H2-kr1-1,W2-kc1-1:W1+W2-kc1-1]
    R2=np.array([[0,1],[-1,0]],np.float32)
    IconR2=signal.convolve2d(I,R2,mode='full',boundary=_boundary,fillvalue=_fillvalue)
    kr2,kc2=0,1
    IconR2=IconR2[H2-kr2-1:H1+H2-kr2-1,W2-kc2-1:W1+W2-kc2-1]
    return (IconR1,IconR2)
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
cv2.imshow("image",image)
IconR1,IconR2=roberts(image,'symm')
IconR1=np.abs(IconR1)
edge_45=IconR1.astype(np.uint8)
cv2.imshow("edge_45",edge_45)
IconR2=np.abs(IconR2)
edge_135=IconR2.astype(np.uint8)
cv2.imshow("edge_135",edge_135)
edge=np.sqrt(np.power(IconR1,2.0)+np.power(IconR2,2.0))
edge=np.round(edge)
edge[edge>255]=255
edge=edge.astype(np.uint8)
cv2.imshow("edge",edge)
cv2.waitKey(0)
cv2.destroyAllWindows()

2、Prewittアルゴリズム
import numpy as np
import cv2
from scipy import signal
def prewitt(I,_boundary='symm',):
    ones_y=np.array([[1],[1],[1]],np.float32)
    i_conv_pre_x=signal.convolve2d(I,ones_y,mode='same',boundary=_boundary)
    diff_x=np.array([[1,0,-1]],np.float32)
    i_conv_pre_x=signal.convolve2d(i_conv_pre_x,diff_x,mode='same',boundary=_boundary)
    ones_x=np.array([[1,1,1]],np.float32)
    i_conv_pre_y=signal.convolve2d(I,ones_x,mode='same',boundary=_boundary)
    diff_y=np.array([[1],[0],[-1]],np.float32)
    i_conv_pre_y=signal.convolve2d(i_conv_pre_y,diff_y,mode='same',boundary=_boundary)
    return (i_conv_pre_x,i_conv_pre_y)
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
i_conv_pre_x,i_conv_pre_y=prewitt(image)
abs_i_conv_pre_x=np.abs(i_conv_pre_x)
abs_i_conv_pre_y=np.abs(i_conv_pre_y)
edge_x=abs_i_conv_pre_x.copy()
edge_y=abs_i_conv_pre_y.copy()
edge_x[edge_x>255]=255;
edge_y[edge_y>255]=255
edge_x=edge_x.astype(np.uint8)
edge_y=edge_y.astype(np.uint8)
cv2.imshow("edge_x",edge_x)
cv2.imshow("edge_y",edge_y)
edge=0.5*abs_i_conv_pre_x+0.5*abs_i_conv_pre_y
edge[edge>255]=255
edge=edge.astype(np.uint8)
cv2.imshow("edge",edge)
cv2.waitKey(0)
cv2.destroyAllWindows()

3、Sobelアルゴリズム
import cv2
import numpy as np
from scipy import signal
import math
def pascalSmooth(n):
    pascalSmooth=np.zeros([1,n],np.float32)
    for i in range(n):
        pascalSmooth[0][i]=math.factorial(n-1)/(math.factorial(i)*math.factorial(n-1-i))
        return pascalSmooth
def pascalDiff(n):
    pascalDiff=np.zeros([1,n],np.float32)
    pascalSmooth_previous=pascalSmooth(n-1)
    for i in range(n):
        if i==0:
            pascalDiff[0][i]=pascalSmooth_previous[0][i]
        elif i==n-1:
            pascalDiff[0][i]=-pascalSmooth_previous[0][i-1]
        else:
            pascalDiff[0][i]=pascalSmooth_previous[0][i]-pascalSmooth_previous[0][i-1]
    return pascalDiff
def sobel(image,n):
    rows,cols=image.shape
    pascalSmoothKernel=pascalSmooth(n)
    pascalDiffKernel=pascalDiff(n)
    image_sobel_x=signal.convolve2d(image,pascalSmoothKernel.transpose(),mode='same')
    image_sobel_x=signal.convolve2d(image_sobel_x,pascalDiffKernel,mode='same')
    image_sobel_y=signal.convolve2d(image,pascalSmoothKernel,mode='same')
    image_sobel_y=signal.convolve2d(image_sobel_y,pascalDiffKernel.transpose(),mode='same')
    return (image_sobel_x,image_sobel_y)
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
image_sobel_x,image_sobel_y=sobel(image,7)
edge=np.sqrt(np.power(image_sobel_x,2.0)+np.power(image_sobel_y,2.0))
edge=edge/np.max(edge)
edge=np.power(edge,1)
edge*=255
edge=edge.astype(np.uint8)
cv2.imshow("image",image)
cv2.imshow("edge",edge)
cv2.waitKey(0)
cv2.destroyAllWindows()

4、Scharrアルゴリズム
import cv2
import numpy as np
from scipy import signal
import math
def scharr(I,_boundary='symm'):
    scharr_x=np.array([[3,0,-3],[10,0,-10],[3,0,-3]],np.float32)
    I_x=signal.convolve2d(I,scharr_x,mode='same',boundary='symm')
    scharr_y=np.array([[3,10,3],[0,0,0],[-3,-10,-3]],np.float32)
    I_y=signal.convolve2d(I,scharr_y,mode='same',boundary='symm')
    return (I_x,I_y)
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
i_conv_pre_x,i_conv_pre_y=scharr(image)
abs_i_conv_pre_x=np.abs(i_conv_pre_x)
abs_i_conv_pre_y=np.abs(i_conv_pre_y)
edge_x=abs_i_conv_pre_x.copy()
edge_y=abs_i_conv_pre_y.copy()
edge_x[edge_x>255]=255
edge_y[edge_y>255]=255
edge_x=edge_x.astype(np.uint8)
edge_y=edge_y.astype(np.uint8)
cv2.imshow("edge_x",edge_x)
cv2.imshow("edge_y",edge_y)
edge=0.5*abs_i_conv_pre_x+0.5*abs_i_conv_pre_y
edge[edge>255]=255
edge=edge.astype(np.uint8)
cv2.imshow("edge",edge)
cv2.waitKey(0)
cv2.destroyAllWindows()

5、Kirschアルゴリズム
import cv2
import numpy as np
from scipy import signal
import math
def kirsch(image,_boundary='fill',_fillvalue=0):
    list_edge=[]
    k1=np.array([[5,5,5],[-3,0,-3],[-3,-3,-3]])
    image_k1=signal.convolve2d(image,k1,mode='same',boundary=_boundary,fillvalue=_fillvalue)
    list_edge.append(np.abs(image_k1))
    k2=np.array([[-3,-3,-3],[-3,0,-3],[5,5,5]])
    image_k2 = signal.convolve2d(image, k2, mode='same', boundary=_boundary, fillvalue=_fillvalue)
    list_edge.append(np.abs(image_k2))
    k3=np.array([[-3,5,5],[-3,0,5],[-3,-3,-3]])
    image_k3 = signal.convolve2d(image, k3, mode='same', boundary=_boundary, fillvalue=_fillvalue)
    list_edge.append(np.abs(image_k3))
    k4=np.array([[-3,-3,-3],[5,0,-3],[5,5,-3]])
    image_k4 = signal.convolve2d(image, k4, mode='same', boundary=_boundary, fillvalue=_fillvalue)
    list_edge.append(np.abs(image_k4))
    k5=np.array([[-3,-3,5],[-3,0,5],[-3,-3,5]])
    image_k5 = signal.convolve2d(image, k5, mode='same', boundary=_boundary, fillvalue=_fillvalue)
    list_edge.append(np.abs(image_k5))
    k6=np.array([[5,-3,-3],[5,0,-3],[5,-3,-3]])
    image_k6 = signal.convolve2d(image, k6, mode='same', boundary=_boundary, fillvalue=_fillvalue)
    list_edge.append(np.abs(image_k6))
    k7=np.array([[-3,-3,-3],[-3,0,5],[-3,5,5]])
    image_k7 = signal.convolve2d(image, k7, mode='same', boundary=_boundary, fillvalue=_fillvalue)
    list_edge.append(np.abs(image_k7))
    k8=np.array([[5,5,-3],[5,0,-3],[-3,-3,-3]])
    image_k8 = signal.convolve2d(image, k8, mode='same', boundary=_boundary, fillvalue=_fillvalue)
    list_edge.append(np.abs(image_k8))
    edge=list_edge[0]
    for i in range(len(list_edge)):
        edge=edge*(edge>=list_edge[i])+list_edge[i]*(edge255]=255
edge=edge.astype(np.uint8)
cv2.imshow("edge",edge)
pencilSketch=255-edge
cv2.imshow("pencilSketch",pencilSketch)
cv2.waitKey(0)
cv2.destroyAllWindows()

6、Cannyアルゴリズム
import cv2
import numpy as np
from scipy import signal
import math
import sobel
def non_maximum_suppression_default(dx,dy):
    edgeMag=np.sqrt(np.power(dx,2.0)+np.power(dy,2.0))
    rows,cols=dx.shape
    gradientDirection=np.zeros(dx.shape)
    edgeMag_nonMaxSup=np.zeros(dx.shape)
    for r in range(1,rows-1):
        for c in range(1,cols-1):
            angle=math.atan2(dy[r][c],dx[r][c])/math.pi*180
            gradientDirection[r][c]=angle
            if abs(angle)<22.5 or abs(angle)>157.5:
                if edgeMag[r][c]>edgeMag[r][c-1] and edgeMag[r][c]>edgeMag[r][c+1]:
                    edgeMag_nonMaxSup[r][c]=edgeMag[r][c]
            if (angle>=22.5 and angle<67.5) or (-angle>112.5 and -angle<=157.5):
                if edgeMag[r][c]>edgeMag[r-1][c-1] and edgeMag[r][c]>edgeMag[r+1][c+1]:
                    edgeMag_nonMaxSup[r][c]=edgeMag[r][c]
            if abs(angle)>=67.5 and abs(angle)<=112.5:
                if edgeMag[r][c]>edgeMag[r-1][c] and edgeMag[r][c]>edgeMag[r+1][c]:
                    edgeMag_nonMaxSup[r][c]=edgeMag[r][c]
            if (angle>=112.5 and angle<=157.5) or (-angle>=22.5 and -angle<67.5):
                if edgeMag[r][c]>edgeMag[r-1][c+1] and edgeMag[r][c]>edgeMag[r+1][c-1]:
                    edgeMag_nonMaxSup[r][c]=edgeMag[r][c]
    return edgeMag_nonMaxSup
def nom_maximum_suppression_Inter(dx,dy):
    edgeMag=np.sqrt(np.power(dx,2.0)+np.power(dy,2.0))
    rows,cols=dx.shape
    gradientDirection=np.zeros(dx.shape)
    edgeMag_nonMaxSup=np.zeros(dx.shape)
    for r in range(1,rows-1):
        for c in range(1,cols-1):
            if dy[r][c]==0 and dx[r][c]==0:
                continue
            angle=math.atan2(dy[r][c],dx[r][c])/math.pi*180
            gradientDirection[r][c]=angle
            if (angle>45 and angle<=90) or (angle>-135 and angle<=-90):
                ratio=dx[r][c]/dy[r][c]
                leftTop_top=ratio*edgeMag[r-1][c-1]+(1-ratio)*edgeMag[r-1][c]
                rightBottom_bottom=(1-ratio)*edgeMag[r+1][c]+ratio*edgeMag[r+1][c+1]
                if edgeMag[r][c]>leftTop_top and edgeMag[r][c]>rightBottom_bottom:
                    edgeMag_nonMaxSup[r][c]=edgeMag[r][c]
            if (angle>90 and angle<=135) or (angle>-90 and angle<=-45):
                ratio=abs(dx[r][c]/dy[r][c])
                rightTop_top=ratio*edgeMag[r-1][c+1]+(1-ratio)*edgeMag[r-1][c]
                leftBottom_bottom=ratio*edgeMag[r+1][c-1]+(1-ratio)*edgeMag[r+1][c]
                if edgeMag[r][c]>rightTop_top and edgeMag[r][c]>leftBottom_bottom:
                    edgeMag_nonMaxSup[r][c]=edgeMag[r][c]
            if (angle>=0 and angle<=45) or (angle>-180 and angle<=-135):
                ratio=dy[r][c]/dx[r][c]
                rightBottom_right=ratio*edgeMag[r+1][c+1]+(1-ratio)*edgeMag[r][c+1]
                leftTop_left=ratio*edgeMag[r-1][c-1]+(1-ratio)*edgeMag[r][c-1]
                if edgeMag[r][c]>rightBottom_right and edgeMag[r][c]>leftTop_left:
                    edgeMag_nonMaxSup[r][c]=edgeMag[r][c]
            if (angle>135 and angle<=180) or (angle>-45 and angle<=0):
                ratio=abs(dy[r][c]/dx[r][c])
                rightTop_right=ratio*edgeMag[r-1][c+1]+(1-ratio)*edgeMag[r][c+1]
                leftBottom_left=ratio*edgeMag[r+1][c-1]+(1-ratio)*edgeMag[r][c-1]
                if edgeMag[r][c]>rightTop_right and edgeMag[r][c]>leftBottom_left:
                    edgeMag_nonMaxSup[r][c]=edgeMag[r][c]
    return edgeMag_nonMaxSup
def checkInRange(r,c,rows,cols):
    if r>0 and r=0 and c=lowerThresh:
                    trace(edgeMag_nonMaxSup,edge,lowerThresh,r+i,c+j,rows,cols)
def hysteresisThreshold(edge_nonMaxSup,lowerThresh,upperThresh):
    rows,cols=edge_nonMaxSup.shape
    edge=np.zeros(edge_nonMaxSup.shape,np.uint8)
    for r in range(1,rows-1):
        for c in range(1,cols-1):
            if edge_nonMaxSup[r][c]>=upperThresh:
                trace(edge_nonMaxSup,edge,lowerThresh,r,c,rows,cols)
            if edge_nonMaxSup[r][c]255]=255
edge=edge.astype(np.uint8)
edgeMag_nonMaxSup=non_maximum_suppression_default(image_sobel_x,image_sobel_y)
edgeMag_nonMaxSup[edgeMag_nonMaxSup>255]=255
edgeMag_nonMaxSup=edgeMag_nonMaxSup.astype(np.uint8)
cv2.imshow("edgeMag_nonMaxSup",edgeMag_nonMaxSup)
edge=hysteresisThreshold(edgeMag_nonMaxSup,60,180)
lowerThresh=40
upperThresh=150
cv2.imshow("canny",edge)
cv2.waitKey(0)
cv2.destroyAllWindows()

7、Laplacianアルゴリズム
import cv2
import numpy as np
from scipy import signal
import math
def laplacian(image,_boundary='fill',_fillvalue=0):
    laplacianKernel=np.array([[0,-1,0],[-1,4,-1],[0,-1,0]],np.float32)
    i_conv_lap=signal.convolve2d(image,laplacianKernel,mode='same',boundary=_boundary,fillvalue=_fillvalue)
    return i_conv_lap
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
cv2.imshow("image",image)
i_conv_lap=laplacian(image,'symm')
threshEdge=np.copy(i_conv_lap)
threshEdge[threshEdge>0]=255
threshEdge[threshEdge<=0]=0
threshEdge=threshEdge.astype(np.uint8)
cv2.imshow("threshEdge",threshEdge)
abstraction=np.copy(i_conv_lap)
abstraction=abstraction.astype(np.float32)
abstraction[abstraction>=0]=1.0
abstraction[abstraction<0]=1.0+np.tanh(abstraction[abstraction<0])
cv2.imshow("abstraction",abstraction)
cv2.waitKey(0)
cv2.destroyAllWindows()

8、Logアルゴリズム
import cv2
import numpy as np
from scipy import signal
import math
def createLoGKernel(sigma,size):
    H,W=size
    r,c=np.mgrid[0:H:1,0:W:1]
    r-=(H-1)//2
    c-=(W-1)//2
    sigma2=pow(sigma,2.0)
    norm2=np.power(r,2.0)+np.power(c,2.0)
    LoGKernel=(norm2/sigma2-2)*np.exp(-norm2/(2*sigma2))
    return LoGKernel
def LoG(image,sigma,size,_boundary='symm'):
    loGKernel=createLoGKernel(sigma,size)
    img_conv_log=signal.convolve2d(image,loGKernel,'same',boundary=_boundary)
    return img_conv_log
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
cv2.imshow("image",image)
img_conv_log=LoG(image,6,(37,37),'symm')
edge_binary=np.copy(img_conv_log)
edge_binary[edge_binary>0]=255
edge_binary[edge_binary<=0]=0
edge_binary=edge_binary.astype(np.uint8)
cv2.imshow("edge_binary",edge_binary)
cv2.waitKey(0)
cv2.destroyAllWindows()

9、DoGアルゴリズム方案一:
import cv2
import numpy as np
from scipy import signal
import math
def gaussConv(I,size,sigma):
    H,W=size
    xr,xc=np.mgrid[0:1,0:W]
    xc-=(W-1)//2
    xk=np.exp(-np.power(xc,2.0))
    I_xk=signal.convolve2d(I,xk,'same','symm')
    yr,yc=np.mgrid[0:H,0:1]
    yr-=(H-1)//2
    yk=np.exp(-np.power(yr,2.0))
    I_xk_yk=signal.convolve2d(I_xk,yk,'same','symm')
    I_xk_yk*=1.0/(2*np.pi*pow(sigma,2.0))
    return I_xk_yk
def DoG(I,size,sigma,k=1.1):
    Is=gaussConv(I,size,sigma)
    Isk=gaussConv(I,size,k*sigma)
    doG=Isk-Is
    doG/=(pow(sigma,2.0)*(k-1))
    return doG
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
cv2.imshow("image",image)
sigma=2
k=1.1
size=(13,13)
imageDoG=DoG(image,size,sigma,k)
edge=np.copy(imageDoG)
edge[edge>0]=255
edge[edge<=0]=0
edge=edge.astype(np.uint8)
cv2.imshow("edge",edge)
abstraction=-np.copy(imageDoG)
abstraction=abstraction.astype(np.float32)
abstraction[abstraction>=0]=1.0
abstraction[abstraction<0]=1.0+np.tanh(abstraction[abstraction<0])
cv2.imshow("abstraction",abstraction)
cv2.waitKey(0)
cv2.destroyAllWindows()

シナリオ2:
import cv2
import numpy as np
from scipy import signal
import math
def gaussConv(I,size,sigma):
    H,W=size
    r,c=np.mgrid[0:H:1,0:W:1]
    r-=(H-1)//2
    c-=(W-1)//2
    sigma2=pow(sigma,2.0)
    norm2=np.power(r,2.0)+np.power(c,2.0)
    xyk=(norm2/sigma2-2)*np.exp(-norm2/(2*sigma2))
    I_xk_yk=signal.convolve2d(I,xyk,'same','symm')
    return I_xk_yk
def DoG(I,size,sigma,k=1.1):
    Is=gaussConv(I,size,sigma)
    Isk=gaussConv(I,size,k*sigma)
    doG=Isk-Is
    doG/=(pow(sigma,2.0)*(k-1))
    return doG
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
cv2.imshow("image",image)
sigma=4
k=1.1
size=(25,25)
imageDoG=DoG(image,size,sigma,k)
edge=np.copy(imageDoG)
edge[edge>0]=255
edge[edge<=0]=0
edge=np.round(edge)
edge=edge.astype(np.uint8)
cv2.imshow("edge",edge)
abstraction=-np.copy(imageDoG)
abstraction=abstraction.astype(np.float32)
abstraction[abstraction>=0]=1.0
abstraction[abstraction<0]=1.0+np.tanh(abstraction[abstraction<0])
cv2.imshow("abstraction",abstraction)
cv2.waitKey(0)
cv2.destroyAllWindows()


10、Marr-Hildrethアルゴリズム
import cv2
import numpy as np
from scipy import signal
import math
def gaussConv(I,size,sigma):
    H,W=size
    xr,xc=np.mgrid[0:1,0:W]
    xc-=(W-1)//2
    xk=np.exp(-np.power(xc,2.0))
    I_xk=signal.convolve2d(I,xk,'same','symm')
    yr,yc=np.mgrid[0:H,0:1]
    yr-=(H-1)//2
    yk=np.exp(-np.power(yr,2.0))
    I_xk_yk=signal.convolve2d(I_xk,yk,'same','symm')
    I_xk_yk*=1.0/(2*np.pi*pow(sigma,2.0))
    return I_xk_yk
def DoG(I,size,sigma,k=1.1):
    Is=gaussConv(I,size,sigma)
    Isk=gaussConv(I,size,k*sigma)
    doG=Isk-Is
    doG/=(pow(sigma,2.0)*(k-1))
    return doG
def zero_cross_default(doG):
    zero_cross=np.zeros(doG.shape,np.uint8)
    rows,cols=doG.shape
    for r in range(1,rows-1):
        for c in range(1,cols-1):
            if doG[r][c-1]*doG[r][c+1]<0:
                zero_cross[r][c]=255
                continue
            if doG[r-1][c]*doG[r+1][c]<0:
                zero_cross[r][c]=255
                continue
            if doG[r-1][c-1]*doG[r+1][c+1]<0:
                zero_cross[r][c]=255
                continue
            if doG[r-1][c+1]*doG[r+1][c-1]<0:
                zero_cross[r][c]=255
                continue
    return zero_cross
def zero_cross_mean(doG):
    zero_cross=np.zeros(doG.shape,np.uint8)
    fourMean=np.zeros(4,np.float32)
    rows,cols=doG.shape
    for r in range(1,rows-1):
        for c in range(1,cols-1):
            leftTopMean=np.mean(doG[r-1:r+1,c-1:c+1])
            fourMean[0]=leftTopMean
            rightTopMean = np.mean(doG[r - 1:r + 1, c - 1:c + 2])
            fourMean[1] = rightTopMean
            leftBottomMean=np.mean(doG[r:r+2,c-1:c+1])
            fourMean[2]=leftBottomMean
            rightBottomMean=np.mean(doG[r:r+2,c:c+2])
            fourMean[3]=rightBottomMean
            if np.min(fourMean)*np.max(fourMean)<0:
                zero_cross[r][c]=255
    return zero_cross
def Marr_Hildreth(image,size,sigma,k=1.1,crossType="ZERO_CROSS_DEFAULT"):
    doG=DoG(image,size,sigma,k)
    if crossType=="ZERO_CROSS_DEFAULT":
        zero_cross=zero_cross_default(doG)
    elif crossType=="ZERO_CROSS_MEAN":
        zero_cross=zero_cross_mean(doG)
    else:
        print("no crossType")
    return zero_cross
image=cv2.imread("/home/xiaomingming/profile/xmm.jpg",cv2.IMREAD_GRAYSCALE)
cv2.imshow("image",image)
result=Marr_Hildreth(image,(37,37),6,1.1,"ZERO_CROSS_MEAN")
cv2.imshow("Marr_Hildreth",result)
cv2.waitKey(0)
cv2.destroyAllWindows()