LCOV - code coverage report
Current view: top level - third_party/aom/av1/encoder - corner_match.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 108 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
       3             :  *
       4             :  * This source code is subject to the terms of the BSD 2 Clause License and
       5             :  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
       6             :  * was not distributed with this source code in the LICENSE file, you can
       7             :  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
       8             :  * Media Patent License 1.0 was not distributed with this source code in the
       9             :  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
      10             :  */
      11             : 
      12             : #include <stdlib.h>
      13             : #include <memory.h>
      14             : #include <math.h>
      15             : 
      16             : #include "./av1_rtcd.h"
      17             : #include "av1/encoder/corner_match.h"
      18             : 
      19             : #define SEARCH_SZ 9
      20             : #define SEARCH_SZ_BY2 ((SEARCH_SZ - 1) / 2)
      21             : 
      22             : #define THRESHOLD_NCC 0.75
      23             : 
      24             : /* Compute var(im) * MATCH_SZ_SQ over a MATCH_SZ by MATCH_SZ window of im,
      25             :    centered at (x, y).
      26             : */
      27           0 : static double compute_variance(unsigned char *im, int stride, int x, int y) {
      28           0 :   int sum = 0;
      29           0 :   int sumsq = 0;
      30             :   int var;
      31             :   int i, j;
      32           0 :   for (i = 0; i < MATCH_SZ; ++i)
      33           0 :     for (j = 0; j < MATCH_SZ; ++j) {
      34           0 :       sum += im[(i + y - MATCH_SZ_BY2) * stride + (j + x - MATCH_SZ_BY2)];
      35           0 :       sumsq += im[(i + y - MATCH_SZ_BY2) * stride + (j + x - MATCH_SZ_BY2)] *
      36           0 :                im[(i + y - MATCH_SZ_BY2) * stride + (j + x - MATCH_SZ_BY2)];
      37             :     }
      38           0 :   var = sumsq * MATCH_SZ_SQ - sum * sum;
      39           0 :   return (double)var;
      40             : }
      41             : 
      42             : /* Compute corr(im1, im2) * MATCH_SZ * stddev(im1), where the
      43             :    correlation/standard deviation are taken over MATCH_SZ by MATCH_SZ windows
      44             :    of each image, centered at (x1, y1) and (x2, y2) respectively.
      45             : */
      46           0 : double compute_cross_correlation_c(unsigned char *im1, int stride1, int x1,
      47             :                                    int y1, unsigned char *im2, int stride2,
      48             :                                    int x2, int y2) {
      49             :   int v1, v2;
      50           0 :   int sum1 = 0;
      51           0 :   int sum2 = 0;
      52           0 :   int sumsq2 = 0;
      53           0 :   int cross = 0;
      54             :   int var2, cov;
      55             :   int i, j;
      56           0 :   for (i = 0; i < MATCH_SZ; ++i)
      57           0 :     for (j = 0; j < MATCH_SZ; ++j) {
      58           0 :       v1 = im1[(i + y1 - MATCH_SZ_BY2) * stride1 + (j + x1 - MATCH_SZ_BY2)];
      59           0 :       v2 = im2[(i + y2 - MATCH_SZ_BY2) * stride2 + (j + x2 - MATCH_SZ_BY2)];
      60           0 :       sum1 += v1;
      61           0 :       sum2 += v2;
      62           0 :       sumsq2 += v2 * v2;
      63           0 :       cross += v1 * v2;
      64             :     }
      65           0 :   var2 = sumsq2 * MATCH_SZ_SQ - sum2 * sum2;
      66           0 :   cov = cross * MATCH_SZ_SQ - sum1 * sum2;
      67           0 :   return cov / sqrt((double)var2);
      68             : }
      69             : 
      70           0 : static int is_eligible_point(int pointx, int pointy, int width, int height) {
      71           0 :   return (pointx >= MATCH_SZ_BY2 && pointy >= MATCH_SZ_BY2 &&
      72           0 :           pointx + MATCH_SZ_BY2 < width && pointy + MATCH_SZ_BY2 < height);
      73             : }
      74             : 
      75           0 : static int is_eligible_distance(int point1x, int point1y, int point2x,
      76             :                                 int point2y, int width, int height) {
      77           0 :   const int thresh = (width < height ? height : width) >> 4;
      78           0 :   return ((point1x - point2x) * (point1x - point2x) +
      79           0 :           (point1y - point2y) * (point1y - point2y)) <= thresh * thresh;
      80             : }
      81             : 
      82           0 : static void improve_correspondence(unsigned char *frm, unsigned char *ref,
      83             :                                    int width, int height, int frm_stride,
      84             :                                    int ref_stride,
      85             :                                    Correspondence *correspondences,
      86             :                                    int num_correspondences) {
      87             :   int i;
      88           0 :   for (i = 0; i < num_correspondences; ++i) {
      89           0 :     int x, y, best_x = 0, best_y = 0;
      90           0 :     double best_match_ncc = 0.0;
      91           0 :     for (y = -SEARCH_SZ_BY2; y <= SEARCH_SZ_BY2; ++y) {
      92           0 :       for (x = -SEARCH_SZ_BY2; x <= SEARCH_SZ_BY2; ++x) {
      93             :         double match_ncc;
      94           0 :         if (!is_eligible_point(correspondences[i].rx + x,
      95           0 :                                correspondences[i].ry + y, width, height))
      96           0 :           continue;
      97           0 :         if (!is_eligible_distance(correspondences[i].x, correspondences[i].y,
      98           0 :                                   correspondences[i].rx + x,
      99           0 :                                   correspondences[i].ry + y, width, height))
     100           0 :           continue;
     101           0 :         match_ncc = compute_cross_correlation(
     102           0 :             frm, frm_stride, correspondences[i].x, correspondences[i].y, ref,
     103           0 :             ref_stride, correspondences[i].rx + x, correspondences[i].ry + y);
     104           0 :         if (match_ncc > best_match_ncc) {
     105           0 :           best_match_ncc = match_ncc;
     106           0 :           best_y = y;
     107           0 :           best_x = x;
     108             :         }
     109             :       }
     110             :     }
     111           0 :     correspondences[i].rx += best_x;
     112           0 :     correspondences[i].ry += best_y;
     113             :   }
     114           0 :   for (i = 0; i < num_correspondences; ++i) {
     115           0 :     int x, y, best_x = 0, best_y = 0;
     116           0 :     double best_match_ncc = 0.0;
     117           0 :     for (y = -SEARCH_SZ_BY2; y <= SEARCH_SZ_BY2; ++y)
     118           0 :       for (x = -SEARCH_SZ_BY2; x <= SEARCH_SZ_BY2; ++x) {
     119             :         double match_ncc;
     120           0 :         if (!is_eligible_point(correspondences[i].x + x,
     121           0 :                                correspondences[i].y + y, width, height))
     122           0 :           continue;
     123           0 :         if (!is_eligible_distance(
     124           0 :                 correspondences[i].x + x, correspondences[i].y + y,
     125           0 :                 correspondences[i].rx, correspondences[i].ry, width, height))
     126           0 :           continue;
     127           0 :         match_ncc = compute_cross_correlation(
     128           0 :             ref, ref_stride, correspondences[i].rx, correspondences[i].ry, frm,
     129           0 :             frm_stride, correspondences[i].x + x, correspondences[i].y + y);
     130           0 :         if (match_ncc > best_match_ncc) {
     131           0 :           best_match_ncc = match_ncc;
     132           0 :           best_y = y;
     133           0 :           best_x = x;
     134             :         }
     135             :       }
     136           0 :     correspondences[i].x += best_x;
     137           0 :     correspondences[i].y += best_y;
     138             :   }
     139           0 : }
     140             : 
     141           0 : int determine_correspondence(unsigned char *frm, int *frm_corners,
     142             :                              int num_frm_corners, unsigned char *ref,
     143             :                              int *ref_corners, int num_ref_corners, int width,
     144             :                              int height, int frm_stride, int ref_stride,
     145             :                              int *correspondence_pts) {
     146             :   // TODO(sarahparker) Improve this to include 2-way match
     147             :   int i, j;
     148           0 :   Correspondence *correspondences = (Correspondence *)correspondence_pts;
     149           0 :   int num_correspondences = 0;
     150           0 :   for (i = 0; i < num_frm_corners; ++i) {
     151           0 :     double best_match_ncc = 0.0;
     152             :     double template_norm;
     153           0 :     int best_match_j = -1;
     154           0 :     if (!is_eligible_point(frm_corners[2 * i], frm_corners[2 * i + 1], width,
     155             :                            height))
     156           0 :       continue;
     157           0 :     for (j = 0; j < num_ref_corners; ++j) {
     158             :       double match_ncc;
     159           0 :       if (!is_eligible_point(ref_corners[2 * j], ref_corners[2 * j + 1], width,
     160             :                              height))
     161           0 :         continue;
     162           0 :       if (!is_eligible_distance(frm_corners[2 * i], frm_corners[2 * i + 1],
     163           0 :                                 ref_corners[2 * j], ref_corners[2 * j + 1],
     164             :                                 width, height))
     165           0 :         continue;
     166           0 :       match_ncc = compute_cross_correlation(
     167           0 :           frm, frm_stride, frm_corners[2 * i], frm_corners[2 * i + 1], ref,
     168           0 :           ref_stride, ref_corners[2 * j], ref_corners[2 * j + 1]);
     169           0 :       if (match_ncc > best_match_ncc) {
     170           0 :         best_match_ncc = match_ncc;
     171           0 :         best_match_j = j;
     172             :       }
     173             :     }
     174             :     // Note: We want to test if the best correlation is >= THRESHOLD_NCC,
     175             :     // but need to account for the normalization in compute_cross_correlation.
     176           0 :     template_norm = compute_variance(frm, frm_stride, frm_corners[2 * i],
     177           0 :                                      frm_corners[2 * i + 1]);
     178           0 :     if (best_match_ncc > THRESHOLD_NCC * sqrt(template_norm)) {
     179           0 :       correspondences[num_correspondences].x = frm_corners[2 * i];
     180           0 :       correspondences[num_correspondences].y = frm_corners[2 * i + 1];
     181           0 :       correspondences[num_correspondences].rx = ref_corners[2 * best_match_j];
     182           0 :       correspondences[num_correspondences].ry =
     183           0 :           ref_corners[2 * best_match_j + 1];
     184           0 :       num_correspondences++;
     185             :     }
     186             :   }
     187           0 :   improve_correspondence(frm, ref, width, height, frm_stride, ref_stride,
     188             :                          correspondences, num_correspondences);
     189           0 :   return num_correspondences;
     190             : }

Generated by: LCOV version 1.13