Esempio n. 1
0
def IntensityF(I, typeflag=None, returnShape=False):
    """
     Input:     - I: A 2D image
                - typeflag: dict of logicals to permit extracting features
                  based on desired characteristics:
                       + typeflag['global']: all features
                       + typeflag['texture']: all features
                       + typeflag['corr']: only features based on correlation
                       + typeflag['entropy']: only features based on entropy
                  default: all features are being extracted
                  For more information see README.txt

     Output:    - Out: A (1x7) vector containing 7 metrics based on intensity
     """
    # ************************************************************************
    # Implemented for MRI feature extraction by the Department of Diagnostic
    # and Interventional Radiology, University Hospital of Tuebingen, Germany
    # and the Institute of Signal Processing and System Theory University of
    # Stuttgart, Germany. Last modified: November 2016
    #
    # This implementation is part of ImFEATbox, a toolbox for image feature
    # extraction and analysis. Available online at:
    # https://github.com/annikaliebgott/ImFEATbox
    #
    # Contact: [email protected]
    # ************************************************************************
    #
    # Implementation based on the intensity-based features of the paper by
    # McGee et al.: "Image metric-based correction (Autocorrection) of motion
    # effects: Analysis of image metrics" (Journal of Magnetic Resonance
    # Imaging, vol. 11, no. 2, pp. 174–181, 2000.)

    if typeflag == None:
        typeflag = dict()
        typeflag['global'] = True
        typeflag['texture'] = True
        typeflag['corr'] = True
        typeflag['entropy'] = True

    if typeflag['global'] or typeflag['texture']:
        typeflag['corr'] = True
        typeflag['entropy'] = True

    if typeflag['global'] == typeflag['texture'] == typeflag[
            'corr'] == typeflag['entropy'] == False:
        # catching this case. gradient like this does not make sense.
        # so we throw a warning and set both to True
        typeflag['global'] = True
        typeflag['texture'] = True
        typeflag['corr'] = True
        typeflag['entropy'] = True
        warnings.warn(
            "typeflag global, texture, corr and entropy are false. Using default settings."
        )

    if returnShape:
        # returns only the shape of feature vectors depending on parameters
        if not (typeflag['texture'] or typeflag['global']):
            if not typeflag['corr']:
                return (1, 1)
            elif not typeflag['entropy']:
                return (2, 1)
            else:
                return (3, 1)
        else:
            return (7, 1)

    # Check for color image and convert to grayscale
    if len(np.shape(I)) == 3:
        if np.shape(I)[2] == 3:
            I = rgb2grayscale(I)

    Height, Width = np.shape(I)
    n = Height * Width

    ## Extract features

    if typeflag['global'] or typeflag['texture'] or typeflag['corr']:
        # AutoCorrelation 1
        p2 = np.zeros((Height, Width - 1))
        p1 = np.sum(np.power(I, 2))
        #k = range(0, Width)
        for i in range(0, Height):
            p2[i, 0:Width - 1] = I[i, 0:Width - 1] * I[i, 1:Width]
        ACORR = p1 - np.sum(p2)

        # AutoCorrelation 2
        p3 = np.zeros((Height, Width - 2))
        #l = range(0, Width-1)
        for i in range(0, Height):
            p3[i, 0:Width - 2] = I[i, 0:Width - 2] * I[i, 2:Width]
        ACORR2 = np.sum(p2) - np.sum(p3)

    if typeflag['global'] or typeflag['texture'] or typeflag['entropy']:
        # Entropy
        H1 = conv2float(I) / (np.sum(np.power(I, 2)))
        # marginal entropies
        E = -np.sum(H1[H1 != 0] * np.log(H1[H1 != 0]))

    if typeflag['global'] or typeflag['texture']:

        #Standard Deviation
        STD = np.std(I, ddof=1)

        # Cube of Normalized Intensities
        NI3 = np.sum(np.power((1.0 * I) / np.sum(I), 3))

        # 4th power of Normalized Intensities
        NI4 = np.sum(np.power((1.0 * I) / np.sum(I), 4))

        # Squared Intensities
        I2 = np.sum(np.power((1.0 * I) / n, 2))

    ## return feature vector
    if not (typeflag['texture'] or typeflag['global']):
        if not typeflag['corr']:
            Out = np.array([E])
        elif not typeflag['entropy']:
            Out = np.array([ACORR, ACORR2])
        else:
            Out = np.array([ACORR, ACORR2, E])
    else:
        Out = np.array([STD, ACORR, ACORR2, E, NI3, NI4, I2])

    return Out
Esempio n. 2
0
def HuF(I, returnShape=False):
    """
     Input:     - I: A 2D image


     Output:    - Out: A (1x8) vector containing the first 8 Hu moments of
                       order 3
    """
    # ************************************************************************
    # Modified for MRI feature extraction by the Department of Diagnostic
    # and Interventional Radiology, University Hospital of Tuebingen, Germany
    # and the Institute of Signal Processing and System Theory University of
    # Stuttgart, Germany. Last modified: November 2016
    #
    # This implementation is part of ImFEATbox, a toolbox for image feature
    # extraction and analysis. Available online at:
    # https://github.com/annikaliebgott/ImFEATbox
    #
    # Contact: [email protected]
    # ************************************************************************
    #
    # Implementation by:    Ishrat Badami, Computer Graphics Department,
    #                       University of Bonn

    if returnShape:
        return (8, 1)

    I = conv2float(I)
    height, width = np.shape(I)

    # define a coordinate system for the image
    xgrid = np.repeat(
        np.array(
            range(int(-np.floor(height / 2.0)), int(np.ceil(height / 2.0)))),
        width)
    xgrid = np.reshape(xgrid, (height, width))

    ygrid = np.repeat(
        np.array(range(int(-np.floor(width / 2.0)),
                       int(np.ceil(width / 2.0)))), height)
    ygrid = np.reshape(ygrid, (height, width), order='F')

    x_bar, y_bar = centerOfMass(I, xgrid, ygrid)

    # normalize coordinate system by subtracting mean
    xnorm = x_bar - xgrid
    ynorm = y_bar - ygrid

    # central moments
    mu_11 = central_moments(I, xnorm, ynorm, 1, 1)
    mu_20 = central_moments(I, xnorm, ynorm, 2, 0)
    mu_02 = central_moments(I, xnorm, ynorm, 0, 2)
    mu_21 = central_moments(I, xnorm, ynorm, 2, 1)
    mu_12 = central_moments(I, xnorm, ynorm, 1, 2)
    mu_03 = central_moments(I, xnorm, ynorm, 0, 3)
    mu_30 = central_moments(I, xnorm, ynorm, 3, 0)

    #calculate first 8 hu moments of order 3
    I_1 = mu_20 + mu_02
    I_2 = (mu_20 - mu_02)**2 + 4 * mu_11
    I_3 = (mu_30 - 3 * mu_12)**2 + (mu_03 - 3 * mu_21)**2
    I_4 = (mu_30 + mu_12)**2 + (mu_03 + mu_21)**2
    I_5 = (mu_30 - 3 * mu_12) * (mu_30 + mu_12) * (
        (mu_30 + mu_12)**2 - 3 *
        (mu_21 + mu_03)**2) + (3 * mu_21 -
                               mu_03) * (mu_21 + mu_03) * (3 *
                                                           (mu_30 + mu_12)**2 -
                                                           (mu_03 + mu_21)**2)
    I_6 = (mu_20 - mu_02) * (
        (mu_30 + mu_12)**2 -
        (mu_21 + mu_03)**2) + 4 * (mu_30 + mu_12) * (mu_21 + mu_03)
    I_7 = (3 * mu_21 - mu_03) * (mu_30 + mu_12) * (
        (mu_30 + mu_12)**2 - 3 * (mu_21 + mu_03)**2) + (mu_30 - 3 * mu_12) * (
            mu_21 + mu_03) * (3 * (mu_30 + mu_12)**2 - (mu_03 + mu_21)**2)
    I_8 = mu_11 * (mu_30 + mu_12)**2 - (
        mu_03 + mu_21)**2 - (mu_20 - mu_02) * (mu_30 + mu_12) * (mu_21 + mu_03)

    Out = np.array([I_1, I_2, I_3, I_4, I_5, I_6, I_7, I_8])
    return Out
Esempio n. 3
0
def DCTF(I, typeflag=None):
"""
     Input:     - I: A 2D image
                - typeflag: Struct of logicals to permit extracting features
                  based on desired characteristics:
                       + typeflag.global: all features
                       + typeflag.transform: all features
                       + typeflag.corr: only features based on correlation
                  default: all features are being extracted
                  For more information see README.txt

     Output:    - Out: A (1x2901) vector containing 2901 metrics calculated
                       from the discrete cosine transform
"""
    # ************************************************************************
    # Implemented for MRI feature extraction by the Department of Diagnostic
    # and Interventional Radiology, University Hospital of Tuebingen, Germany
    # and the Institute of Signal Processing and System Theory University of
    # Stuttgart, Germany. Last modified: December 2016
    #
    # This implementation is part of ImFEATbox, a toolbox for image feature
    # extraction and analysis. Available online at:
    # https://github.com/annikaliebgott/ImFEATbox
    #
    # Contact: [email protected]
    # ************************************************************************

    if typeflag == None:
        typeflag = dict()
        typeflag['global'] = True
        typeflag['transform'] = True
        typeflag['corr'] = True


    I = conv2float(I)

    # reserve space for the feature vector
    # if typeflag.transform || typeflag.global == true: extract all features
    # if only typeflag.corr == true: extract especially correlation based
    # features
    if typeflag.transform or typeflag.global:
        f = np.zeros(3,967)
    else:
        f = np.zeros(3,84)

    ## calculate DCT for different orientations: horizontal,vertical, diagonal

    for z in range(0, 3):
        # horizontal, vertical and diagonal by counting the number of occurrence
        # of each selected coefficient with respect to its position
        # equal importance of horizontal, vertical and diagonal

        if (z == 1):
            # rotate image by 90 degree
            I = imrotate(I, 90, interp='bilinear')  #'bicubic'
        elif (z == 2):
            # rotate image by -90 degree
            I = imrotate(I, -180, interp='bilinear')

        # index counter
        idx = 0

        # 2D discrete cosine transform, later on used as reference matrix
        B = dct(I, type=2, norm='ortho')

        # perform SVD
        U,S,V = svd(B)
        eUB = eig(U)[0]
        eVB = eig(V)[0]

        # extract features
        if typeflag.transform || typeflag.global:
            f(z,idx:idx+99) = [np.swapaxes(eUB(1:50), 0, 1) np.swapaxes(eVB(1:50), 0, 1)]
            idx = idx+99

            if np.shape(B)[1] < 150:
                coefB = [B[0,0], B[0,39], B[19,59], B[79,99], B[99, np.shape(B)[1]]]
            else:
                coefB = [B[0,0], B[0,39], B[19,59], B[79,99], B[99, 149]]
            end
            f(z,idx:idx+ len(coefB)-1) = coefB
            idx = idx + len(coefB)

            f(z,idx:idx+3) = [det(U), trace(U), det(V), trace(V)]
            idx = idx + 4

        ## calculate transform for different block decomposition sizes
        for i in [2, 4, 8, 16, 32, 64]:

            # TODO block_struct ?!

            # extract spatio-temporal features
            # decompose blocks of images into independent tiles
            fun = @(block_struct) np.std(block_struct.data, ddof=1) * np.ones(np.shape(block_struct.data))
            I2 = blockproc(I,[i i],fun)


            # 2D discrete cosine transform
            # I2 has to be grayscale
            B2 = dct(I2, type=2, norm='ortho')

            # output of some coefficients
            # 3D zigzag transversal to select 25# of the coefficents
            if typeflag.transform || typeflag.global:
                if np.shape(B2)[1] < 150:
                    coefB2 = [B[0,0], B[0,39], B[19,59], B[79,99], B[99, np.shape(B)[1]]]
                else:
                    coefB2 = [B[0,0], B[0,39], B[19,59], B[79,99], B[99, 149]]
                end
                f(z,idx+1:idx + len(coefB2)) = coefB2
                idx = idx + len(coefB2)

                # calculate important features of the 2D DCT
                temp = [np.std(B2, ddof=1) np.std(np.std(B2, ddof=1), ddof=1), np.mean(B2), np.linalg.matrix_rank(B2), np.max(B2), np.min(B2) np.count_nonzero(B2)]
                f(z,idx+1:idx+ len(temp)) = temp
                idx = idx + len(temp)
            end

            # correlation between DCT of I and decomposed I
            Corr = np.corrcoef(B, B2)
            f(z,idx) = Corr(1,2)
            idx = idx +1

            # singular value deomposition, U & V are square matrices
            [U2,S2,V2] = svd(B2)
            eUB2 = eig(U2)[0]
            eVB2 = eig(V2)[0]

            if typeflag.transform || typeflag.global:
                temp = [np.swapaxes(eUB2(1:50), 0, 1), np.swapaxes(eVB2(1:50), 0, 1),
                np.std(U2, ddof=1), np.std(S2, ddof=1), np.std(V2, ddof=1), np.mean(U2), np.mean(S2), np.mean(V2),
                np.max(U2), np.max(S2), np.max(V2), np.min(U2), np.min(S2), np.min(V2),
                np.count_nonzero(B2), det(U2), det(V2), trace(U2), trace(V2)]
                f(z,idx:idx + len(temp)-1) = temp
                idx = idx + len(temp)

            # correlation between SVD matrices
            corrS = np.corrcoef(S,S2)
            corrU = np.corrcoef(U,U2)
            corrV = np.corrcoef(V,V2)

            # correlation between eigenvalues of SVD
            correV = np.corrcoef(eVB,eVB2)
            correU = np.corrcoef(eUB,eUB2)
            xcorreV = np.correlate(eVB,eVB2)
            xcorreU = np.correlate(eUB,eUB2)
            temp = [corrS[0,1], corrU[0,1], corrV[0,1], correV[0,1], correU[0,1], mean(xcorreV), std(xcorreV, ddof=1), np.min(xcorreV), np.max(xcorreV). np.mean(xcorreU), std(xcorreU, ddof=1), np.min(xcorreU), np.max(xcorreU)]

            f[z,idx:idx + len(temp) -1] = temp
            idx = idx + len(temp)
        end
    end

    ## return feature vector
    f = np.swapaxes(f, 0, 1)
    Out = f[:].T

    return Out
Esempio n. 4
0
def ZernikeF(I, returnShape=False):
    """
     Input:     - I: A 2D image


     Output:    - Out: A (1x92) vector containing 92 metrics based on Zernike
                  moments
    """
    # ************************************************************************
    # Modified for MRI feature extraction by the Department of Diagnostic
    # and Interventional Radiology, University Hospital of Tuebingen, Germany
    # and the Institute of Signal Processing and System Theory University of
    # Stuttgart, Germany. Last modified: November 2016
    #
    # This implementation is part of ImFEATbox, a toolbox for image feature
    # extraction and analysis. Available online at:
    # https://github.com/annikaliebgott/ImFEATbox
    #
    # Contact: [email protected]
    # ************************************************************************
    #
    # Copyright C 2014 Amir Tahmasbi
    # Texas A&M University
    # [email protected]
    # http://people.tamu.edu/~amir.tahmasbi/index.html
    #
    # License Agreement: To acknowledge the use of the code please cite the
    #                    following papers:
    #
    # [1] A. Tahmasbi, F. Saki, S. B. Shokouhi,
    #     Classification of Benign and Malignant Masses Based on Zernike Moments,
    #     Comput. Biol. Med., vol. 41, no. 8, pp. 726-735, 2011.
    #
    # [2] F. Saki, A. Tahmasbi, H. Soltanian-Zadeh, S. B. Shokouhi,
    #     Fast opposite weight learning rules with application in breast cancer
    #     diagnosis, Comput. Biol. Med., vol. 43, no. 1, pp. 32-41, 2013.


    if returnShape:
        return (92,1)

    # reserve space for the variables
    Z = np.zeros(20, dtype=_complex_dtype())
    A = np.zeros(20)
    Phi = np.zeros(20)

    ## determine the moments for different orders
    # TODO ???????????? order always = number of repetition ?
    for m in range(2,42,2): #m=2:2:40
        n = m

        # convert image to square size image
        s = np.shape(I)
        if s[0] < s[1]:
            p = conv2float(I[:,0:s[0]])
        elif s[0] > s[1]:
            p = conv2float(I[0 : s[1],:])
        elif s[0] == s[1]:
            p = conv2float(I)

        # determine Zernike moments
        N = np.shape(p)[0]
        x = range(1, N+1) #1:N
        y = x
        [X,Y] = np.meshgrid(x,y)
        R = np.sqrt(np.power((2*X)-N-1,2)+(np.power((2*Y)-N-1,2)))/float(N)
        Theta = np.arctan2((N-1-(2*Y)+2),((2*X)-N+1-2))
        #R[R<=1] = (R[R<=1] * R[R<=1])

        #R[np.less_equal(R,1)] = R[np.less_equal(R,1)] * R[np.less_equal(R,1)]
        #R = np.reshape(np.less_equal(R,np.ones(R.shape))*1, R.shape ) * R
        R[R>1] = 0
        #R[np.less(R,1)] = 0
        #plt.imshow(R);plt.show()

        # compute Zernike Polynomials
        Rad = np.zeros(R.shape, dtype=_complex_dtype())

        # TODO: for loop does not make sense...?
        for s in range(0,(n-abs(m))/2+1): # 0:(n-abs(m))/2
            c = np.power(-1,s)*factorial(n-s)/(factorial(s)*factorial((n+np.abs(m))/2.0-s)*factorial((n-np.abs(m))/2.0-s))
            Rad = Rad + c * np.power(R,(n-2*s))

        # calculate moments
        Product = p*Rad*np.exp(-1j*m*Theta)
        Zernike = np.sum(Product)

        # count number of pixels inside the unit circle and normalize moments
        cnt = np.count_nonzero(R)+1
        Z[m/2-1] = (n+1)*Zernike / float(cnt)

        # calculate amplitude and phase (in degrees) of the moments
        A[m/2-1] = np.real(np.abs(Zernike))
        Phi[m/2-1] = np.real(np.angle(Zernike)*180/np.pi)

    # calculate mean, std and max values for Z, A and Phi
    mean_Z = np.mean(Z)
    mean_A = np.mean(A)
    mean_Phi = np.mean(Phi)

    std_Z = np.std(Z, ddof=1)
    std_A = np.std(A, ddof=1)
    std_Phi = np.std(Phi, ddof=1)

    max_Z = Z[np.argmax(np.abs(Z))]
    max_A = np.max(A)
    max_Phi = np.max(Phi)

    ## return feature vector

    Out = np.hstack([np.real(Z), np.imag(Z), A, Phi, np.real(mean_Z), np.imag(mean_Z), mean_A, mean_Phi,
        np.real(std_Z), np.imag(std_Z), std_A, std_Phi, np.real(max_Z), np.imag(max_Z), max_A, max_Phi])

    return Out
Esempio n. 5
0
def SVDF(I, returnShape=False):
    """
     Input:     - I: A 2D image


     Output:    - Out: A (1x780) vector containing 780 metrics calculated
                  from singular value decomposition
    """
    # ************************************************************************
    # Implemented for MRI feature extraction by the Department of Diagnostic
    # and Interventional Radiology, University Hospital of Tuebingen, Germany
    # and the Institute of Signal Processing and System Theory University of
    # Stuttgart, Germany. Last modified: November 2016
    #
    # This implementation is part of ImFEATbox, a toolbox for image feature
    # extraction and analysis. Available online at:
    # https://github.com/annikaliebgott/ImFEATbox
    #
    # Contact: [email protected]
    # ************************************************************************

    if returnShape:
        return (780,1)

    ## Calculate Singular Value Decomposition of the image

    # convert image to float
    I = conv2float(I)

    I = I.T

    # initialize feature variables
    dia_elements = np.zeros((np.min(np.shape(I)),3))
    eig_U = np.zeros((np.shape(I)[0],3))
    eig_V = np.zeros((np.shape(I)[1],3))
    det_U = np.zeros(3)
    det_V = np.zeros(3)
    trace_U = np.zeros(3)
    trace_V = np.zeros(3)
    rank_U = np.zeros(3)
    rank_V = np.zeros(3)
    median_eig_U = np.zeros(3)
    median_eig_V = np.zeros(3)
    max_eig_U = np.zeros(3)
    max_eig_V = np.zeros(3)
    mean_U = np.zeros(3)
    mean_V = np.zeros(3)
    mean_S = np.zeros(3)
    std_U = np.zeros(3)
    std_V = np.zeros(3)
    std_S = np.zeros(3)
    skewness_U = np.zeros(3)
    skewness_V = np.zeros(3)
    kurtosis_U = np.zeros(3)
    kurtosis_V = np.zeros(3)


    # Calculate the measures for 3 different orientations
    for z in range(0,3):

        if z == 1:
            # rotate image by 90 degree
            I = imrotate(I, 90, interp='bilinear')
        elif z == 2:
            # rotate image by -90 degree
            I = imrotate(I, -180, interp='bilinear')

        # calculate singular value decomposition with diagonal matrix S and
        # unitary matrices U and V
        [U,S,V] = np.linalg.svd(I)

        #U, V = U.T, V.T
        ## feature extraction

        # calculate diagonal elements of matrix S
        #for i in range(0, np.count_nonzero(S)):
        dia_elements[:,z] = S[:]

        # eigen values of U and V
        eig_U[:,z] = np.linalg.eig(U)[0]
        eig_V[:,z] = np.linalg.eig(V)[0]

        # determinant of U and V
        det_U[z] = np.linalg.det(U)
        det_V[z] = np.linalg.det(V)

        # trace of U and V
        trace_U[z] = np.trace(U)
        trace_V[z] = np.trace(V)

        # rank of U and V
        rank_U[z] = np.linalg.matrix_rank(U)
        rank_V[z] = np.linalg.matrix_rank(V)

        # skewness of U and V
        skewness_U[z] = skew(np.ndarray.flatten(U))
        skewness_V[z] = skew(np.ndarray.flatten(V))

        # kurtosis of U and V
        kurtosis_U[z] = kurtosis(np.ndarray.flatten(U), fisher=False, bias=False)
        kurtosis_V[z] = kurtosis(np.ndarray.flatten(V), fisher=False, bias=False)

        # mean of U, V and S
        mean_U[z] = np.mean(U)
        mean_V[z] = np.mean(V)
        mean_S[z] = np.mean(S)

        # standard deviation of U, V and S
        std_U[z] = np.std(U, ddof=1)
        std_V[z] = np.std(V, ddof=1)
        std_S[z] = np.std(S, ddof=1)

        # median of eigen values of U and V
        median_eig_U[z] = np.median(eig_U[:,z])
        median_eig_V[z] = np.median(eig_V[:,z])

        # maximum of eigen values of U and V
        max_eig_U[z] = np.max(eig_U[:,z])
        max_eig_V[z] = np.max(eig_V[:,z])

    ## return feature vector

    #np.prod(np.shape(eig_U[:100,:]))

    Out = np.hstack([np.ndarray.flatten(dia_elements[:40,:]),
        np.ndarray.flatten(eig_U[:100,:]),
        np.ndarray.flatten(eig_V[:100,:]),
        det_U, det_V, trace_U, trace_V, rank_U, rank_V, skewness_U, skewness_V,
        kurtosis_U, kurtosis_V, mean_U, mean_V, mean_S, std_U, std_V, std_S,
        median_eig_U, median_eig_V, max_eig_U, max_eig_V])

    return Out
Esempio n. 6
0
def LawF(I, returnShape=False):
    """
 Input:     - I: A 2D image


 Output:    - Out: A (1x58) vector containing 58 metrics calculated from
                   the 2nd and 4th moments of the results of the image
                   filtered by 25 different filters
    """
    # ************************************************************************
    # Implemented for MRI feature extraction by the Department of Diagnostic
    # and Interventional Radiology, University Hospital of Tuebingen, Germany
    # and the Institute of Signal Processing and System Theory University of
    # Stuttgart, Germany. Last modified: November 2016
    #
    # This implementation is part of ImFEATbox, a toolbox for image feature
    # extraction and analysis. Available online at:
    # https://github.com/annikaliebgott/ImFEATbox
    #
    # Contact: [email protected]
    # ************************************************************************
    #
    # Law features are constructed from a set of five one-dimensional filters:
    # edge, spot, ripple, wave and lowpass. By applying a one-dimensional
    # filter in the horizontal direction followed by a one-dimensional filter
    # in the vertical direction, this results in 25 different two-dimensional
    # filters.

    if returnShape:
        return (58, 1)

    ## filter image horizontal and vertical

    #converte to double
    I = conv2float(I)

    # define 5 filters
    edge = np.array([[-1, -2, 0, 2, 1]])
    low_pass = np.array([[1, 4, 6, 4, 1]])
    spots = np.array([[-1, 0, 2, 0, 1]])
    ripples = np.array([[1, -4, 6, -4, 1]])
    waves = np.array([[-1, 2, 0, -2, 1]])

    # edge filter
    ee = convolve2d_image(edge, edge, I)
    le = convolve2d_image(edge, low_pass, I)
    se = convolve2d_image(edge, spots, I)
    re = convolve2d_image(edge, ripples, I)
    we = convolve2d_image(edge, waves, I)

    #spots
    es = convolve2d_image(spots, edge, I)
    ls = convolve2d_image(spots, low_pass, I)
    ss = convolve2d_image(spots, spots, I)
    rs = convolve2d_image(spots, ripples, I)
    ws = convolve2d_image(spots, waves, I)

    #ripples
    er = convolve2d_image(ripples, edge, I)
    lr = convolve2d_image(ripples, low_pass, I)
    sr = convolve2d_image(ripples, spots, I)
    rr = convolve2d_image(ripples, ripples, I)
    wr = convolve2d_image(ripples, waves, I)

    #waves
    ew = convolve2d_image(waves, edge, I)
    lw = convolve2d_image(waves, low_pass, I)
    sw = convolve2d_image(waves, spots, I)
    rw = convolve2d_image(waves, ripples, I)
    ww = convolve2d_image(waves, waves, I)

    #low pass
    el = convolve2d_image(low_pass, edge, I)
    ll = convolve2d_image(low_pass, low_pass, I)
    sl = convolve2d_image(low_pass, spots, I)
    rl = convolve2d_image(low_pass, ripples, I)
    wl = convolve2d_image(low_pass, waves, I)

    ## feature extraction

    # determine the 2nd and 4th moment of the filtered images
    m2 = np.hstack([
        moment(ee.ravel(), 2),
        moment(se.ravel(), 2),
        moment(re.ravel(), 2),
        moment(we.ravel(), 2),
        moment(le.ravel(), 2),
        moment(es.ravel(), 2),
        moment(ss.ravel(), 2),
        moment(rs.ravel(), 2),
        moment(ws.ravel(), 2),
        moment(ls.ravel(), 2),
        moment(er.ravel(), 2),
        moment(sr.ravel(), 2),
        moment(rr.ravel(), 2),
        moment(wr.ravel(), 2),
        moment(lr.ravel(), 2),
        moment(ew.ravel(), 2),
        moment(sw.ravel(), 2),
        moment(rw.ravel(), 2),
        moment(ww.ravel(), 2),
        moment(lw.ravel(), 2),
        moment(el.ravel(), 2),
        moment(sl.ravel(), 2),
        moment(rl.ravel(), 2),
        moment(wl.ravel(), 2),
        moment(ll.ravel(), 2)
    ])

    m4 = np.hstack([
        moment(ee.ravel(), 4),
        moment(se.ravel(), 4),
        moment(re.ravel(), 4),
        moment(we.ravel(), 4),
        moment(le.ravel(), 4),
        moment(es.ravel(), 4),
        moment(ss.ravel(), 4),
        moment(rs.ravel(), 4),
        moment(ws.ravel(), 4),
        moment(ls.ravel(), 4),
        moment(er.ravel(), 4),
        moment(sr.ravel(), 4),
        moment(rr.ravel(), 4),
        moment(wr.ravel(), 4),
        moment(lr.ravel(), 4),
        moment(ew.ravel(), 4),
        moment(sw.ravel(), 4),
        moment(rw.ravel(), 4),
        moment(ww.ravel(), 4),
        moment(lw.ravel(), 4),
        moment(el.ravel(), 4),
        moment(sl.ravel(), 4),
        moment(rl.ravel(), 4),
        moment(wl.ravel(), 4),
        moment(ll.ravel(), 4)
    ])

    # mean of the moments
    mean_m2 = np.mean(m2)
    mean_m4 = np.mean(m4)

    # standard deviation of the moments
    std_m2 = np.std(m2, ddof=1)
    std_m4 = np.std(m4, ddof=1)

    # maximum and minimum values of the moments
    max_m2 = np.max(m2)
    max_m4 = np.max(m4)
    min_m2 = np.min(m2)
    min_m4 = np.min(m4)

    ## return feature vector
    Out = np.hstack([
        m2, m4, mean_m2, mean_m4, std_m2, std_m4, max_m2, max_m4, min_m2,
        min_m4
    ])
    return Out
Esempio n. 7
0
def HarrisF(I, plotflag=False, N_s=0, returnShape=False):
    """
     Input:     - I: A 2D image
                - plotflag: a flag to enable/disable visualization
                  Default: plotflag = false
                - N_s: number of points considered to be the strongest points.
                  Default: N_s = ceil(0.1*N) (N: number of detected corners)

     Output:    - Out: A (1x10) vector containing 10 metrics calculated based
                       on corner points detected with Harris-Stephens algorithm
    """
    #
    # ************************************************************************
    # Implemented for MRI feature extraction by the Department of Diagnostic
    # and Interventional Radiology, University Hospital of Tuebingen, Germany
    # and the Institute of Signal Processing and System Theory University of
    # Stuttgart, Germany. Last modified: November 2016
    #
    # This implementation is part of ImFEATbox, a toolbox for image feature
    # extraction and analysis. Available online at:
    # https://github.com/annikaliebgott/ImFEATbox
    #
    # Contact: [email protected]
    # ************************************************************************

    if returnShape:
        return (10, 1)

    # convert image
    I = conv2float(I)

    if np.iscomplexobj(I):
        I = np.real(I)

    # calculation of corner points using Harris-Stephens algorithm
    threshold = 7e-3

    N_s = 0
    c = corner_peaks(corner_harris(I), min_distance=3, threshold_rel=threshold)

    ## extract features
    N = c.shape[0]

    if N_s == 0 or N_s > 0.5 * N:
        N_s = int(np.ceil(0.1 * N))

    c_s = corners = corner_peaks(corner_harris(I),
                                 min_distance=3,
                                 num_peaks=N_s,
                                 threshold_rel=threshold)

    # determine center  of gravity for all points
    x_gravity = np.sum(c[:, 0] / float(N))
    y_gravity = np.sum(c[:, 1] / float(N))

    # deterime center of gravity for the strongest points
    x_gravity_s = np.sum(c_s[:, 0] / float(N_s))
    y_gravity_s = np.sum(c_s[:, 1] / float(N_s))

    # display the results
    if plotflag:
        plt.scatter(c[:, 1], c[:, 0], color='blue', marker="+", s=50)
        plt.scatter(c_s[:, 1], c_s[:, 0], color='red', marker="+", s=100)
        plt.plot(x_gravity_s,
                 y_gravity_s,
                 color='green',
                 marker="*",
                 MarkerSize=30)
        plt.show()
        #scatter(c(:,1),c(:,2),'+')
        #scatter(c_s(:,1),c_s(:,2),'g+')
        #plot(x_gravity_s, y_gravity_s,'r*','MarkerSize',10)

    # density of corner points
    dens = N / float(I.size)

    #standard derivation
    std_x = np.std(c[:, 0], ddof=1)
    std_y = np.std(c[:, 1], ddof=1)
    std_x_s = np.std(c_s[:, 0], ddof=1)
    std_y_s = np.std(c_s[:, 1], ddof=1)

    ## return feature vector
    Out = np.array([
        N, x_gravity, y_gravity, x_gravity_s, y_gravity_s, dens, std_x, std_y,
        std_x_s, std_y_s
    ])

    print(Out)
    print(Out.shape)

    return Out
Esempio n. 8
0
def GradientF(I, typeflag=None, gradtype=None, returnShape=False):
    """
         Input:     - I: A 2D image
                    - typeflag: Struct of logicals to permit extracting features
                      based on desired characteristics:
                           + typeflag['global']: all features
                           + typeflag['texture']: all features
                           + typeflag['gradient']: all features
                           + typeflag['entropy']: only features based on entropy
                      default: all features are being extracted
                      For more information see README.txt
                    - gradtype: Struct of logicals to choose which type of
                      gradient should be applied:
                           + gradtype['first']: first order gradient
                           + gradtype['second']: second order gradient (Laplacian)
                      default: both types of gradients are used
                    - returnShape: A logical flag to return only the shape of features.
                      Default: False


         Output:    - Out: A (1x81) vector containing 81 metrics calculated from
                      image gradients
    """
    # ************************************************************************
    # Implemented for MRI feature extraction by the Department of Diagnostic
    # and Interventional Radiology, University Hospital of Tuebingen, Germany
    # and the Institute of Signal Processing and System Theory University of
    # Stuttgart, Germany. Last modified: February 2017
    #
    # This implementation is part of ImFEATbox, a toolbox for image feature
    # extraction and analysis. Available online at:
    # https://github.com/annikaliebgott/ImFEATbox
    #
    # Contact: [email protected]
    # ************************************************************************
    #
    # Implementation based on:  McGee et al.: "Image metric-based correction
    #                           (Autocorrection) of motion effects: Analysis of
    #                           image metrics", Journal of Magnetic Resonance
    #                           Imaging, vol. 11, issue 2, p. 174-181, Feb 2000

    ##

    if typeflag == None:
        typeflag = dict()
        typeflag['global'] = True
        typeflag['texture'] = True
        typeflag['entropy'] = True

    if gradtype == None:
        gradtype = dict()
        gradtype['first'] = True
        gradtype['second'] = True

    if gradtype['first'] == gradtype['second'] == False:
        # catching this case. gradient like this does not make sense.
        # so we throw a warning and set both to True
        gradtype['first'] = True
        gradtype['second'] = True
        warnings.warn(
            "gradtype first and second are false. Using default settings.")

    if returnShape:
        ## returns only the shape of feature vectors depending on parameters
        if typeflag['global'] or typeflag['texture'] or typeflag['gradient']:
            if gradtype['first'] and gradtype['second']:
                return (81, 1)
            elif gradtype['first']:
                return (36, 1)
            else:
                return (45, 1)
        elif gradtype['first'] and gradtype['second']:
            return (9, 1)
        elif gradtype['first']:
            return (4, 1)
        else:
            return (5, 1)

    # Check for color image and convert to grayscale
    if isColorImage(I):
        I = rgb2grayscale(I)

    # make float
    I = conv2float(I)

    n = I.size

    ## define gradients
    if gradtype['first']:
        # gradient 1
        # gradient direction: x
        g1_x = np.array([[1, -1], [0, 0]])
        # gradient direction: y
        g1_y = np.array([[1, 0], [-1, 0]])

        # gradient 2
        g2_x = np.array([[0, 0, 0], [1, 0, -1], [0, 0, 0]])

        g2_y = np.array([[0, 1, 0], [0, 0, 0], [0, -1, 0]])

    if gradtype['second']:
        # laplacian 1
        l1_x = np.array([[0, 0, 0], [-1, 2, -1], [0, 0, 0]])

        l1_y = np.array([[0, -1, 0], [0, 2, 0], [0, -1, 0]])

        # laplacian 2
        l2 = np.array([[-1, -2, -1], [-2, 12, -2], [-1, -2, -1]])

        # laplacian 3
        l3 = np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]])

        # laplacian 4
        l4 = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])

    ## convolve image
    if gradtype['first']:
        G1_x = convolve2d(I, g1_x, boundary='fill', mode='full')
        G1_y = convolve2d(I, g1_y, boundary='fill', mode='full')
        G2_x = convolve2d(I, g2_x, boundary='fill', mode='full')
        G2_y = convolve2d(I, g2_y, boundary='fill', mode='full')

    if gradtype['second']:
        L1_x = convolve2d(I, l1_x, boundary='fill', mode='full')
        L1_y = convolve2d(I, l1_y, boundary='fill', mode='full')
        L2 = convolve2d(I, l2, boundary='fill', mode='full')
        L3 = convolve2d(I, l3, boundary='fill', mode='full')
        L4 = convolve2d(I, l4, boundary='fill', mode='full')

    ## extract features

    # summed gradients
    if gradtype['first']:
        G1_y_sum = np.sum(np.abs(G1_y))
        G1_x_sum = np.sum(np.abs(G1_x))
        G2_x_sum = np.sum(np.abs(G2_x))
        G2_y_sum = np.sum(np.abs(G2_y))

    if gradtype['second']:
        L1_x_sum = np.sum(np.abs(L1_x))
        L1_y_sum = np.sum(np.abs(L1_y))
        L2_sum = np.sum(np.abs(L2))
        L3_sum = np.sum(np.abs(L3))
        L4_sum = np.sum(np.abs(L4))

    # normalized gradients
    if gradtype['first']:
        G1_x_norm = np.abs(G1_x) / G1_x_sum
        G1_y_norm = np.abs(G1_y) / G1_y_sum
        G2_x_norm = np.abs(G2_x) / G2_x_sum
        G2_y_norm = np.abs(G2_y) / G2_y_sum

    if gradtype['second']:
        L1_x_norm = np.abs(L1_x) / L1_x_sum
        L1_y_norm = np.abs(L1_y) / L1_y_sum
        L2_norm = np.abs(L2) / L2_sum
        L3_norm = np.abs(L3) / L3_sum
        L4_norm = np.abs(L4) / L4_sum

    if typeflag['global'] or typeflag['texture'] or typeflag['gradient']:
        # sum of squared gradients
        if gradtype['first']:
            G1_x_2 = np.sum(np.power(G1_x, 2)) / n
            G1_y_2 = np.sum(np.power(G1_y, 2)) / n
            G2_x_2 = np.sum(np.power(G2_x, 2)) / n
            G2_y_2 = np.sum(np.power(G2_y, 2)) / n
        if gradtype['second']:
            L1_x_2 = np.sum(np.power(L1_x, 2)) / n
            L1_y_2 = np.sum(np.power(L1_y, 2)) / n
            L2_2 = np.sum(np.power(L2, 2)) / n
            L3_2 = np.sum(np.power(L3, 2)) / n
            L4_2 = np.sum(np.power(L4, 2)) / n

        # sum of 4th power of gradients
        if gradtype['first']:
            G1_x_4 = np.sum(np.power(G1_x, 4)) / n
            G1_y_4 = np.sum(np.power(G1_y, 4)) / n
            G2_x_4 = np.sum(np.power(G2_x, 4)) / n
            G2_y_4 = np.sum(np.power(G2_y, 4)) / n

        if gradtype['second']:
            L1_x_4 = np.sum(np.power(L1_x, 4)) / n
            L1_y_4 = np.sum(np.power(L1_y, 4)) / n
            L2_4 = np.sum(np.power(L2, 4)) / n
            L3_4 = np.sum(np.power(L3, 4)) / n
            L4_4 = np.sum(np.power(L4, 4)) / n

        # maximum of normalized gradients
        if gradtype['first']:
            G1_x_norm_max = np.max(G1_x_norm[:])
            G1_y_norm_max = np.max(G1_y_norm[:])
            G2_x_norm_max = np.max(G2_x_norm[:])
            G2_y_norm_max = np.max(G2_y_norm[:])

        if gradtype['second']:
            L1_x_norm_max = np.max(L1_x_norm[:])
            L1_y_norm_max = np.max(L1_y_norm[:])
            L2_norm_max = np.max(L2_norm[:])
            L3_norm_max = np.max(L3_norm[:])
            L4_norm_max = np.max(L4_norm[:])

        # standard deviation of normalized gradients
        if gradtype['first']:
            G1_x_norm_std = np.std(G1_x_norm, ddof=1)
            G1_y_norm_std = np.std(G1_y_norm, ddof=1)
            G2_x_norm_std = np.std(G2_x_norm, ddof=1)
            G2_y_norm_std = np.std(G2_y_norm, ddof=1)

        if gradtype['second']:
            L1_x_norm_std = np.std(L1_x_norm, ddof=1)
            L1_y_norm_std = np.std(L1_y_norm, ddof=1)
            L2_norm_std = np.std(L2_norm, ddof=1)
            L3_norm_std = np.std(L3_norm, ddof=1)
            L4_norm_std = np.std(L3_norm, ddof=1)

        # mean of normalized gradients
        if gradtype['first']:
            G1_x_norm_mean = np.mean(G1_x_norm)
            G1_y_norm_mean = np.mean(G1_y_norm)
            G2_x_norm_mean = np.mean(G2_x_norm)
            G2_y_norm_mean = np.mean(G2_y_norm)

        if gradtype['second']:
            L1_x_norm_mean = np.mean(L1_x_norm)
            L1_y_norm_mean = np.mean(L1_y_norm)
            L2_norm_mean = np.mean(L2_norm)
            L3_norm_mean = np.mean(L3_norm)
            L4_norm_mean = np.mean(L3_norm)

        # sum of normalized gradients squared
        if gradtype['first']:
            G1_x_norm_2 = np.sum(np.power(G1_x_norm, 2)) / n
            G1_y_norm_2 = np.sum(np.power(G1_y_norm, 2)) / n
            G2_x_norm_2 = np.sum(np.power(G2_x_norm, 2)) / n
            G2_y_norm_2 = np.sum(np.power(G2_y_norm, 2)) / n

        if gradtype['second']:
            L1_x_norm_2 = np.sum(np.power(L1_x_norm, 2)) / n
            L1_y_norm_2 = np.sum(np.power(L1_y_norm, 2)) / n
            L2_norm_2 = np.sum(np.power(L2_norm, 2)) / n
            L3_norm_2 = np.sum(np.power(L3_norm, 2)) / n
            L4_norm_2 = np.sum(np.power(L4_norm, 2)) / n

        # sum of normalized gradients to 4th power
        if gradtype['first']:
            G1_x_norm_4 = np.sum(np.power(G1_x_norm, 4)) / n
            G1_y_norm_4 = np.sum(np.power(G1_y_norm, 4)) / n
            G2_x_norm_4 = np.sum(np.power(G2_x_norm, 4)) / n
            G2_y_norm_4 = np.sum(np.power(G2_y_norm, 4)) / n

        if gradtype['second']:
            L1_x_norm_4 = np.sum(np.power(L1_x_norm, 4)) / n
            L1_y_norm_4 = np.sum(np.power(L1_y_norm, 4)) / n
            L2_norm_4 = np.sum(np.power(L2_norm, 4)) / n
            L3_norm_4 = np.sum(np.power(L3_norm, 4)) / n
            L4_norm_4 = np.sum(np.power(L4_norm, 4)) / n

    # marginal entropies of normalized gradients
    if gradtype['first']:
        G1_x_E = -np.sum(G1_x_norm[np.nonzero(G1_x_norm)] *
                         np.log2(G1_x_norm[np.nonzero(G1_x_norm)]))
        G1_y_E = -np.sum(
            G1_y_norm[G1_y_norm != 0] * np.log2(G1_y_norm[G1_y_norm != 0]))
        G2_x_E = -np.sum(
            G2_x_norm[G2_x_norm != 0] * np.log2(G2_x_norm[G2_x_norm != 0]))
        G2_y_E = -np.sum(
            G2_y_norm[G2_y_norm != 0] * np.log2(G2_y_norm[G2_y_norm != 0]))

    if gradtype['second']:
        L1_x_E = -np.sum(
            L1_x_norm[L1_x_norm != 0] * np.log2(L1_x_norm[L1_x_norm != 0]))
        L1_y_E = -np.sum(
            L1_y_norm[L1_y_norm != 0] * np.log2(L1_y_norm[L1_y_norm != 0]))
        L2_E = -np.sum(L2_norm[L2_norm != 0] * np.log2(L2_norm[L2_norm != 0]))
        L3_E = -np.sum(L3_norm[L3_norm != 0] * np.log2(L3_norm[L3_norm != 0]))
        L4_E = -np.sum(L4_norm[L4_norm != 0] * np.log2(L4_norm[L4_norm != 0]))

    ## Build output vector Out, we swapped x and y here to match the matlab code
    if typeflag['global'] or typeflag['texture'] or typeflag['gradient']:
        if gradtype['first'] and gradtype['second']:
            Out = np.array([
                G1_y_sum,
                G1_x_sum,
                G2_y_sum,
                G2_x_sum,
                L1_y_sum,
                L1_x_sum,
                L2_sum,
                L3_sum,
                L4_sum,
                G1_y_2,
                G1_x_2,
                G2_y_2,
                G2_x_2,
                L1_y_2,
                L1_x_2,
                L2_2,
                L3_2,
                L4_2,
                G1_y_4,
                G1_x_4,
                G2_y_4,
                G2_x_4,
                L1_y_4,
                L1_x_4,
                L2_4,
                L3_4,
                L4_4,  #G2_y_4
                G1_y_norm_max,
                G1_x_norm_max,
                G2_y_norm_max,
                G2_x_norm_max,
                L1_y_norm_max,
                L1_x_norm_max,
                L2_norm_max,
                L3_norm_max,
                L4_norm_max,
                G1_y_norm_std,
                G1_x_norm_std,
                G2_y_norm_std,
                G2_x_norm_std,
                L1_y_norm_std,
                L1_x_norm_std,
                L2_norm_std,
                L3_norm_std,
                L4_norm_std,
                G1_y_norm_mean,
                G1_x_norm_mean,
                G2_y_norm_mean,
                G2_x_norm_mean,
                L1_y_norm_mean,
                L1_x_norm_mean,
                L2_norm_mean,
                L3_norm_mean,
                L4_norm_mean,
                G1_y_norm_2,
                G1_x_norm_2,
                G2_y_norm_2,
                G2_x_norm_2,
                L1_y_norm_2,
                L1_x_norm_2,
                L2_norm_2,
                L3_norm_2,
                L4_norm_2,
                G1_y_norm_4,
                G1_x_norm_4,
                G2_y_norm_4,
                G2_x_norm_4,
                L1_y_norm_4,
                L1_x_norm_4,
                L2_norm_4,
                L3_norm_4,
                L4_norm_4,
                G1_y_E,
                G1_x_E,
                G2_y_E,
                G2_x_E,
                L1_y_E,
                L1_x_E,
                L2_E,
                L3_E,
                L4_E
            ])
        elif gradtype['first']:
            Out = [
                G1_y_sum, G1_x_sum, G2_y_sum, G2_x_sum, G1_y_2, G1_x_2, G2_y_2,
                G2_x_2, G1_y_4, G1_x_4, G2_y_4, G2_x_4, G1_y_norm_max,
                G1_x_norm_max, G2_y_norm_max, G2_x_norm_max, G1_y_norm_std,
                G1_x_norm_std, G2_y_norm_std, G2_x_norm_std, G1_y_norm_mean,
                G1_x_norm_mean, G2_y_norm_mean, G2_x_norm_mean, G1_y_norm_2,
                G1_x_norm_2, G2_y_norm_2, G2_x_norm_2, G1_y_norm_4,
                G1_x_norm_4, G2_y_norm_4, G2_x_norm_4, G1_y_E, G1_x_E, G2_y_E,
                G2_x_E
            ]
        else:
            Out = [
                L1_y_sum, L1_x_sum, L2_sum, L3_sum, L4_sum, L1_y_2, L1_x_2,
                L2_2, L3_2, L4_2, L1_y_4, L1_x_4, L2_4, L3_4, L4_4,
                L1_y_norm_max, L1_x_norm_max, L2_norm_max, L3_norm_max,
                L4_norm_max, L1_y_norm_std, L1_x_norm_std, L2_norm_std,
                L3_norm_std, L4_norm_std, L1_y_norm_mean, L1_x_norm_mean,
                L2_norm_mean, L3_norm_mean, L4_norm_mean, L1_y_norm_2,
                L1_x_norm_2, L2_norm_2, L3_norm_2, L4_norm_2, L1_y_norm_4,
                L1_x_norm_4, L2_norm_4, L3_norm_4, L4_norm_4, L1_y_E, L1_x_E,
                L2_E, L3_E, L4_E
            ]
    elif gradtype['first'] and gradtype['second']:
        Out = [
            G1_y_E, G1_x_E, G2_y_E, G2_x_E, L1_y_E, L1_x_E, L2_E, L3_E, L4_E
        ]
    elif gradtype['first']:
        Out = [G1_y_E, G1_x_E, G2_y_E, G2_x_E]
    else:
        Out = [L1_y_E, L1_x_E, L2_E, L3_E, L4_E]
    return Out