Compute strongest Sobel x and y edge component Change-Id: I731975a3f5e49602a5e370e9aa6fa5b8dc01ce6a
diff --git a/av1/encoder/block.h b/av1/encoder/block.h index 87761e9..e96ca16 100644 --- a/av1/encoder/block.h +++ b/av1/encoder/block.h
@@ -416,6 +416,9 @@ // detection). For reference, 556 is the value returned for a solid // vertical black/white edge. uint16_t edge_strength; + // The strongest edge strength seen along the x/y axis. + uint16_t edge_strength_x; + uint16_t edge_strength_y; // [Saved stat index] COMP_RD_STATS comp_rd_stats[MAX_COMP_RD_STATS];
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index 50b619f..3423abf 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -510,15 +510,16 @@ cpi, cm->base_qindex + xd->delta_qindex + cm->y_dc_delta_q); } -static uint16_t edge_strength(const struct buf_2d *ref, const BLOCK_SIZE bsize, - const bool high_bd, const int bd) { +static EdgeInfo edge_info(const struct buf_2d *ref, const BLOCK_SIZE bsize, + const bool high_bd, const int bd) { const int width = block_size_wide[bsize]; const int height = block_size_high[bsize]; // Implementation requires width to be a multiple of 8. It also requires // height to be a multiple of 4, but this is always the case. assert(height % 4 == 0); if (width % 8 != 0) { - return 0; + EdgeInfo ei = { .magnitude = 0, .x = 0, .y = 0 }; + return ei; } return av1_edge_exists(ref->buf, ref->stride, width, height, high_bd, bd); } @@ -611,9 +612,14 @@ // should not be used. Use a value that will always succeed in the check. if (cpi->sf.disable_wedge_search_edge_thresh == 0) { x->edge_strength = UINT16_MAX; + x->edge_strength_x = UINT16_MAX; + x->edge_strength_y = UINT16_MAX; } else { - x->edge_strength = - edge_strength(&x->plane[0].src, bsize, is_cur_buf_hbd(xd), xd->bd); + EdgeInfo ei = + edge_info(&x->plane[0].src, bsize, is_cur_buf_hbd(xd), xd->bd); + x->edge_strength = ei.magnitude; + x->edge_strength_x = ei.x; + x->edge_strength_y = ei.y; } // Save rdmult before it might be changed, so it can be restored later. orig_rdmult = x->rdmult;
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c index 28caad0..f5dfca0 100644 --- a/av1/encoder/rdopt.c +++ b/av1/encoder/rdopt.c
@@ -13061,12 +13061,14 @@ } } -static uint16_t edge_probability(const uint8_t *input, int w, int h, +static EdgeInfo edge_probability(const uint8_t *input, int w, int h, bool high_bd, int bd) { // The probability of an edge in the whole image is the same as the highest // probability of an edge for any individual pixel. Use Sobel as the metric // for finding an edge. uint16_t highest = 0; + uint16_t highest_x = 0; + uint16_t highest_y = 0; // Ignore the 1 pixel border around the image for the computation. for (int j = 1; j < h - 1; ++j) { for (int i = 1; i < w - 1; ++i) { @@ -13076,18 +13078,22 @@ int16_t g_y = g.y >> (bd - 8); uint16_t magnitude = (uint16_t)sqrt(g_x * g_x + g_y * g_y); highest = AOMMAX(highest, magnitude); + highest_x = AOMMAX(highest_x, g_x); + highest_y = AOMMAX(highest_y, g_y); } } - return highest; + EdgeInfo ei = { .magnitude = highest, .x = highest_x, .y = highest_y }; + return ei; } /* Uses most of the Canny edge detection algorithm to find if there are any * edges in the image. */ -uint16_t av1_edge_exists(const uint8_t *src, int src_stride, int w, int h, +EdgeInfo av1_edge_exists(const uint8_t *src, int src_stride, int w, int h, bool high_bd, int bd) { if (w < 3 || h < 3) { - return 0; + EdgeInfo n = { .magnitude = 0, .x = 0, .y = 0 }; + return n; } uint8_t *blurred; if (high_bd) { @@ -13100,7 +13106,7 @@ // want a probability of an edge existing in the buffer, which is determined // by the strongest edge in it -- we don't need to eliminate the weaker // edges. Use Sobel for the edge detection. - uint16_t prob = edge_probability(blurred, w, h, high_bd, bd); + EdgeInfo prob = edge_probability(blurred, w, h, high_bd, bd); if (high_bd) { aom_free(CONVERT_TO_SHORTPTR(blurred)); } else {
diff --git a/av1/encoder/rdopt.h b/av1/encoder/rdopt.h index 983d385..0ce931a 100644 --- a/av1/encoder/rdopt.h +++ b/av1/encoder/rdopt.h
@@ -128,13 +128,21 @@ struct macroblock *x, int mi_row, int mi_col, struct RD_STATS *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far); +// The best edge strength seen in the block, as well as the best x and y +// components of edge strength seen. +typedef struct { + uint16_t magnitude; + uint16_t x; + uint16_t y; +} EdgeInfo; + /** Returns an integer indicating the strength of the edge. * 0 means no edge found, 556 is the strength of a solid black/white edge, * and the number may range higher if the signal is even stronger (e.g., on a * corner). high_bd is a bool indicating the source should be treated * as a 16-bit array. bd is the bit depth. */ -uint16_t av1_edge_exists(const uint8_t *src, int src_stride, int w, int h, +EdgeInfo av1_edge_exists(const uint8_t *src, int src_stride, int w, int h, bool high_bd, int bd); /** Applies a Gaussian blur with sigma = 1.3. Used by av1_edge_exists and
diff --git a/test/edge_detect_test.cc b/test/edge_detect_test.cc index 47466cb..77a731f 100644 --- a/test/edge_detect_test.cc +++ b/test/edge_detect_test.cc
@@ -185,8 +185,9 @@ const bool high_bd = GET_PARAM(3); const int bd = GET_PARAM(4); - ASSERT_EQ(0, av1_edge_exists(input_, stride_8tap(width), width, height, - high_bd, bd)); + ASSERT_EQ( + 0, av1_edge_exists(input_, stride_8tap(width), width, height, high_bd, bd) + .magnitude); } INSTANTIATE_TEST_CASE_P(ImageBrightnessTests, EdgeDetectBrightnessTest, @@ -245,9 +246,11 @@ free(orig); // Value should be between 556 and 560. ASSERT_LE(556, av1_edge_exists(padded, stride_8tap(width), width, height, - high_bd, bd)); + high_bd, bd) + .magnitude); ASSERT_GE(560, av1_edge_exists(padded, stride_8tap(width), width, height, - high_bd, bd)); + high_bd, bd) + .magnitude); free_pad_8tap(padded, width, high_bd); }