class_docstr: Class matching two sets of line segments with the Needleman-Wunsch algorithm.
  
  TODO: move it later in kornia.feature.matching
class_docstr_tok: ["Class","matching","two","sets","of","line","segments","with","the","Needleman-Wunsch","algorithm",".","TODO",":","move","it","later","in","kornia.feature.matching"]
docstr: Use the scores to keep the top k best lines, compute the Needleman- Wunsch algorithm on each candidate
  pairs, and keep the highest score.
  
  Inputs:
      scores: a (N, M, n, n) Tensor containing the pairwise scores
              of the elements to match.
  Outputs:
      matches: a (N) Tensor containing the indices of the best match
docstr_tok: ["Use","the","scores","to","keep","the","top","k","best","lines",",","compute","the","Needleman-","Wunsch","algorithm","on","each","candidate","pairs",",","and","keep","the","highest","score",".","Inputs",":","scores",":","a","(","N",",","M",",","n",",","n",")","Tensor","containing","the","pairwise","scores","of","the","elements","to","match",".","Outputs",":","matches",":","a","(","N",")","Tensor","containing","the","indices","of","the","best","match"]
code: def filter_and_match_lines(self, scores: Tensor) -> Tensor:
      """Use the scores to keep the top k best lines, compute the Needleman- Wunsch algorithm on each candidate
      pairs, and keep the highest score.
  
      Inputs:
          scores: a (N, M, n, n) Tensor containing the pairwise scores
                  of the elements to match.
      Outputs:
          matches: a (N) Tensor containing the indices of the best match
      """
      KORNIA_CHECK_SHAPE(scores, ["M", "N", "n", "n"])
  
      # Pre-filter the pairs and keep the top k best candidate lines
      line_scores1 = scores.max(3)[0]
      valid_scores1 = line_scores1 != -1
      line_scores1 = (line_scores1 * valid_scores1).sum(
          2
      ) / valid_scores1.sum(2)
      line_scores2 = scores.max(2)[0]
      valid_scores2 = line_scores2 != -1
      line_scores2 = (line_scores2 * valid_scores2).sum(
          2
      ) / valid_scores2.sum(2)
      line_scores = (line_scores1 + line_scores2) / 2
      topk_lines = torch.argsort(line_scores, dim=1)[
          :, -self.top_k_candidates :
      ]
      # topk_lines.shape = (n_lines1, top_k_candidates)
  
      top_scores = torch.take_along_dim(
          scores, topk_lines[:, :, None, None], dim=1
      )
  
      # Consider the reversed line segments as well
      top_scores = concatenate(
          [top_scores, torch.flip(top_scores, dims=[-1])], 1
      )
  
      # Compute the line distance matrix with Needleman-Wunsch algo and
      # retrieve the closest line neighbor
      n_lines1, top2k, n, m = top_scores.shape
      top_scores = top_scores.reshape((n_lines1 * top2k, n, m))
      nw_scores = self.needleman_wunsch(top_scores)
      nw_scores = nw_scores.reshape(n_lines1, top2k)
      matches = torch.remainder(
          torch.argmax(nw_scores, dim=1), top2k // 2
      )
      matches = topk_lines[torch.arange(n_lines1), matches]
      return matches
  
imports: from typing import Any, Dict, Optional, Tuple
  import torch
  import torch.nn.functional
  from kornia.core import Module, Tensor, concatenate, pad, stack
  from kornia.core.check import KORNIA_CHECK_SHAPE
  from kornia.geometry.conversions import normalize_pixel_coordinates
  from kornia.utils import map_location_to_cpu
  from .backbones import SOLD2Net
  from .sold2_detector import LineSegmentDetectionModule, line_map_to_segments, prob_to_junctions
label_desc: Use image node_id 4 for calling the WunschLineMatcher obj's underlying member method code with example usage: obj.filter_and_match_lines(scores) and returns: matches