]> granicus.if.org Git - libvpx/commitdiff
VPX skin map improvement.
authorJackyChen <jackychen@google.com>
Tue, 26 Jan 2016 10:01:10 +0000 (18:01 +0800)
committerMarco <marpan@google.com>
Thu, 28 Jan 2016 18:38:14 +0000 (10:38 -0800)
Use multiple clusters instead of one and decrease
the distance thresholds.

Add a define to switch between models.
Default is set to existing (1 cluster) model.

Change-Id: I802cd9bb565437ae8983ef39453939f5d5073bb1

vp8/encoder/pickinter.c
vp9/encoder/vp9_skin_detection.c

index d0fff3f04f1439ee8af20e9034ac382f3d914990..0ea06329181daf9ac356159cb521315475270f4f 100644 (file)
@@ -36,6 +36,8 @@
 extern unsigned int cnt_pm;
 #endif
 
+#define MODEL_MODE 0
+
 extern const int vp8_ref_frame_order[MAX_MODES];
 extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
 
@@ -45,18 +47,21 @@ extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
 // skin color classifier is defined.
 
 // Fixed-point skin color model parameters.
-static const int skin_mean[2] = {7463, 9614};                 // q6
+static const int skin_mean[5][2] =
+    {{7463, 9614}, {6400, 10240}, {7040, 10240}, {8320, 9280}, {6800, 9614}};
 static const int skin_inv_cov[4] = {4107, 1663, 1663, 2157};  // q16
-static const int skin_threshold = 1570636;                    // q18
+static const int skin_threshold[2] = {1570636, 800000};       // q18
 
 // Evaluates the Mahalanobis distance measure for the input CbCr values.
-static int evaluate_skin_color_difference(int cb, int cr)
-{
+static int evaluate_skin_color_difference(int cb, int cr, int idx) {
   const int cb_q6 = cb << 6;
   const int cr_q6 = cr << 6;
-  const int cb_diff_q12 = (cb_q6 - skin_mean[0]) * (cb_q6 - skin_mean[0]);
-  const int cbcr_diff_q12 = (cb_q6 - skin_mean[0]) * (cr_q6 - skin_mean[1]);
-  const int cr_diff_q12 = (cr_q6 - skin_mean[1]) * (cr_q6 - skin_mean[1]);
+  const int cb_diff_q12 =
+      (cb_q6 - skin_mean[idx][0]) * (cb_q6 - skin_mean[idx][0]);
+  const int cbcr_diff_q12 =
+      (cb_q6 - skin_mean[idx][0]) * (cr_q6 - skin_mean[idx][1]);
+  const int cr_diff_q12 =
+      (cr_q6 - skin_mean[idx][1]) * (cr_q6 - skin_mean[idx][1]);
   const int cb_diff_q2 = (cb_diff_q12 + (1 << 9)) >> 10;
   const int cbcr_diff_q2 = (cbcr_diff_q12 + (1 << 9)) >> 10;
   const int cr_diff_q2 = (cr_diff_q12 + (1 << 9)) >> 10;
@@ -67,6 +72,34 @@ static int evaluate_skin_color_difference(int cb, int cr)
   return skin_diff;
 }
 
+// Checks if the input yCbCr values corresponds to skin color.
+static int is_skin_color(int y, int cb, int cr)
+{
+  if (y < 40 || y > 220)
+  {
+    return 0;
+  }
+  else
+  {
+    if (MODEL_MODE == 0)
+    {
+      return (evaluate_skin_color_difference(cb, cr, 0) < skin_threshold[0]);
+    }
+    else
+    {
+      int i = 0;
+      for (; i < 5; i++)
+      {
+        if (evaluate_skin_color_difference(cb, cr, i) < skin_threshold[1])
+        {
+          return 1;
+        }
+      }
+      return 0;
+    }
+  }
+}
+
 static int macroblock_corner_grad(unsigned char* signal, int stride,
                                   int offsetx, int offsety, int sgnx, int sgny)
 {
@@ -157,16 +190,6 @@ static int check_dot_artifact_candidate(VP8_COMP *cpi,
   return 0;
 }
 
-// Checks if the input yCbCr values corresponds to skin color.
-static int is_skin_color(int y, int cb, int cr)
-{
-  if (y < 40 || y > 220)
-  {
-    return 0;
-  }
-  return (evaluate_skin_color_difference(cb, cr) < skin_threshold);
-}
-
 int vp8_skip_fractional_mv_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d,
                                 int_mv *bestmv, int_mv *ref_mv,
                                 int error_per_bit,
index 0ca1665365d2416bdb601488a0b0ec513ee070b6..54cc0828b6b48b0d4d962d7c81d2087b7e9bc195 100644 (file)
 #include "vp9/encoder/vp9_encoder.h"
 #include "vp9/encoder/vp9_skin_detection.h"
 
+#define MODEL_MODE 0
+
 // Fixed-point skin color model parameters.
-static const int skin_mean[2] = {7463, 9614};                 // q6
+static const int skin_mean[5][2] = {
+    {7463, 9614}, {6400, 10240}, {7040, 10240}, {8320, 9280}, {6800, 9614}};
 static const int skin_inv_cov[4] = {4107, 1663, 1663, 2157};  // q16
-static const int skin_threshold = 1570636;                    // q18
+static const int skin_threshold[2] = {1570636, 800000};       // q18
 
 // Thresholds on luminance.
 static const int y_low = 20;
 static const int y_high = 220;
 
 // Evaluates the Mahalanobis distance measure for the input CbCr values.
-static int evaluate_skin_color_difference(int cb, int cr) {
+static int evaluate_skin_color_difference(int cb, int cr, int idx) {
   const int cb_q6 = cb << 6;
   const int cr_q6 = cr << 6;
-  const int cb_diff_q12 = (cb_q6 - skin_mean[0]) * (cb_q6 - skin_mean[0]);
-  const int cbcr_diff_q12 = (cb_q6 - skin_mean[0]) * (cr_q6 - skin_mean[1]);
-  const int cr_diff_q12 = (cr_q6 - skin_mean[1]) * (cr_q6 - skin_mean[1]);
+  const int cb_diff_q12 =
+      (cb_q6 - skin_mean[idx][0]) * (cb_q6 - skin_mean[idx][0]);
+  const int cbcr_diff_q12 =
+      (cb_q6 - skin_mean[idx][0]) * (cr_q6 - skin_mean[idx][1]);
+  const int cr_diff_q12 =
+      (cr_q6 - skin_mean[idx][1]) * (cr_q6 - skin_mean[idx][1]);
   const int cb_diff_q2 = (cb_diff_q12 + (1 << 9)) >> 10;
   const int cbcr_diff_q2 = (cbcr_diff_q12 + (1 << 9)) >> 10;
   const int cr_diff_q2 = (cr_diff_q12 + (1 << 9)) >> 10;
@@ -42,10 +48,21 @@ static int evaluate_skin_color_difference(int cb, int cr) {
 }
 
 int vp9_skin_pixel(const uint8_t y, const uint8_t cb, const uint8_t cr) {
-  if (y < y_low || y > y_high)
+  if (y < y_low || y > y_high) {
     return 0;
-  else
-    return (evaluate_skin_color_difference(cb, cr) < skin_threshold);
+  } else {
+    if (MODEL_MODE == 0) {
+      return (evaluate_skin_color_difference(cb, cr, 0) < skin_threshold[0]);
+    } else {
+      int i = 0;
+      for (; i < 5; i++) {
+        if (evaluate_skin_color_difference(cb, cr, i) < skin_threshold[1]) {
+          return 1;
+        }
+      }
+      return 0;
+    }
+  }
 }
 
 int vp9_compute_skin_block(const uint8_t *y, const uint8_t *u, const uint8_t *v,