From a36017e007e0822366ebb1bb530b5bf9189e2f3c Mon Sep 17 00:00:00 2001 From: Jerome Jiang Date: Tue, 13 Jun 2017 17:22:26 -0700 Subject: [PATCH] Enable 8x8 skin detection for vp8. If 2 or more 8x8 blocks are identified as skin, the macroblock will be labeled as skin. Change-Id: I596542c81a2df9e96270cab39d920bbfeb02bc6e --- vp8/common/vp8_skin_detection.c | 58 +++++++++++++++++++++++++-------- vp8/common/vp8_skin_detection.h | 11 ++++++- vp8/encoder/pickinter.c | 2 +- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/vp8/common/vp8_skin_detection.c b/vp8/common/vp8_skin_detection.c index 495366dc8..2c0237087 100644 --- a/vp8/common/vp8_skin_detection.c +++ b/vp8/common/vp8_skin_detection.c @@ -14,26 +14,55 @@ #include "vpx_mem/vpx_mem.h" #include "vpx_util/vpx_write_yuv_frame.h" +static int avg_2x2(const uint8_t *s, int p) { + int i, j; + int sum = 0; + for (i = 0; i < 2; ++i, s += p) { + for (j = 0; j < 2; ++j) { + sum += s[j]; + } + } + return (sum + 2) >> 2; +} + int vp8_compute_skin_block(const uint8_t *y, const uint8_t *u, const uint8_t *v, - int stride, int strideuv, int consec_zeromv, + int stride, int strideuv, + SKIN_DETECTION_BLOCK_SIZE bsize, int consec_zeromv, int curr_motion_magn) { // No skin if block has been zero/small motion for long consecutive time. if (consec_zeromv > 60 && curr_motion_magn == 0) { return 0; } else { int motion = 1; - // Take the average of center 2x2 pixels. - const int ysource = (y[7 * stride + 7] + y[7 * stride + 8] + - y[8 * stride + 7] + y[8 * stride + 8]) >> - 2; - const int usource = (u[3 * strideuv + 3] + u[3 * strideuv + 4] + - u[4 * strideuv + 3] + u[4 * strideuv + 4]) >> - 2; - const int vsource = (v[3 * strideuv + 3] + v[3 * strideuv + 4] + - v[4 * strideuv + 3] + v[4 * strideuv + 4]) >> - 2; if (consec_zeromv > 25 && curr_motion_magn == 0) motion = 0; - return vpx_skin_pixel(ysource, usource, vsource, motion); + if (bsize == SKIN_16X16) { + // Take the average of center 2x2 pixels. + const int ysource = avg_2x2(y + 7 * stride + 7, stride); + const int usource = avg_2x2(u + 3 * strideuv + 3, strideuv); + const int vsource = avg_2x2(v + 3 * strideuv + 3, strideuv); + return vpx_skin_pixel(ysource, usource, vsource, motion); + } else { + int num_skin = 0; + int i, j; + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + // Take the average of center 2x2 pixels. + const int ysource = avg_2x2(y + 3 * stride + 3, stride); + const int usource = avg_2x2(u + strideuv + 1, strideuv); + const int vsource = avg_2x2(v + strideuv + 1, strideuv); + num_skin += vpx_skin_pixel(ysource, usource, vsource, motion); + if (num_skin >= 2) return 1; + y += 8; + u += 4; + v += 4; + } + y += (stride << 3) - 16; + u += (strideuv << 2) - 8; + v += (strideuv << 2) - 8; + } + + return 0; + } } } @@ -74,8 +103,9 @@ void vp8_compute_skin_map(VP8_COMP *const cpi, FILE *yuv_skinmap_file) { VPXMIN(cpi->consec_zero_last[bl_index1], VPXMIN(cpi->consec_zero_last[bl_index2], cpi->consec_zero_last[bl_index3]))); - is_skin = vp8_compute_skin_block(src_y, src_u, src_v, src_ystride, - src_uvstride, consec_zeromv, 0); + is_skin = + vp8_compute_skin_block(src_y, src_u, src_v, src_ystride, src_uvstride, + SKIN_8X8, consec_zeromv, 0); for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { if (is_skin) diff --git a/vp8/common/vp8_skin_detection.h b/vp8/common/vp8_skin_detection.h index 3d0a9f45f..4d27f5eb2 100644 --- a/vp8/common/vp8_skin_detection.h +++ b/vp8/common/vp8_skin_detection.h @@ -22,8 +22,17 @@ extern "C" { struct VP8_COMP; +typedef enum { + // Skin detection based on 8x8 block. If two of them are identified as skin, + // the macroblock is marked as skin. + SKIN_8X8, + // Skin detection based on 16x16 block. + SKIN_16X16 +} SKIN_DETECTION_BLOCK_SIZE; + int vp8_compute_skin_block(const uint8_t *y, const uint8_t *u, const uint8_t *v, - int stride, int strideuv, int consec_zeromv, + int stride, int strideuv, + SKIN_DETECTION_BLOCK_SIZE bsize, int consec_zeromv, int curr_motion_magn); #ifdef OUTPUT_YUV_SKINMAP diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c index 74f9def69..d399839dd 100644 --- a/vp8/encoder/pickinter.c +++ b/vp8/encoder/pickinter.c @@ -693,7 +693,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int block_index = mb_row * cpi->common.mb_cols + mb_col; x->is_skin = vp8_compute_skin_block( x->src.y_buffer, x->src.u_buffer, x->src.v_buffer, x->src.y_stride, - x->src.uv_stride, cpi->consec_zero_last[block_index], 0); + x->src.uv_stride, SKIN_16X16, cpi->consec_zero_last[block_index], 0); } #if CONFIG_TEMPORAL_DENOISING if (cpi->oxcf.noise_sensitivity) { -- 2.40.0