血管強調におけるヘシアン行列の応用

       ヘッセ行列は、エッジ検出、テクスチャ分析などの画像セグメンテーションの分野など、画像処理において幅広い用途に使用できます。

原理:

      座標 (x, y) に対する画像のピクセル値の関数を f(x, y) とすると、 f(x+dx, y+dy) を f(x0, y0) で展開すると、次のようになります。式

39dc308f3123831e7b5d97cd0108277e.png

      この式を行列で表し、余りを切り捨てた場合

cbd5e5513af2a7ea14293dfce2198097.png

      上式の右辺の第 3 項の 2 番目の行列は、2 次元空間のヘッセ行列です。

95ec2415bd0ccda4b0c7a21670e49d1c.png

      簡略化された 2D

8fefd7ad22fa39fdf5f27609bbb6dc9b.png

      2 次元画像を例にとると、画像内の点構造は等方性ですが、線構造は異方性です。したがって、ヘシアン行列を使用して画像内の線形構造を強調し、点状の構造とノイズ ポイントを除去できます。同様に、画像内の点構造を見つけて他の情報を除外するためにも使用できます。

      一般に、デジタル グラフィックス上で 2 次微分を直接実行しますが、この方法はロバスト性が低く、ノイズの影響を受けやすいです。したがって、ガウス関数が増加します。

応用:

次に、注釈付きの Frangi フィルターに基づいて血管強調を実行します。

def getkernel(kernel=7,sigma=1.0):
    w = kernel//2
    PI = 3.1415926
    
    [Y,X]= np.mgrid[-w:w+1,-w:w+1]
    xxGauKernel = (1-X**2/sigma**2)*np.exp(-1*(X**2+Y**2)/(2*sigma**2))*(-1/(2*PI*sigma**4))
    yyGauKernel = (1-Y**2/sigma**2)*np.exp(-1*(X**2+Y**2)/(2*sigma**2))*(-1/(2*PI*sigma**4))
    xyGauKernel = np.exp(-1*(X**2+Y**2)/(2*sigma**2))*((X*Y)/(2*PI*sigma**6))
    return xxGauKernel,yyGauKernel,xyGauKernel
    
    
def Hessian2Dd(image,kernel=7,sigma=1.0):
    xxGauKernel,yyGauKernel,xyGauKernel = getkernel(kernel,sigma)
    xxDerivae = cv2.filter2D(image,-1,xxGauKernel,borderType =cv2.BORDER_CONSTANT)
    yyDerivae = cv2.filter2D(image,-1,yyGauKernel,borderType =cv2.BORDER_CONSTANT)
    xyDerivae = cv2.filter2D(image,-1,xyGauKernel,borderType =cv2.BORDER_CONSTANT)
    return xxDerivae,xyDerivae,yyDerivae




def eig2image(Dxx,Dxy,Dyy):
    Dxx=np.array(Dxx,dtype=float)
    Dyy=np.array(Dyy,dtype=float)
    Dxy=np.array(Dxy,dtype=float)
    if (len(Dxx.shape)!=2):
        print("len(Dxx.shape)!=2,不是二维数组!")
        return 0
    tmp = np.sqrt( (Dxx - Dyy)**2 + 4*Dxy**2)
    v2x = 2*Dxy
    v2y = Dyy - Dxx + tmp
    mag = np.sqrt(v2x**2 + v2y**2)
    i=np.array(mag!=0)
    v2x[i==True] = v2x[i==True]/mag[i==True]
    v2y[i==True] = v2y[i==True]/mag[i==True]
    v1x = -v2y
    v1y = v2x
    mu1 = 0.5*(Dxx + Dyy + tmp)
    mu2 = 0.5*(Dxx + Dyy - tmp)
    check=abs(mu1)>abs(mu2) 
    Lambda1=mu1.copy()
    Lambda1[check==True] = mu2[check==True]
    Lambda2=mu2
    Lambda2[check==True] = mu1[check==True]
    Ix=v1x
    Ix[check==True] = v2x[check==True]
    Iy=v1y
    Iy[check==True] = v2y[check==True]
    return Lambda1,Lambda2,Ix,Iy
    
    
def FrangiFilter2D(I):
    I=np.array(I,dtype=float)
    defaultoptions = {'FrangiScaleRange':(1,10), 'FrangiScaleRatio':2, 'FrangiBetaOne':0.5, 'FrangiBetaTwo':15, 'verbose':True,'BlackWhite':True};  
    options=defaultoptions
    sigmas=np.arange(options['FrangiScaleRange'][0],options['FrangiScaleRange'][1],options['FrangiScaleRatio'])
    sigmas.sort()
    beta  = 2*pow(options['FrangiBetaOne'],2)  
    c     = 2*pow(options['FrangiBetaTwo'],2)
    shape=(I.shape[0],I.shape[1],len(sigmas))
    ALLfiltered=np.zeros(shape) 
    ALLangles  =np.zeros(shape) 
    Rb=0
    S2=0
    for i in range(len(sigmas)):
        #Show progress
        if(options['verbose']):
            print('Current Frangi Filter Sigma: ',sigmas[i])
        S_round=np.round(3*sigmas[i])*2+1
        [Dxx,Dxy,Dyy] = Hessian2Dd(I,S_round,sigmas[i])
        Dxx = pow(sigmas[i],2)*Dxx  
        Dxy = pow(sigmas[i],2)*Dxy  
        Dyy = pow(sigmas[i],2)*Dyy
        
        [Lambda2,Lambda1,Ix,Iy]=eig2image(Dxx,Dxy,Dyy)  
 
        angles = np.arctan2(Ix,Iy)  
 
        Lambda1[Lambda1==0] = np.spacing(1)


        Rb = (Lambda2/Lambda1)**2  
        S2 = Lambda1**2 + Lambda2**2
        
        Ifiltered = np.exp(-Rb/beta) * (np.ones(I.shape)-np.exp(-S2/c))
        
        if(options['BlackWhite']): 
            Ifiltered[Lambda1<0]=0
        else:
            Ifiltered[Lambda1>0]=0
        
        ALLfiltered[:,:,i] = Ifiltered 
        ALLangles[:,:,i] = angles
 
        if len(sigmas) > 1:
            outIm=ALLfiltered.max(2)
        else:
            outIm = (outIm.transpose()).reshape(I.shape)
            
    return outIm

テスト結果を表示:

ce645c81582ce81a667d9fee81ce1db7.png

9449f3a09b365bc5bdc36152e6392518.png

フランジ フィルタリングの 3D バージョンの原理は 2D バージョンと同じです。この記事では直接提供されなくなりました。必要な読者は私にプライベート メッセージを送ってください。

おすすめ

転載: blog.csdn.net/weixin_41202834/article/details/121882547