Local features (detector and descriptor together)#
- class kornia.feature.LocalFeature(detector, descriptor, scaling_coef=1.0)[source]#
nn.Module, which combines local feature detector and descriptor.
- Parameters:
detector (
Module) – the detection module.descriptor (
LAFDescriptor) – the descriptor module.scaling_coef (
float, optional) – multiplier for change default detector scale (e.g. it is too small for KeyNet by default) Default:1.0
- forward(img, mask=None)[source]#
Run forward.
- Parameters:
- Return type:
- Returns:
Detected local affine frames with shape \((B,N,2,3)\).
Response function values for corresponding lafs with shape \((B,N)\).
Local descriptors of shape \((B,N,D)\) where \(D\) is descriptor size.
The shape is fixed at the detector’s
num_features. When an image yields fewer detections, the remaining slots carry a zero response and a zero LAF, and their descriptor is that of a patch sampled at the origin – one and the same vector for every such slot.LocalFeatureMatcherdrops them before matching; a hand-rolled pipeline must do the same before any other matcher, includingmatch_nn(),match_mnn(),match_fginn(),match_adalam()andLightGlueMatcher, since identical descriptors match each other at zero distance and a mutual test does not reject a pair of them:valid = lafs.ne(0).any(-1).any(-1) # (B, N); the zero LAF marks a padded slot descs, lafs = descs[0][valid[0]], lafs[:, valid[0]]
Test the LAF, not the response: a signed response can legitimately peak at exactly zero. Only the ratio tests in
match_snn()andmatch_smnn()reject padded slots on their own, because the second-nearest padded descriptor is at the same zero distance.
- class kornia.feature.SOLD2_detector(pretrained=True, config=None)[source]#
nn.Module, which detects line segments in an image.
This is based on the original code from the paper “SOLD²: Self-supervised Occlusion-aware Line Detector and Descriptor”. See [PautratLinL+21] for more details.
- Parameters:
config (DetectorCfg) – Configuration object containing all parameters. None will load the default parameters, which are tuned for images in the range 400~800 px. Using a dataclass ensures type safety and clearer parameter management. Default:
Nonepretrained (bool) – If True, download and set pretrained weights to the model. Default:
True
- Returns:
The raw junction and line heatmaps, as well as the list of detected line segments (ij coordinates convention).
Example
>>> img = torch.rand(1, 1, 128, 128) >>> sold2_detector = SOLD2_detector(pretrained=False) >>> line_segments = sold2_detector(img)["line_segments"]
- forward(img)[source]#
Run forward.
- Parameters:
img (
Tensor) – batched images with shape \((B, 1, H, W)\).- Returns:
list of N line segments in each of the B images \(List[(N, 2, 2)]\). junction_heatmap: raw junction heatmap of shape \((B, H, W)\). line_heatmap: raw line heatmap of shape \((B, H, W)\).
- Return type:
line_segments
- class kornia.feature.ALIKED(model_name='aliked-n16', max_num_keypoints=-1, detection_threshold=0.2, nms_radius=2)[source]#
ALIKED local feature detector and descriptor.
ALIKED (Adaptive Local Image KEypoint Detection) combines a multi-scale ResNet backbone with deformable descriptor sampling (SDDH) and a differentiable keypoint detector (DKD).
See [ZWC+23] for details.
- Parameters:
model_name (
str, optional) – backbone configuration, one of'aliked-t16','aliked-n16','aliked-n16rot','aliked-n32'. Default:"aliked-n16"max_num_keypoints (
int, optional) – maximum number of keypoints to detect.-1means no limit (threshold-based mode). Default:-1detection_threshold (
float, optional) – minimum detection score in threshold mode. Default:0.2nms_radius (
int, optional) – NMS radius (kernel size= 2 * nms_radius + 1). Default:2
Example
>>> aliked = ALIKED.from_pretrained('aliked-n16') >>> images = torch.rand(1, 3, 256, 256) >>> features = aliked(images)
- forward(images, image_size=None)[source]#
Detect and describe local features in a batch of images.
- Parameters:
- Return type:
- Returns:
A list of
ALIKEDFeaturesof length B, one per image. Keypoints are in pixel coordinates[x, y].
- forward_laf(img, mask=None, compute_affine=True)[source]#
Detect and describe local features, returning results in kornia LAF format.
Local Affine Frames are estimated from the soft-argmax weight covariance computed inside
DKD: the 2x2 affine matrix captures the dominant orientation and scale of each detected keypoint without any additional network parameters.All per-image tensors are zero-padded along the keypoint dimension so that the outputs are proper batched tensors.
- Parameters:
img (
Tensor) – image to extract features with shape \((B,C,H,W)\).mask (
Optional[Tensor], optional) – optional spatial mask(B, 1, H, W)with values in[0, 1]; the score map is multiplied by this mask before keypoint detection so that features are suppressed in masked regions. Default:Nonecompute_affine (
bool, optional) – ifTrue(default), estimate the 2x2 affine shape of each LAF usingtorch.linalg.eighon the soft-argmax covariance. Set toFalseto skip the eigendecomposition and return identity affines, which is faster and avoids the linalg call entirely (useful when only keypoint positions are needed). Default:True
- Return type:
- Returns:
Detected local affine frames with shape \((B,N,2,3)\).
Response function values for corresponding LAFs with shape \((B,N,1)\).
Local descriptors of shape \((B,N,D)\).
- classmethod from_pretrained(model_name='aliked-n16', max_num_keypoints=-1, detection_threshold=0.2, nms_radius=2, device=None)[source]#
Load a pretrained ALIKED model from the official checkpoint repository.
- Parameters:
model_name (
str, optional) – one of'aliked-t16','aliked-n16','aliked-n16rot','aliked-n32'. Default:"aliked-n16"max_num_keypoints (
int, optional) – passed toALIKEDconstructor. Default:-1detection_threshold (
float, optional) – passed toALIKEDconstructor. Default:0.2nms_radius (
int, optional) – passed toALIKEDconstructor. Default:2device (
Optional[device], optional) – target device; defaults to CPU. Default:None
- Return type:
- Returns:
Pretrained
ALIKEDin eval mode.
- class kornia.feature.ALIKEDFeatures(keypoints, descriptors, keypoint_scores)[source]#
Keypoints, descriptors and scores detected by ALIKED for a single image.
Since ALIKED detects a varying number of keypoints per image,
ALIKEDFeaturesis not batched.- Parameters:
- class kornia.feature.DeDoDe(detector_model='L', descriptor_model='G', amp_dtype=torch.float16)[source]#
nn.Module which detects and/or describes local features in an image using the DeDode method.
See [EBWF24] for details.
Note
DeDode takes ImageNet normalized images as input (not in range [0, 1]).
- Parameters:
detector_model (
Literal['L'], optional) – The detector model kind. Available options are: L. Default:"L"descriptor_model (
Literal['G','B'], optional) – The descriptor model kind. Available options are: G or B Default:"G"amp_dtype (
dtype, optional) – The automatic mixed precision desired. Default:torch.float16
Example
>>> dedode = DeDoDe.from_pretrained(detector_weights="L-C4-v2", descriptor_weights="B-upright") >>> images = torch.randn(1, 3, 256, 256) >>> keypoints, scores = dedode.detect(images) >>> descriptions = dedode.describe(images, keypoints = keypoints) >>> keypoints, scores, features = dedode(images) # alternatively do both
- describe(images, keypoints=None, apply_imagenet_normalization=True, pad_if_not_divisible=True, crop_h=None, crop_w=None)[source]#
Describe keypoints in the input images. If keypoints are not provided, returns the dense descriptors.
Note
This method unconditionally sets the model to eval mode via
self.train(False)so that BatchNorm and Dropout behave deterministically. This is intentional: the descriptor is only used at inference time and its statistics must be frozen.- Parameters:
images (
Tensor) – A torch.Tensor of shape \((B, 3, H, W)\) containing the input images.keypoints (
Optional[Tensor], optional) – An optional torch.Tensor of shape \((B, N, 2)\) containing the detected keypoints. Default:Noneapply_imagenet_normalization (
bool, optional) – Whether to apply ImageNet normalization to the input images. Default:Truepad_if_not_divisible (
bool, optional) – Zero-pad the image so H and W are divisible by 14. Required when using theGdescriptor backed by DINOv2 (patch size 14). Ignored forB. Default:Truecrop_h (
Optional[int], optional) – The height of the crop to be used for description. If None, the full image is used. Default:Nonecrop_w (
Optional[int], optional) – The width of the crop to be used for description. If None, the full image is used. Default:None
- Returns:
- A torch.Tensor of shape \((B, N, DIM)\) containing the descriptions
of the detected keypoints. If the dense descriptors are requested, the shape is \((B, DIM, H, W)\).
- Return type:
descriptions
- detect(images, n=10000, apply_imagenet_normalization=True, pad_if_not_divisible=True, crop_h=None, crop_w=None)[source]#
Detect keypoints in the input images.
Note
This method unconditionally sets the model to eval mode via
self.train(False)so that BatchNorm and Dropout behave deterministically. This is intentional: the detector is only used at inference time and its statistics must be frozen.- Parameters:
images (
Tensor) – A torch.Tensor of shape \((B, 3, H, W)\) containing the input images.n (
Optional[int], optional) – The number of keypoints to detect. Default:10000apply_imagenet_normalization (
bool, optional) – Whether to apply ImageNet normalization to the input images. Default:Truepad_if_not_divisible (
bool, optional) – F.pad image shape if not evenly divisible. Default:Truecrop_h (
Optional[int], optional) – The height of the crop to be used for detection. If None, the full image is used. Default:Nonecrop_w (
Optional[int], optional) – The width of the crop to be used for detection. If None, the full image is used. Default:None
- Returns:
A torch.Tensor of shape \((B, N, 2)\) containing the detected keypoints, normalized to the range \([-1, 1]\). scores: A torch.Tensor of shape \((B, N)\) containing the scores of the detected keypoints.
- Return type:
- forward(images, n=10_000, apply_imagenet_normalization=True, pad_if_not_divisible=True)[source]#
Detect and describe keypoints in the input images.
- Parameters:
images (
Tensor) – A torch.Tensor of shape \((B, 3, H, W)\) containing the ImageNet-Normalized input images.n (
Optional[int], optional) – The number of keypoints to detect. Default:10_000apply_imagenet_normalization (
bool, optional) – Whether to apply ImageNet normalization to the input images. Default:Truepad_if_not_divisible (
bool, optional) – F.pad image shape if not evenly divisible. Default:True
- Returns:
- A torch.Tensor of shape \((B, N, 2)\) containing the detected keypoints in the image range,
unlike .detect() function.
scores: A torch.Tensor of shape \((B, N)\) containing the scores of the detected keypoints.
- descriptions: A torch.Tensor of shape \((B, N, DIM)\) containing the descriptions
of the detected keypoints. DIM is 256 for B and 512 for G.
- Return type:
- classmethod from_pretrained(detector_weights='L-C4-v2', descriptor_weights='G-upright', amp_dtype=torch.float16)[source]#
Load a pretrained model.
- Parameters:
detector_weights (
str, optional) – The weights to load for the detector. One of ‘L-upright’ (original paper, https://arxiv.org/abs/2308.08479), ‘L-C4’, ‘L-SO2’ (from steerers, better for rotations, https://arxiv.org/abs/2312.02152), ‘L-C4-v2’ (from dedode v2, better at rotations, less clustering, https://arxiv.org/abs/2404.08928). Default is ‘L-C4-v2’. Default:"L-C4-v2"descriptor_weights (
str, optional) – The weights to load for the descriptor. One of ‘B-upright’,’G-upright’ (original paper, https://arxiv.org/abs/2308.08479), ‘B-C4’, ‘B-SO2’, ‘G-C4’, ‘G-SO2’ (from steerers, better for rotations, https://arxiv.org/abs/2312.02152). Default is ‘G-upright’. Default:"G-upright"amp_dtype (
dtype, optional) – the dtype to use for the model. One of torch.float16 or torch.float32. Default:torch.float16torch.float16 (Default is)
MPS (suitable for CUDA. Use torch.float32 for CPU or)
- Return type:
- Returns:
The pretrained model.
- class kornia.feature.DISK(desc_dim=128, unet=None)[source]#
nn.Module which detects and described local features in an image using the DISK method.
See [TFT20] for details.
- Parameters:
desc_dim (
int, optional) – The dimension of the descriptor. Default:128unet (
Module|None, optional) – The U-Net to use. If None, a default U-Net is used. Kornia doesn’t provide the training code for DISK so this is only useful when using a custom checkpoint trained using the code released with the paper. The unet should take as input a torch.Tensor of shape \((B, C, H, W)\) and output a torch.Tensor of shape \((B, \mathrm{desc\_dim} + 1, H, W)\). Default:None
Example
>>> disk = DISK.from_pretrained('depth') >>> images = torch.rand(1, 3, 256, 256) >>> features = disk(images)
- forward(images, n=None, window_size=5, score_threshold=0.0, pad_if_not_divisible=False)[source]#
Detect features in an image, returning keypoint locations, descriptors and detection scores.
- Parameters:
images (
Tensor) – The image to detect features in. Shape \((B, 3, H, W)\).n (
int|None, optional) – The maximum number of keypoints to detect. If None, all keypoints are returned. Default:Nonewindow_size (
int, optional) – The size of the non-maxima suppression window used to filter detections. Default:5score_threshold (
float, optional) – The minimum score a detection must have to be returned. SeeDISKFeaturesfor details. Default:0.0pad_if_not_divisible (
bool, optional) – if True, the non-16 divisible input is zero-padded to the closest 16-multiply Default:False
- Return type:
- Returns:
A list of length \(B\) containing the detected features.
- classmethod from_pretrained(checkpoint='depth', device=None)[source]#
Load a pretrained model.
Depth model was trained using depth map supervision and is slightly more precise but biased to detect keypoints only where SfM depth is available. Epipolar model was trained using epipolar geometry supervision and is less precise but detects keypoints everywhere where they are matchable. The difference is especially pronounced on thin structures and on edges of objects.
- class kornia.feature.XFeat(top_k=4096, detection_threshold=0.05)[source]#
XFeat sparse and semi-dense local feature extractor and matcher.
Wraps
XFeatModelwith NMS keypoint detection, descriptor interpolation, and mutual nearest-neighbour matching helpers.- Reference:
“XFeat: Accelerated Features for Lightweight Image Matching”, CVPR 2024. https://www.verlab.dcc.ufmg.br/descriptors/xfeat_cvpr24/
- Parameters:
Example
>>> model = XFeat() >>> img = torch.rand(1, 3, 256, 256) >>> out = model.detectAndCompute(img) >>> out[0]['keypoints'].shape torch.Size([..., 2])
- detectAndCompute(x, top_k=None, detection_threshold=None)[source]#
Detect sparse keypoints and compute descriptors.
- Parameters:
- Returns:
'keypoints': \((N, 2)\) keypoints in (x, y) pixel coordinates.'scores': \((N,)\) reliability scores.'descriptors': \((N, 64)\) L2-normalised descriptors.
- Return type:
List of length
B. Each element is a dict with
- detectAndComputeDense(x, top_k=None, multiscale=True)[source]#
Detect keypoints and compute dense coarse descriptors.
- Parameters:
- Returns:
'keypoints': \((B, K, 2)\) coarse keypoints.'descriptors': \((B, K, 64)\) coarse descriptors.'scales': \((B, K)\) extraction scale per keypoint.
- Return type:
Dict with
- forward(*input)[source]#
Define the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the
Moduleinstance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.- Return type:
- classmethod from_pretrained(top_k=4096, detection_threshold=0.05)[source]#
Instantiate XFeat with pretrained weights downloaded from the official release.
- match_xfeat(img1, img2, top_k=None, min_cossim=-1)[source]#
Detect, describe and mutually match keypoints from two images.
- Parameters:
img1 (
Tensor) – first image tensor of shape \((1, C, H, W)\).img2 (
Tensor) – second image tensor of shape \((1, C, H, W)\).top_k (
Optional[int], optional) – number of top keypoints to use. Default:Nonemin_cossim (
float, optional) – minimum cosine similarity threshold. Use-1to disable. Default:-1
- Return type:
- Returns:
Tuple
(mkpts0, mkpts1)of matched keypoints, each \((N, 2)\).
- class kornia.feature.XFeatModel[source]#
XFeat backbone: CNN feature extractor, keypoint and reliability heads.
Implements the architecture from “XFeat: Accelerated Features for Lightweight Image Matching”, CVPR 2024.
Input: float image tensor \((B, C, H, W)\) (grayscale or RGB, any channel count). Output:
feats: dense descriptors \((B, 64, H/8, W/8)\).keypoints: keypoint logits \((B, 65, H/8, W/8)\).heatmap: reliability map \((B, 1, H/8, W/8)\).
Note
Image normalisation (
InstanceNorm2d) is wrapped intorch.no_grad()following the original design; backpropagating through it is not supported.
- class kornia.feature.InterpolateSparse2d(mode='bicubic', align_corners=False)[source]#
Bilinearly or bicubically sample a dense feature map at sparse 2-D positions.
- Parameters:
mode (
str, optional) – interpolation mode fortorch.nn.functional.grid_sample(). Default:'bicubic'.align_corners (
bool, optional) – passed togrid_sample. Default:False.
- Shape:
Input
x: \((B, C, H, W)\).Input
pos: \((B, N, 2)\) integer or float (x, y) coordinates.Output: \((B, N, C)\).
- class kornia.feature.DISKFeatures(keypoints, descriptors, detection_scores)[source]#
A data structure holding DISK keypoints, descriptors and detection scores for an image.
Since DISK detects a varying number of keypoints per image, DISKFeatures is not batched.
- Parameters:
keypoints (
Tensor) – torch.Tensor of shape \((N, 2)\), where \(N\) is the number of keypoints.descriptors (
Tensor) – torch.Tensor of shape \((N, D)\), where \(D\) is the descriptor dimension.detection_scores (
Tensor) – torch.Tensor of shape \((N,)\) where the detection score can be interpreted as the log-probability of keeping a keypoint after it has been proposed (see the paper section Method → Feature distribution for details).
- class kornia.feature.SIFTFeature(num_features=8000, upright=False, rootsift=True, device=None, config=None, compile_model=False, score_threshold=0.0)[source]#
Convenience module, which implements DoG detector + (Root)SIFT descriptor.
Using kornia.feature.MultiResolutionDetector without blur pyramid Still not as good as OpenCV/VLFeat because of kornia/kornia#884, but we are working on it
- forward(img, mask=None)[source]#
Run forward.
- Parameters:
- Return type:
- Returns:
Detected local affine frames with shape \((B,N,2,3)\).
Response function values for corresponding lafs with shape \((B,N)\).
Local descriptors of shape \((B,N,D)\) where \(D\) is descriptor size.
The shape is fixed at the detector’s
num_features. When an image yields fewer detections, the remaining slots carry a zero response and a zero LAF, and their descriptor is that of a patch sampled at the origin – one and the same vector for every such slot.LocalFeatureMatcherdrops them before matching; a hand-rolled pipeline must do the same before any other matcher, includingmatch_nn(),match_mnn(),match_fginn(),match_adalam()andLightGlueMatcher, since identical descriptors match each other at zero distance and a mutual test does not reject a pair of them:valid = lafs.ne(0).any(-1).any(-1) # (B, N); the zero LAF marks a padded slot descs, lafs = descs[0][valid[0]], lafs[:, valid[0]]
Test the LAF, not the response: a signed response can legitimately peak at exactly zero. Only the ratio tests in
match_snn()andmatch_smnn()reject padded slots on their own, because the second-nearest padded descriptor is at the same zero distance.
- class kornia.feature.SIFTFeatureScaleSpace(num_features=8000, upright=False, rootsift=True, device=None, compile_modules=False)[source]#
Convenience module, which implements DoG detector + (Root)SIFT descriptor.
Using kornia.feature.ScaleSpaceDetector with blur pyramid.
Still not as good as OpenCV/VLFeat because of kornia/kornia#884, but we are working on it
- forward(img, mask=None)[source]#
Run forward.
- Parameters:
- Return type:
- Returns:
Detected local affine frames with shape \((B,N,2,3)\).
Response function values for corresponding lafs with shape \((B,N)\).
Local descriptors of shape \((B,N,D)\) where \(D\) is descriptor size.
The shape is fixed at the detector’s
num_features. When an image yields fewer detections, the remaining slots carry a zero response and a zero LAF, and their descriptor is that of a patch sampled at the origin – one and the same vector for every such slot.LocalFeatureMatcherdrops them before matching; a hand-rolled pipeline must do the same before any other matcher, includingmatch_nn(),match_mnn(),match_fginn(),match_adalam()andLightGlueMatcher, since identical descriptors match each other at zero distance and a mutual test does not reject a pair of them:valid = lafs.ne(0).any(-1).any(-1) # (B, N); the zero LAF marks a padded slot descs, lafs = descs[0][valid[0]], lafs[:, valid[0]]
Test the LAF, not the response: a signed response can legitimately peak at exactly zero. Only the ratio tests in
match_snn()andmatch_smnn()reject padded slots on their own, because the second-nearest padded descriptor is at the same zero distance.
- class kornia.feature.GFTTAffNetHardNet(num_features=8000, upright=False, device=None, compile_modules=False)[source]#
Convenience module, which implements GFTT detector + AffNet-HardNet descriptor.
- forward(img, mask=None)[source]#
Run forward.
- Parameters:
- Return type:
- Returns:
Detected local affine frames with shape \((B,N,2,3)\).
Response function values for corresponding lafs with shape \((B,N)\).
Local descriptors of shape \((B,N,D)\) where \(D\) is descriptor size.
The shape is fixed at the detector’s
num_features. When an image yields fewer detections, the remaining slots carry a zero response and a zero LAF, and their descriptor is that of a patch sampled at the origin – one and the same vector for every such slot.LocalFeatureMatcherdrops them before matching; a hand-rolled pipeline must do the same before any other matcher, includingmatch_nn(),match_mnn(),match_fginn(),match_adalam()andLightGlueMatcher, since identical descriptors match each other at zero distance and a mutual test does not reject a pair of them:valid = lafs.ne(0).any(-1).any(-1) # (B, N); the zero LAF marks a padded slot descs, lafs = descs[0][valid[0]], lafs[:, valid[0]]
Test the LAF, not the response: a signed response can legitimately peak at exactly zero. Only the ratio tests in
match_snn()andmatch_smnn()reject padded slots on their own, because the second-nearest padded descriptor is at the same zero distance.
- class kornia.feature.HesAffNetHardNet(num_features=2048, upright=False, device=None, compile_modules=False)[source]#
Convenience module, which implements Hessian detector + AffNet-HardNet descriptor.
- forward(img, mask=None)[source]#
Run forward.
- Parameters:
- Return type:
- Returns:
Detected local affine frames with shape \((B,N,2,3)\).
Response function values for corresponding lafs with shape \((B,N)\).
Local descriptors of shape \((B,N,D)\) where \(D\) is descriptor size.
The shape is fixed at the detector’s
num_features. When an image yields fewer detections, the remaining slots carry a zero response and a zero LAF, and their descriptor is that of a patch sampled at the origin – one and the same vector for every such slot.LocalFeatureMatcherdrops them before matching; a hand-rolled pipeline must do the same before any other matcher, includingmatch_nn(),match_mnn(),match_fginn(),match_adalam()andLightGlueMatcher, since identical descriptors match each other at zero distance and a mutual test does not reject a pair of them:valid = lafs.ne(0).any(-1).any(-1) # (B, N); the zero LAF marks a padded slot descs, lafs = descs[0][valid[0]], lafs[:, valid[0]]
Test the LAF, not the response: a signed response can legitimately peak at exactly zero. Only the ratio tests in
match_snn()andmatch_smnn()reject padded slots on their own, because the second-nearest padded descriptor is at the same zero distance.
- class kornia.feature.KeyNetAffNetHardNet(num_features=8000, upright=False, device=None, scale_laf=1.0, compile_model=False, score_threshold=0.0)[source]#
Convenience module, which implements KeyNet detector + AffNet + HardNet descriptor.
- forward(img, mask=None)[source]#
Run forward.
- Parameters:
- Return type:
- Returns:
Detected local affine frames with shape \((B,N,2,3)\).
Response function values for corresponding lafs with shape \((B,N)\).
Local descriptors of shape \((B,N,D)\) where \(D\) is descriptor size.
The shape is fixed at the detector’s
num_features. When an image yields fewer detections, the remaining slots carry a zero response and a zero LAF, and their descriptor is that of a patch sampled at the origin – one and the same vector for every such slot.LocalFeatureMatcherdrops them before matching; a hand-rolled pipeline must do the same before any other matcher, includingmatch_nn(),match_mnn(),match_fginn(),match_adalam()andLightGlueMatcher, since identical descriptors match each other at zero distance and a mutual test does not reject a pair of them:valid = lafs.ne(0).any(-1).any(-1) # (B, N); the zero LAF marks a padded slot descs, lafs = descs[0][valid[0]], lafs[:, valid[0]]
Test the LAF, not the response: a signed response can legitimately peak at exactly zero. Only the ratio tests in
match_snn()andmatch_smnn()reject padded slots on their own, because the second-nearest padded descriptor is at the same zero distance.
- class kornia.feature.KeyNetHardNet(num_features=8000, upright=False, device=None, scale_laf=1.0, compile_model=False, score_threshold=0.0)[source]#
Convenience module, which implements KeyNet detector + HardNet descriptor.
- forward(img, mask=None)[source]#
Run forward.
- Parameters:
- Return type:
- Returns:
Detected local affine frames with shape \((B,N,2,3)\).
Response function values for corresponding lafs with shape \((B,N)\).
Local descriptors of shape \((B,N,D)\) where \(D\) is descriptor size.
The shape is fixed at the detector’s
num_features. When an image yields fewer detections, the remaining slots carry a zero response and a zero LAF, and their descriptor is that of a patch sampled at the origin – one and the same vector for every such slot.LocalFeatureMatcherdrops them before matching; a hand-rolled pipeline must do the same before any other matcher, includingmatch_nn(),match_mnn(),match_fginn(),match_adalam()andLightGlueMatcher, since identical descriptors match each other at zero distance and a mutual test does not reject a pair of them:valid = lafs.ne(0).any(-1).any(-1) # (B, N); the zero LAF marks a padded slot descs, lafs = descs[0][valid[0]], lafs[:, valid[0]]
Test the LAF, not the response: a signed response can legitimately peak at exactly zero. Only the ratio tests in
match_snn()andmatch_smnn()reject padded slots on their own, because the second-nearest padded descriptor is at the same zero distance.