U
    ?h$t                     @   s   d dl Z d dlZd dlmZ ddlmZmZ ddl	m
Z
mZ ddlmZ ddlmZ ddlmZ dd	lmZmZmZ d
d Zdd Zdd Zdd ZG dd dee
ZdS )    N   )check_nD_supported_float_type)DescriptorExtractorFeatureDetector)gaussian)rescale)img_as_float   )
_local_max_ori_distances_update_histogramc                 C   s$   | | }| | ||  }|| | S )z5Compute edgeness (eq. 18 of Otero et. al. IPOL paper) )ZhxxZhyyZhxytraceZdeterminantr   r   F/var/www/html/venv/lib/python3.8/site-packages/skimage/feature/sift.py	_edgeness   s    r   c                 C   s   |d }|d }|d }| |d ||f | |d ||f  }|d9 }| ||d |f | ||d |f  }|d9 }| |||d f | |||d f  }|d9 }|||fS )zGradient of a 3D volume at the provided `positions`.

    For SIFT we only need the gradient at specific positions and do not need
    the gradient at the edge positions, so can just use this simple
    implementation instead of numpy.gradient.
    .r   .r
   .r   r
         ?r   )Zvol	positionsp0p1p2g0g1g2r   r   r   _sparse_gradient   s    $$$r   c                 C   s  |d }|d }|d }d| |||f  }| |d ||f | |d ||f  | }| ||d |f | ||d |f  | }| |||d f | |||d f  | }d| |d |d |f | |d |d |f  | |d |d |f  | |d |d |f   }	d| |d ||d f | |d ||d f  | |d ||d f  | |d ||d f   }
d| ||d |d f | ||d |d f  | ||d |d f  | ||d |d f   }||||	|
|fS )zCompute the non-redundant 3D Hessian terms at the requested positions.

    Source: "Anatomy of the SIFT Method"  p.380 (13)
    r   r   r   r   r
   g      ?r   )dr   r   r   r   Ztwo_d0h00h11h22h01h02h12r   r   r   _hessian(   s.    (((,,,r%   c                 C   sD  |\}}}}}}| \}}	}
|| | }||| | 8 }||| | 8 }|d| | | 7 }||| | 8 }|| ||  | }|| ||  | }|| ||  | }|| ||  | }|| ||  | }|| ||  | }| | ||	  ||
  }| | ||	  ||
  }| | ||	  ||
  }t j|||fddS )a2  Compute position refinement offsets from gradient and Hessian.

    This is equivalent to np.linalg.solve(-H, J) where H is the Hessian
    matrix and J is the gradient (Jacobian).

    This analytical solution is adapted from (BSD-licensed) C code by
    Otero et. al (see SIFT docstring References).
    r   Zaxis)npstack)gradhessr   r    r!   r"   r#   r$   r   r   r   ZdetZaaabacZbbbcccZoffset0Zoffset1Zoffset2r   r   r   _offsets>   s"    	
r0   c                   @   s   e Zd ZdZd+ddZedd Zdd Zdd Zdd Z	dd Z
dd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*S ),SIFTu  SIFT feature detection and descriptor extraction.

    Parameters
    ----------
    upsampling : int, optional
        Prior to the feature detection the image is upscaled by a factor
        of 1 (no upscaling), 2 or 4. Method: Bi-cubic interpolation.
    n_octaves : int, optional
        Maximum number of octaves. With every octave the image size is
        halved and the sigma doubled. The number of octaves will be
        reduced as needed to keep at least 12 pixels along each dimension
        at the smallest scale.
    n_scales : int, optional
        Maximum number of scales in every octave.
    sigma_min : float, optional
        The blur level of the seed image. If upsampling is enabled
        sigma_min is scaled by factor 1/upsampling
    sigma_in : float, optional
        The assumed blur level of the input image.
    c_dog : float, optional
        Threshold to discard low contrast extrema in the DoG. It's final
        value is dependent on n_scales by the relation:
        final_c_dog = (2^(1/n_scales)-1) / (2^(1/3)-1) * c_dog
    c_edge : float, optional
        Threshold to discard extrema that lie in edges. If H is the
        Hessian of an extremum, its "edgeness" is described by
        tr(H)²/det(H). If the edgeness is higher than
        (c_edge + 1)²/c_edge, the extremum is discarded.
    n_bins : int, optional
        Number of bins in the histogram that describes the gradient
        orientations around keypoint.
    lambda_ori : float, optional
        The window used to find the reference orientation of a keypoint
        has a width of 6 * lambda_ori * sigma and is weighted by a
        standard deviation of 2 * lambda_ori * sigma.
    c_max : float, optional
        The threshold at which a secondary peak in the orientation
        histogram is accepted as orientation
    lambda_descr : float, optional
        The window used to define the descriptor of a keypoint has a width
        of 2 * lambda_descr * sigma * (n_hist+1)/n_hist and is weighted by
        a standard deviation of lambda_descr * sigma.
    n_hist : int, optional
        The window used to define the descriptor of a keypoint consists of
        n_hist * n_hist histograms.
    n_ori : int, optional
        The number of bins in the histograms of the descriptor patch.

    Attributes
    ----------
    delta_min : float
        The sampling distance of the first octave. It's final value is
        1/upsampling.
    float_dtype : type
        The datatype of the image.
    scalespace_sigmas : (n_octaves, n_scales + 3) array
        The sigma value of all scales in all octaves.
    keypoints : (N, 2) array
        Keypoint coordinates as ``(row, col)``.
    positions : (N, 2) array
        Subpixel-precision keypoint coordinates as ``(row, col)``.
    sigmas : (N, ) array
        The corresponding sigma (blur) value of a keypoint.
    scales : (N, ) array
        The corresponding scale of a keypoint.
    orientations : (N, ) array
        The orientations of the gradient around every keypoint.
    octaves : (N, ) array
        The corresponding octave of a keypoint.
    descriptors : (N, n_hist*n_hist*n_ori) array
        The descriptors of a keypoint.

    Notes
    -----
    The SIFT algorithm was developed by David Lowe [1]_, [2]_ and later
    patented by the University of British Columbia. Since the patent expired in
    2020 it's free to use. The implementation here closely follows the
    detailed description in [3]_, including use of the same default parameters.

    References
    ----------
    .. [1] D.G. Lowe. "Object recognition from local scale-invariant
           features", Proceedings of the Seventh IEEE International
           Conference on Computer Vision, 1999, vol.2, pp. 1150-1157.
           :DOI:`10.1109/ICCV.1999.790410`

    .. [2] D.G. Lowe. "Distinctive Image Features from Scale-Invariant
           Keypoints", International Journal of Computer Vision, 2004,
           vol. 60, pp. 91–110.
           :DOI:`10.1023/B:VISI.0000029664.99615.94`

    .. [3] I. R. Otero and M. Delbracio. "Anatomy of the SIFT Method",
           Image Processing On Line, 4 (2014), pp. 370–396.
           :DOI:`10.5201/ipol.2014.82`

    Examples
    --------
    >>> from skimage.feature import SIFT, match_descriptors
    >>> from skimage.data import camera
    >>> from skimage.transform import rotate
    >>> img1 = camera()
    >>> img2 = rotate(camera(), 90)
    >>> detector_extractor1 = SIFT()
    >>> detector_extractor2 = SIFT()
    >>> detector_extractor1.detect_and_extract(img1)
    >>> detector_extractor2.detect_and_extract(img2)
    >>> matches = match_descriptors(detector_extractor1.descriptors,
    ...                             detector_extractor2.descriptors,
    ...                             max_ratio=0.6)
    >>> matches[10:15]
    array([[ 10, 412],
           [ 11, 417],
           [ 12, 407],
           [ 13, 411],
           [ 14, 406]])
    >>> detector_extractor1.keypoints[matches[10:15, 0]]
    array([[ 95, 214],
           [ 97, 211],
           [ 97, 218],
           [102, 215],
           [104, 218]])
    >>> detector_extractor2.keypoints[matches[10:15, 1]]
    array([[297,  95],
           [301,  97],
           [294,  97],
           [297, 102],
           [293, 104]])

    r         皙?r   O贁N?
   $         ?皙?      c                 C   s   |dkr|| _ ntd|| _|| _|| | _|| _dd|  d d | | _|| _|| _|	| _	|
| _
|| _|| _|| _d| | _d | _d | _d | _d | _d | _d | _d | _d | _d | _d S )N)r
   r   r;   zupsampling must be 1, 2 or 4r   r
   g,5拢?)
upsampling
ValueError	n_octavesn_scales	sigma_minsigma_inc_dogc_edgen_bins
lambda_oric_maxlambda_descrn_histn_ori	delta_minfloat_dtypescalespace_sigmas	keypointsr   sigmasscalesorientationsoctavesdescriptors)selfr<   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   r   r   r   __init__   s2    

zSIFT.__init__c                 C   s$   | j tjdt| j| jd }|S )z%The sampling distances of all octavesr   dtype)rJ   r(   poweraranger>   rK   )rS   deltasr   r   r   rY      s    zSIFT.deltasc                 C   s<   d}t || j }tt|| d }|| jk r8|| _d S )N   r
   )minr<   intmathlog2r>   )rS   Zimage_shapeZsize_mins0Zmax_octavesr   r   r   _set_number_of_octaves  s
    
zSIFT._set_number_of_octavesc           
      C   s  g }| j dkrt|| j dd}t|| j t| jd | jd   dd}tdt	| j
d | j
 }|| j9 }| jddtjf | jd  |tjddf  }|| _tj|| dd	}t|| jddtjf  }t| jD ]}tj| j
d f|j | jd
d}||d< td| j
d D ].}	t||	d  |||	d f d||	 d q|t|dd || jd k r|| j
 ddddddf }q|S )zSource: "Anatomy of the SIFT Method" Alg. 1
        Construction of the scalespace by gradually blurring (scales) and
        downscaling (octaves) the image.
        r
   )orderr   Zreflectmoder3   Nr   r'   C)rV   ra   )rc   outputr&   )r<   r   r   r]   sqrtr@   rA   r(   rW   rX   r?   rY   newaxisrL   diffranger>   emptyshaperK   appendZmoveaxis)
rS   imageZ
scalespacetmprN   Zvar_diffZgaussian_sigmasooctavesr   r   r   _create_scalespace
  sF    

  
 zSIFT._create_scalespacec                 C   s`   |d d df dk|d d df |d d k @ |d d df dk@ |d d df |d d k @ S )Nr   r
   r   )rS   adimr   r   r   _inrange>  s
    .zSIFT._inrangec           #   	      s  g }g }g }| j d }tt|| jD ]8\}\}}	tt||}
|
jdkr`|t	d q&|j
}d}d}t|D ]}|dkr|
| |
|ddf }
t||
}t||
}t||}||d kr qFt||k|
d tdd	 |D k }t|| k |
d dk}tt||s$ qF|
|  d7  < |
|  d8  < qvtjt||k dd
 |
  }
|  } fdd	|D }||
dddf |
dddf |
dddf f }|}tdD ]&}|d||  |dd|f  7 }q|d   |d   |d     }}}| jd | jd  }| j }t||k}t| jd | j }t|| || || }t||k}|
| | }
|| | }|
ddddf |ddddf  |	 | j}| j||
dddf f t||dddf  } tjt|| ddtjf  dk|| ddtjf  |k dd
}!|||!  ||
|!df  || |!  q&tdd	 t|D }"t|"dkrt dt|}t|}t|}||||"fS )aL  Source: "Anatomy of the SIFT Method" Alg. 4-9
        1) first find all extrema of a (3, 3, 3) neighborhood
        2) use second order Taylor development to refine the positions to
           sub-pixel precision
        3) filter out extrema that have low contrast and lie on edges or close
           to the image borders
        r9   r   )r   r      g333333?Nr
   c                 S   s   g | ]}|d  qS )r
   r   ).0rs   r   r   r   
<listcomp>j  s     z0SIFT._find_localize_evaluate.<locals>.<listcomp>r'   c                    s   g | ]}|  qS r   r   )rw   gfinishedr   r   rx   z  s     r   r3   r   )r   r
   )r   r   g        c                 S   s    g | ]\}}t t||qS r   )r(   fulllen)rw   ipr   r   r   rx     s   zoSIFT found no features. Try passing in an image containing greater intensity contrasts between adjacent pixels.)!rB   	enumerateziprY   r   r(   Zascontiguousarraysizerl   rj   rk   ri   ru   r   r%   r0   logical_andtupleany
logical_orallabsrL   squarerC   r   astyperK   rW   rg   concatenater}   RuntimeError)#rS   ZdogspaceZ	img_shapeZextrema_posZextrema_scalesZextrema_sigmas	thresholdro   rp   deltakeysoshapeZrefinement_iterationsZ
offset_maxr~   r*   r+   offZwrong_position_posZwrong_position_negvalswr   r    r"   Z
sigmaratioZcontrast_thresholdZcontrast_filterZedge_thresholdZedge_responseZedge_filteryxrN   Zborder_filterZoctave_indicesr   rz   r   _find_localize_evaluateB  s    






2$ 4 



zSIFT._find_localize_evaluatec                 C   s0   |d |d  d|d |d  d|d     S )z;Refine the position of the peak by fitting it to a parabolar   r   r
   r   )rS   hr   r   r   _fit  s    z	SIFT._fitc           *      C   sL  g }g }g }g }	t j|| jd}
d}tt|| jD ]\}\}}|t | ||k}t |sfq4|| }|| }|| }|j	dd }|| }|| }d| j
 | }t d||ddt jf  d t}t ||ddt jf  d |d d |d d ft}t j| j| jd}t jdd	| jd}tt|D ]}d|dd< t jt ||df ||df d t ||df ||df d d
dd\}}|| d |||| f }|| d |||| f }|j| jdd}|j| jdd}|||df 8 }|||df 8 }t t |t | } t t ||dt j }!t t || ||  d| j
||  d  }"t |!dt j  | j d | j t}#t j ||#|"|   t !|dd ||dd f}tdD ]}$t j"||dd}q|dd }t#j$|dgdd}%t %t &|| j't (| k|%|k}&t|&d D ]\}}'t |'d |'d t| }(|'| )||(  d d t j | j })|)t jkr|)dt j 8 })|dkr|)|
|< n|| ||) |	| qD|d7 }q>q4t !||| f| _*t !||| f| _+t !||| f| _,t !|
|f| _-t !||	f| _.|S )z~Source: "Anatomy of the SIFT Method" Alg. 11
        Calculates the orientation of the gradient around every keypoint
        rU   r   Nr   r3   r   r
   )r3   gUUUUUU?ijTZindexingsparseFcopyir:   Zsamerb   wrap)/r(   Z
zeros_likerK   r   r   rY   rl   gradientr   rk   rE   maximumrg   r   r\   minimumrj   rD   r|   ri   r}   meshgridrX   rf   r   modarctan2piexpdivideflooraddatr   ZconvolvendiZmaximum_filternonzeror   rF   maxr   r   rO   rN   rP   rQ   )*rS   Zpositions_octZ
scales_octZ
sigmas_octrQ   gaussian_scalespacegradient_spaceZkeypoint_indicesZkeypoint_anglesZkeypoint_octaverP   Z	key_countro   rp   r   in_octr   rO   rN   r   r   sigmaradiusp_minp_maxhistZ
avg_kernelkrcgradient_rowgradient_col	magnitudethetakernelbins_Z
max_filtermaximamZneighorir   r   r   _compute_orientation  s    
" 
 






zSIFT._compute_orientationc                 C   s>   t |}t |}|| ||  }| | ||  }||fS )N)r]   cossin)rS   rowcolZangler   rq   Zrot_rowZrot_colr   r   r   _rotate   s
    

zSIFT._rotatec           0   
   C   s  t | j}tj|| jd | j ftjd| _tjd| jd | j	d}tjd| jd | j	d}t|}t
t|| jD ]\}\}}| j|k}	t|	sqv| j|	 }
| j|	 }| j|	 }| j|	 }||	 }|d jdd }|
| }|| }| jdd| j   | }td| }tjtd||ddtjf  d td}tjt||ddtjf  d |d d |d d ftd}tt |D ]|}|| }|| }tj| j| j| jf| j	d}tjt||df ||df t||df ||df ddd	\}}tj|||df | j	d}tj|||df | j	d}| |||\}}tt |t ||k }|| ||  }}t!|\}} ||df }|d| f }|d |||| f }!|d |||| f }"t"|"|!| }#| j||  }$t#|| ||  d
|$d   }%t|!|! |"|"  |% }&d|$ | j }'|d| j d  |' }(|'})dtj$ | | j }*t tj%|(|}+t tj%|(|},t&|*|#\}-}.t'||-|.|&|+|,|) |(d}t|dtj)*| }d| tj)*| }/tt+|/d}/|/| j|| ddf< qqvdS )zjSource: "Anatomy of the SIFT Method" Alg. 12
        Calculates the descriptor for every keypoint
        r   rU   r
   r   Nr   r   Tr   r   r&   g?i      ),r}   rO   r(   rj   rH   rI   Zuint8rR   rX   rK   r   r   rY   rQ   r   r   rN   rP   rk   rG   r]   rf   Zasarrayr   rg   r\   r   ri   Zzerosr   subtractr   r   r   r   r   r   outerr   r   ZreshapeZlinalgZnormr   )0rS   r   Zn_keyZhistsr   Zkey_numbersro   r   r   r   r   rO   rN   rP   numbersrt   Z
center_posr   r   Zradius_patchr   r   r   Zrad_kr   Z
histogramsr   r   Zr_normZc_normZinsideZr_idxZc_idxr   r   r   Zlam_sigr   r   Zlam_sig_ratioZrc_binsZrc_bin_spacingZori_binsZdist_rZdist_cZnear_tZ
near_t_valZ
descriptorr   r   r   _compute_descriptor'  s    







  



  
zSIFT._compute_descriptorc                 C   s>   t |d t|}t|j| _|j| jdd}| |j |S )Nr   Fr   )r   r	   r   rV   rK   r   r`   rk   )rS   rm   r   r   r   _preprocess  s    
zSIFT._preprocessc                 C   s`   |  |}| |}dd |D }| ||j\}}}}| ||||| | j t| _	dS )zxDetect the keypoints.

        Parameters
        ----------
        image : 2D array
            Input image.

        c                 S   s   g | ]}t j|d dqS r   r'   r(   rh   rw   layerr   r   r   rx     s     zSIFT.detect.<locals>.<listcomp>N)
r   rr   r   rk   r   r   roundr   r\   rM   )rS   rm   r   dog_scalespacer   rO   rN   rQ   r   r   r   detect  s    	

 zSIFT.detectc                 C   s0   |  |}| |}dd |D }| | dS )zExtract the descriptors for all keypoints in the image.

        Parameters
        ----------
        image : 2D array
            Input image.

        c                 S   s   g | ]}t |qS r   )r(   r   )rw   rp   r   r   r   rx     s     z SIFT.extract.<locals>.<listcomp>N)r   rr   r   )rS   rm   r   r   r   r   r   extract  s    	

zSIFT.extractc           	      C   sj   |  |}| |}dd |D }| ||j\}}}}| |||||}| | | j t	| _
dS )zDetect the keypoints and extract their descriptors.

        Parameters
        ----------
        image : 2D array
            Input image.

        c                 S   s   g | ]}t j|d dqS r   r   r   r   r   r   rx     s     z+SIFT.detect_and_extract.<locals>.<listcomp>N)r   rr   r   rk   r   r   r   r   r   r\   rM   )	rS   rm   r   r   r   rO   rN   rQ   r   r   r   r   detect_and_extract  s    	

 

zSIFT.detect_and_extractN)r   r2   r3   r4   r   r5   r6   r7   r8   r9   r:   r;   r2   )__name__
__module____qualname____doc__rT   propertyrY   r`   rr   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r1   Z   s6                    

4lnc	r1   )r]   numpyr(   Zscipy.ndimageZndimager   Z_shared.utilsr   r   Zfeature.utilr   r   Z_shared.filtersr   Z	transformr   utilr	   Z_siftr   r   r   r   r   r%   r0   r1   r   r   r   r   <module>   s   