VPX skin map improvement.

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
This commit is contained in:
JackyChen 2016-01-26 18:01:10 +08:00 committed by Marco
parent aa3fb7e1b5
commit d1e3d0467c
2 changed files with 66 additions and 26 deletions

View 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,

View File

@ -15,22 +15,28 @@
#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,