Example #1
0
def localizeExtremumViaQuadraticFit(i, j, image_index, octave_index, num_intervals, dog_images_in_octave, sigma,
                                    contrast_threshold, image_border_width, eigenvalue_ratio=10,
                                    num_attempts_until_convergence=5):
    """Iteratively refine pixel positions of scale-space extrema via quadratic fit around each extremum's neighbors
    """
    logger.debug('Localizing scale-space extrema...')
    extremum_is_outside_image = False
    image_shape = dog_images_in_octave[0].shape
    for attempt_index in range(num_attempts_until_convergence):
        # need to convert from uint8 to float32 to compute derivatives and need to rescale pixel values to [0, 1] to apply Lowe's thresholds
        first_image, second_image, third_image = dog_images_in_octave[image_index - 1:image_index + 2]
        pixel_cube = stack([first_image[i - 1:i + 2, j - 1:j + 2],
                            second_image[i - 1:i + 2, j - 1:j + 2],
                            third_image[i - 1:i + 2, j - 1:j + 2]]).astype('float32') / 255.
        gradient = computeGradientAtCenterPixel(pixel_cube)
        hessian = computeHessianAtCenterPixel(pixel_cube)
        extremum_update = -lstsq(hessian, gradient, rcond=None)[0]
        if abs(extremum_update[0]) < 0.5 and abs(extremum_update[1]) < 0.5 and abs(extremum_update[2]) < 0.5:
            break
        j += int(round(extremum_update[0]))
        i += int(round(extremum_update[1]))
        image_index += int(round(extremum_update[2]))
        # make sure the new pixel_cube will lie entirely within the image
        if i < image_border_width or i >= image_shape[0] - image_border_width or j < image_border_width or j >= \
                image_shape[1] - image_border_width or image_index < 1 or image_index > num_intervals:
            extremum_is_outside_image = True
            break
    if extremum_is_outside_image:
        logger.debug('Updated extremum moved outside of image before reaching convergence. Skipping...')
        return None
    if attempt_index >= num_attempts_until_convergence - 1:
        logger.debug('Exceeded maximum number of attempts without reaching convergence for this extremum. Skipping...')
        return None
    functionValueAtUpdatedExtremum = pixel_cube[1, 1, 1] + 0.5 * dot(gradient, extremum_update)
    if abs(functionValueAtUpdatedExtremum) * num_intervals >= contrast_threshold:
        xy_hessian = hessian[:2, :2]
        xy_hessian_trace = trace(xy_hessian)
        xy_hessian_det = det(xy_hessian)
        if xy_hessian_det > 0 and eigenvalue_ratio * (xy_hessian_trace ** 2) < (
                (eigenvalue_ratio + 1) ** 2) * xy_hessian_det:
            # Contrast check passed -- construct and return OpenCV KeyPoint object
            keypoint = KeyPoint()
            keypoint.pt = (
            (j + extremum_update[0]) * (2 ** octave_index), (i + extremum_update[1]) * (2 ** octave_index))
            keypoint.octave = octave_index + image_index * (2 ** 8) + int(round((extremum_update[2] + 0.5) * 255)) * (
                        2 ** 16)
            keypoint.size = sigma * (2 ** ((image_index + extremum_update[2]) / float32(num_intervals))) * (
                        2 ** (octave_index + 1))  # octave_index + 1 because the input image was doubled
            keypoint.response = abs(functionValueAtUpdatedExtremum)
            return keypoint, image_index
    return None
Example #2
0
def localizar_Extremo_via_AjusteCuadratico(i, j, indice_imagen, indice_octava, num_intervalos, imagenes_dog_por_octava, sigma, contrast_threshold, ancho_borde_imagen, eigenvalue_ratio=10, num_attempts_until_convergence=5):
    """Refina iterativamente las posiciones de los píxeles de los extremos del espacio de escala mediante un ajuste cuadrático alrededor de los vecinos de cada extremo
       Por eso es costoso esta wada
    """
    logger.debug('Localizando los extremos del espacio-escala...')
    extremo_esta_fuera_Imagen = False
    image_shape = imagenes_dog_por_octava[0].shape
    for attempt_index in range(num_attempts_until_convergence):
        '''
        Los extremos relacionados con el espacio de escala deben convertirse de uint8 a float32
        para calcular derivadas y deben cambiar la escala de los valores de píxeles a [0, 1] para aplicar los umbrales de Lowe's.
        '''
        primera_imagen, segunda_imagen, tercera_imagen = imagenes_dog_por_octava[indice_imagen-1:indice_imagen+2]
        pixel_cube = stack([primera_imagen[i-1:i+2, j-1:j+2],
                            segunda_imagen[i-1:i+2, j-1:j+2],
                            tercera_imagen[i-1:i+2, j-1:j+2]]).astype('float32') / 255.
        gradient = calcular_Gradiente_Pixel_Central(pixel_cube)
        hessiana = calcular_Hessiana_Pixel_central(pixel_cube)
        extremo_actualizado = -lstsq(hessiana, gradient, rcond=None)[0]
        if abs(extremo_actualizado[0]) < 0.5 and abs(extremo_actualizado[1]) < 0.5 and abs(extremo_actualizado[2]) < 0.5:
            break
        j += int(round(extremo_actualizado[0]))
        i += int(round(extremo_actualizado[1]))
        indice_imagen += int(round(extremo_actualizado[2]))

        # Nos aseguramos  de que el nuevo cubo de píxeles se encuentre completamente dentro de la imagen
        if i < ancho_borde_imagen or i >= image_shape[0] - ancho_borde_imagen or j < ancho_borde_imagen or j >= image_shape[1] - ancho_borde_imagen or indice_imagen < 1 or indice_imagen > num_intervalos:
            extremo_esta_fuera_Imagen = True
            break
    if extremo_esta_fuera_Imagen:
        logger.debug('El extremo actualizado se movió fuera de la imagen antes de alcanzar la convergencia -> Salto...')
        return None
    if attempt_index >= num_attempts_until_convergence - 1:
        logger.debug('Se superó el número máximo de intentos sin alcanzar la convergencia para este extremo -> Salto...')
        return None
    ValorFuncion_Extrenmo_actualizado = pixel_cube[1, 1, 1] + 0.5 * dot(gradient, extremo_actualizado)
    if abs(ValorFuncion_Extrenmo_actualizado) * num_intervalos >= contrast_threshold:
        xy_hessian = hessiana[:2, :2]
        xy_hessian_traza = trace(xy_hessian)
        xy_hessian_determinante = det(xy_hessian)
        if xy_hessian_determinante > 0 and eigenvalue_ratio * (xy_hessian_traza ** 2) < ((eigenvalue_ratio + 1) ** 2) * xy_hessian_determinante:
            # Comprobación de contraste superada: construir y devolver el objeto Punto Clave
            keypoint = KeyPoint()
            keypoint.pt = ((j + extremo_actualizado[0]) * (2 ** indice_octava), (i + extremo_actualizado[1]) * (2 ** indice_octava))
            keypoint.octave = indice_octava + indice_imagen * (2 ** 8) + int(round((extremo_actualizado[2] + 0.5) * 255)) * (2 ** 16)

            #indice_octava + 1 porque la imagen de entrada se duplicó   Pesha PS PELOTUDO
            keypoint.size = sigma * (2 ** ((indice_imagen + extremo_actualizado[2]) / float32(num_intervalos))) * (2 ** (indice_octava + 1))
            keypoint.response = abs(ValorFuncion_Extrenmo_actualizado)
            return keypoint, indice_imagen
    return None
Example #3
0
def localizeExtremumViaQuadraticFit(i, j, image_index, octave_index, num_intervals, dog_images_in_octave, sigma, contrast_threshold, image_border_width, eigenvalue_ratio=10, num_attempts_until_convergence=5):
    """
    在scale-space中,迭代进行每个像素点的位置更新
    """
    logger.info('Localizing scale-space extrema...')
    extremum_is_outside_image = False
    image_shape = dog_images_in_octave[0].shape
    for attempt_index in range(num_attempts_until_convergence):
        first_image, second_image, third_image = dog_images_in_octave[image_index-1:image_index+2]
        pixel_cube = stack([first_image[i-1:i+2, j-1:j+2],
                            second_image[i-1:i+2, j-1:j+2],
                            third_image[i-1:i+2, j-1:j+2]]).astype('float32') / 255.
        gradient = computeGradientAtCenterPixel(pixel_cube)
        hessian = computeHessianAtCenterPixel(pixel_cube)
        extremum_update = -lstsq(hessian, gradient, rcond=None)[0]
        if abs(extremum_update[0]) < 0.5 and abs(extremum_update[1]) < 0.5 and abs(extremum_update[2]) < 0.5:
            break
        j += int(round(extremum_update[0]))
        i += int(round(extremum_update[1]))
        image_index += int(round(extremum_update[2]))

        if i < image_border_width or i >= image_shape[0] - image_border_width or j < image_border_width or j >= image_shape[1] - image_border_width or image_index < 1 or image_index > num_intervals:
            extremum_is_outside_image = True
            break
    functionValueAtUpdatedExtremum = pixel_cube[1, 1, 1] + 0.5 * dot(gradient, extremum_update)
    if abs(functionValueAtUpdatedExtremum) * num_intervals >= contrast_threshold:
        xy_hessian = hessian[:2, :2]
        xy_hessian_trace = trace(xy_hessian)
        xy_hessian_det = det(xy_hessian)
        if xy_hessian_det > 0 and eigenvalue_ratio * (xy_hessian_trace ** 2) < ((eigenvalue_ratio + 1) ** 2) * xy_hessian_det:
            # 设计Keypoints
            keypoint = KeyPoint()
            keypoint.pt = ((j + extremum_update[0]) * (2 ** octave_index), (i + extremum_update[1]) * (2 ** octave_index))
            keypoint.octave = octave_index + image_index * (2 ** 8) + int(round((extremum_update[2] + 0.5) * 255)) * (2 ** 16)
            keypoint.size = sigma * (2 ** ((image_index + extremum_update[2]) / float32(num_intervals))) * (2 ** (octave_index + 1))  # octave_index + 1 because the input image was doubled
            keypoint.response = abs(functionValueAtUpdatedExtremum)
            return keypoint, image_index
    return None
def localize_extremum_via_quadratic_fit(i,
                                        j,
                                        image_index,
                                        octave_index,
                                        num_intervals,
                                        dog_images_in_octave,
                                        sigma,
                                        contrast_threshold,
                                        image_border_width,
                                        eigenvalue_ratio=10,
                                        num_attempts_until_convergence=5):
    """
    利用泰勒展开对像素进行亚像素(子像素)精确定位。
    """
    extremum_is_outside_image = False
    image_shape = dog_images_in_octave[0].shape
    for attempt_index in range(num_attempts_until_convergence):
        # need to convert from uint8 to float32 to compute derivatives and need
        # to rescale pixel values to [0, 1] to apply Lowe's thresholds
        first_image, second_image, third_image = dog_images_in_octave[
            image_index - 1:image_index + 2]
        pixel_cube = stack([
            first_image[i - 1:i + 2, j - 1:j + 2],
            second_image[i - 1:i + 2, j - 1:j + 2], third_image[i - 1:i + 2,
                                                                j - 1:j + 2]
        ]).astype('float32') / 255.
        gradient = compute_gradient_at_center_pixel(pixel_cube)
        hessian = compute_hessian_at_center_pixel(pixel_cube)
        extremum_update = -lstsq(hessian, gradient, rcond=None)[0]
        if abs(extremum_update[0]) < 0.5 and abs(
                extremum_update[1]) < 0.5 and abs(extremum_update[2]) < 0.5:
            break
        j += int(round(extremum_update[0]))
        i += int(round(extremum_update[1]))
        image_index += int(round(extremum_update[2]))
        # make sure the new pixel_cube will lie entirely within the image
        if i < image_border_width or i >= image_shape[0] - image_border_width or j < image_border_width or j >= \
                image_shape[1] - image_border_width or image_index < 1 or image_index > num_intervals:
            extremum_is_outside_image = True
            break
    if extremum_is_outside_image:
        return None
    if attempt_index >= num_attempts_until_convergence - 1:
        return None
    functionValueAtUpdatedExtremum = pixel_cube[1, 1, 1] + 0.5 * dot(
        gradient, extremum_update)
    if abs(functionValueAtUpdatedExtremum) * \
            num_intervals >= contrast_threshold:
        xy_hessian = hessian[:2, :2]
        xy_hessian_trace = trace(xy_hessian)
        xy_hessian_det = det(xy_hessian)
        if xy_hessian_det > 0 and eigenvalue_ratio * (xy_hessian_trace**2) < (
            (eigenvalue_ratio + 1)**2) * xy_hessian_det:
            # Contrast check passed -- construct and return OpenCV KeyPoint
            # object
            keypoint = KeyPoint()
            keypoint.pt = ((j + extremum_update[0]) * (2**octave_index),
                           (i + extremum_update[1]) * (2**octave_index))
            keypoint.octave = octave_index + image_index * \
                (2 ** 8) + int(round((extremum_update[2] + 0.5) * 255)) * (2 ** 16)
            keypoint.size = sigma * (2**(
                (image_index + extremum_update[2]) / float32(num_intervals)
            )) * (2**(octave_index + 1)
                  )  # octave_index + 1 because the input image was doubled
            keypoint.response = abs(functionValueAtUpdatedExtremum)
            return keypoint, image_index
    return None
Example #5
0
def DetecteKeyPoint(i,
                    j,
                    ImgIndex,
                    OctaveIndex,
                    NumOfIntervals,
                    DoGImgInOctave,
                    Sigma0,
                    ContrastThreshold,
                    ImgBorderWidth,
                    EigenvalueRatio=10,
                    NumOfAttempts=5):
    """
    探测极值点是否是关键点
    @param i: 极值点坐标i
    @param j: 极值点坐标j
    @param ImgIndex: 图片的层数s
    @param OctaveIndex: 图片所在组数O
    @param NumOfIntervals: SIFT里的大S
    @param DoGImgInOctave: 差分高斯金字塔的一组图片,探测时可能移动层数
    @param Sigma0: SIFT里的Sigma0
    @param ContrastThreshold: SIFT里用于消除噪音点
    @param ImgBorderWidth: 抛弃的图片边缘的长度,便于计算,网上说一般为5
    @param EigenvalueRatio: 消除边缘响应的阈值里的r
    @param NumOfAttempts: 关键点的探测次数
    @return: 如果探测到关键点就返回KeyPoint,探测不到就返回None
    """
    ImgShape = (len(DoGImgInOctave[0]), len(DoGImgInOctave[0][0]))
    for AttemptIndex in range(NumOfAttempts):
        FirstImg, SecondImg, ThirdImg = DoGImgInOctave[ImgIndex - 1:ImgIndex +
                                                       2]
        DoGArray = np.array([
            FirstImg[i - 1:i + 2, j - 1:j + 2],
            SecondImg[i - 1:i + 2, j - 1:j + 2], ThirdImg[i - 1:i + 2,
                                                          j - 1:j + 2]
        ]).astype(np.float) / 255  # Lowe要求归一化,为了跟阈值比较,消除噪音点

        Gradient = ComputeGradientAtCenterPixel(DoGArray)
        Hessian = ComputeHessianAtCenterPixel(DoGArray)
        CoordinatesUpdateValueOfKeyPoint = -1 * np.dot(
            ComputeInv3(Hessian),
            np.array([Gradient]).reshape((3, 1)))
        CoordinatesUpdateValueOfKeyPoint.reshape(-1)  # 偏移量

        if abs(CoordinatesUpdateValueOfKeyPoint[0]) < 0.5 and abs(
                CoordinatesUpdateValueOfKeyPoint[1]) < 0.5 and abs(
                    CoordinatesUpdateValueOfKeyPoint[2]) < 0.5:
            break
        j += int(np.round(CoordinatesUpdateValueOfKeyPoint[0]))
        i += int(np.round(CoordinatesUpdateValueOfKeyPoint[1]))
        ImgIndex += int(np.round(CoordinatesUpdateValueOfKeyPoint[2]))
        if i < ImgBorderWidth or i >= ImgShape[
                0] - ImgBorderWidth or j < ImgBorderWidth or j >= ImgShape[
                    1] - ImgBorderWidth or ImgIndex < 1 or ImgIndex > NumOfIntervals:
            return None
    if AttemptIndex >= NumOfAttempts - 1:
        return None

    NewKeyPointValue = DoGArray[1, 1, 1] + 0.5 * np.dot(
        Gradient, CoordinatesUpdateValueOfKeyPoint)

    if abs(NewKeyPointValue) * NumOfIntervals >= ContrastThreshold:
        xy_Hessian = Hessian[:2, :2]
        Tr = xy_Hessian[0, 0] + xy_Hessian[1, 1]
        Det = xy_Hessian[0, 0] * xy_Hessian[1, 1] - (xy_Hessian[0, 1]**2)
        if Det > 0 and EigenvalueRatio * (Tr**2) < (
            (EigenvalueRatio + 1)**2) * Det:
            Keypoint = KeyPoint()
            Keypoint.pt = ((j + CoordinatesUpdateValueOfKeyPoint[0]) *
                           (2**OctaveIndex),
                           (i + CoordinatesUpdateValueOfKeyPoint[1]) *
                           (2**OctaveIndex))
            # Keypoint.pt 要以初始图片大小为准,这里的初始图片是扩大二倍后的图片
            Keypoint.octave = OctaveIndex + ImgIndex * (2**8) + np.int(
                np.round(
                    (CoordinatesUpdateValueOfKeyPoint[2]) * 255)) * (2**16)
            # Keypoint.octave 0-7位保存Octave,8-15位保存ImgIndex, 16-23位保存sigma,防止在后面用Sigma返过来求s时,s直接取整会出错
            Keypoint.size = Sigma0 * (2**(
                (ImgIndex + CoordinatesUpdateValueOfKeyPoint[2]) /
                np.float32(NumOfIntervals))) * (2**(OctaveIndex + 1))
            # Keypoint.size 这里的初始图片是扩大二倍后的图片,各个Sigma要多乘一个2, 所以OctaveIndex + 1
            Keypoint.response = abs(NewKeyPointValue)
            # 为什么不直接从初始图片开始算?SIFT关键点主要在-1组,具体在报告中介绍

            return Keypoint, int(ImgIndex +
                                 CoordinatesUpdateValueOfKeyPoint[2])
    return None
Example #6
0
File: SIFT.py Project: albgp/SIFT
    def localize(self, x, y, top, center, bottom, index_img, index_octv, octv):
        outside_image = False
        img_shape = center.shape
        num_intervals = len(octv) + 1
        for attempt in range(self.params["convergence_attempts"] + 1):
            cube = stack([
                bottom[x - 1:x + 2, y - 1:y + 2],
                center[x - 1:x + 2, y - 1:y + 2], top[x - 1:x + 2, y - 1:y + 2]
            ]).astype('float32') / 255

            update = -lstsq(LocateKeypoints.getHessian(cube),
                            LocateKeypoints.getGrad(cube),
                            rcond=None)[0]

            if all(update < 0.5):
                break

            x += int(round(update[0]))
            y += int(round(update[1]))
            index_octv += int(round(update[2]))

            image_border_width = self.params["image_border_width"]

            if (x < image_border_width
                    or x >= img_shape[0] - image_border_width
                    or y < image_border_width
                    or y >= img_shape[1] - image_border_width or index_img < 1
                    or index_img >= num_intervals - 1):
                outside_image = True
                break

            top, center, bottom = octv[index_img +
                                       1], octv[index_img], octv[index_img - 1]

        if outside_image:
            logger.debug(
                f'Updated extremum {x},{y} moved outside of image before reaching convergence. Skipping...'
            )
            return None

        if attempt == self.params["convergence_attempts"]:
            logger.debug(f'The extremum {x},{y} did not converge. Skipping...')
            return None

        functionValueAtUpdatedExtremum = cube[1, 1, 1] + 0.5 * dot(
            LocateKeypoints.getGrad(cube), update)
        eigenvalue_ratio = self.params["eigenvalue_ratio"]

        if abs(functionValueAtUpdatedExtremum
               ) * num_intervals >= self.params["contrast_threshold"]:
            xy_hessian = LocateKeypoints.getHessian(cube)[:2, :2]
            xy_hessian_trace = trace(xy_hessian)
            xy_hessian_det = det(xy_hessian)
            if xy_hessian_det > 0 and eigenvalue_ratio * (
                    xy_hessian_trace**2) < (
                        (eigenvalue_ratio + 1)**2) * xy_hessian_det:
                # Contrast check passed -- construct and return OpenCV KeyPoint object
                keypoint = KeyPoint()
                keypoint.pt = ((y + update[0]) * (2**index_octv),
                               (x + update[1]) * (2**index_octv))
                keypoint.octave = index_octv + index_img * (2**8) + int(
                    round((update[2] + 0.5) * 255)) * (2**16)
                keypoint.size = self.params["sigma"] * (2**(
                    (index_img + update[2]) / float32(num_intervals))) * (
                        2**(index_octv + 1)
                    )  # octave_index + 1 because the input image was doubled
                keypoint.response = abs(functionValueAtUpdatedExtremum)
                return keypoint, index_img, index_octv
        return None