Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions libvmaf/src/feature/feature_extractor.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ extern VmafFeatureExtractor vmaf_fex_float_psnr;
extern VmafFeatureExtractor vmaf_fex_float_ansnr;
extern VmafFeatureExtractor vmaf_fex_float_adm;
extern VmafFeatureExtractor vmaf_fex_float_vif;
extern VmafFeatureExtractor vmaf_fex_integer_motion;
extern VmafFeatureExtractor vmaf_fex_integer_motion2;
Copy link
Collaborator

@kylophone kylophone Jun 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If #594 is merged, I don't think it makes sense to rename these *_motion2, since they provide both. We could also use the same feature extractor for motion3 in the future.

extern VmafFeatureExtractor vmaf_fex_integer_vif;
extern VmafFeatureExtractor vmaf_fex_float_motion;
extern VmafFeatureExtractor vmaf_fex_float_motion2;
extern VmafFeatureExtractor vmaf_fex_float_ms_ssim;
extern VmafFeatureExtractor vmaf_fex_float_moment;

Expand All @@ -44,9 +44,9 @@ static VmafFeatureExtractor *feature_extractor_list[] = {
&vmaf_fex_float_ansnr,
&vmaf_fex_float_adm,
&vmaf_fex_float_vif,
&vmaf_fex_integer_motion,
&vmaf_fex_integer_motion2,
&vmaf_fex_integer_vif,
&vmaf_fex_float_motion,
&vmaf_fex_float_motion2,
&vmaf_fex_float_ms_ssim,
&vmaf_fex_float_moment,
NULL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ static const char *provided_features[] = {
NULL
};

VmafFeatureExtractor vmaf_fex_float_motion = {
.name = "float_motion",
VmafFeatureExtractor vmaf_fex_float_motion2 = {
.name = "float_motion2",
.init = init,
.extract = extract,
.flush = flush,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ static const char *provided_features[] = {
NULL
};

VmafFeatureExtractor vmaf_fex_integer_motion = {
.name = "motion",
VmafFeatureExtractor vmaf_fex_integer_motion2 = {
.name = "motion2",
.init = init,
.extract = extract,
.flush = flush,
Expand Down
4 changes: 2 additions & 2 deletions libvmaf/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ libvmaf_rc_feature_sources = [
feature_src_dir + 'feature_collector.c',
feature_src_dir + 'float_psnr.c',
feature_src_dir + 'float_ansnr.c',
feature_src_dir + 'integer_motion.c',
feature_src_dir + 'float_motion.c',
feature_src_dir + 'integer_motion2.c',
feature_src_dir + 'float_motion2.c',
feature_src_dir + 'float_ssim.c',
feature_src_dir + 'float_ms_ssim.c',
feature_src_dir + 'float_vif.c',
Expand Down
4 changes: 2 additions & 2 deletions libvmaf/test/test_feature_extractor.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ static char *test_feature_extractor_flush()
int err = 0;

VmafFeatureExtractor *fex;
fex = vmaf_get_feature_extractor_by_name("float_motion");
fex = vmaf_get_feature_extractor_by_name("float_motion2");
mu_assert("problem vmaf_get_feature_extractor_by_name",
!strcmp(fex->name, "float_motion"));
!strcmp(fex->name, "float_motion2"));
VmafFeatureExtractorContext *fex_ctx;
err = vmaf_feature_extractor_context_create(&fex_ctx, fex, NULL);
mu_assert("problem during vmaf_feature_extractor_context_create", !err);
Expand Down
105 changes: 105 additions & 0 deletions python/test/vmafrc_feature_extractor_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import unittest

from test.testutil import set_default_576_324_videos_for_testing

from vmaf.core.vmafrc_feature_extractor import FloatMotion2FeatureExtractor, IntegerMotion2FeatureExtractor, FloatVifFeatureExtractor, FloatAdmFeatureExtractor, IntegerVifFeatureExtractor, IntegerPsnrFeatureExtractor


class FeatureExtractorTest(unittest.TestCase):

def tearDown(self):
if hasattr(self, 'fextractor'):
self.fextractor.remove_results()
pass

def test_run_float_motion2_fextractor(self):
ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing()
self.fextractor = FloatMotion2FeatureExtractor(
[asset, asset_original],
None, fifo_mode=False,
result_store=None
)
self.fextractor.run()
results = self.fextractor.results
self.assertAlmostEqual(results[0]['float_motion2_feature_motion2_score'], 3.8953518541666665, places=8)
self.assertAlmostEqual(results[1]['float_motion2_feature_motion2_score'], 3.8953518541666665, places=8)

def test_run_integer_motion2_fextractor(self):
ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing()
self.fextractor = IntegerMotion2FeatureExtractor(
[asset, asset_original],
None, fifo_mode=False,
result_store=None
)
self.fextractor.run()
results = self.fextractor.results
self.assertAlmostEqual(results[0]['integer_motion2_feature_motion2_score'], 3.895345229166667, places=8)
self.assertAlmostEqual(results[1]['integer_motion2_feature_motion2_score'], 3.895345229166667, places=8)

def test_run_float_vif_fextractor(self):
ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing()
self.fextractor = FloatVifFeatureExtractor(
[asset, asset_original],
None, fifo_mode=False,
result_store=None
)
self.fextractor.run()
results = self.fextractor.results
self.assertAlmostEqual(results[0]['float_VIF_feature_vif_scale0_score'], 0.3634208125, places=6)
self.assertAlmostEqual(results[0]['float_VIF_feature_vif_scale1_score'], 0.7666474166666667, places=6)
self.assertAlmostEqual(results[0]['float_VIF_feature_vif_scale2_score'], 0.8628533333333334, places=6)
self.assertAlmostEqual(results[0]['float_VIF_feature_vif_scale3_score'], 0.9159719583333334, places=6)
self.assertAlmostEqual(results[1]['float_VIF_feature_vif_scale0_score'], 1.0, places=6)
self.assertAlmostEqual(results[1]['float_VIF_feature_vif_scale1_score'], 1.0, places=6)
self.assertAlmostEqual(results[1]['float_VIF_feature_vif_scale2_score'], 1.0, places=6)
self.assertAlmostEqual(results[1]['float_VIF_feature_vif_scale3_score'], 1.0, places=5)

def test_run_integer_vif_fextractor(self):
ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing()
self.fextractor = IntegerVifFeatureExtractor(
[asset, asset_original],
None, fifo_mode=False,
result_store=None
)
self.fextractor.run()
results = self.fextractor.results
self.assertAlmostEqual(results[0]['integer_VIF_feature_vif_scale0_score'], 0.3634233125, places=6)
self.assertAlmostEqual(results[0]['integer_VIF_feature_vif_scale1_score'], 0.7666542916666667, places=6)
self.assertAlmostEqual(results[0]['integer_VIF_feature_vif_scale2_score'], 0.862872125, places=6)
self.assertAlmostEqual(results[0]['integer_VIF_feature_vif_scale3_score'], 0.9159956249999999, places=6)
self.assertAlmostEqual(results[1]['integer_VIF_feature_vif_scale0_score'], 1.000002, places=6)
self.assertAlmostEqual(results[1]['integer_VIF_feature_vif_scale1_score'], 1.0000023541666667, places=6)
self.assertAlmostEqual(results[1]['integer_VIF_feature_vif_scale2_score'], 1.0000022916666667, places=6)
self.assertAlmostEqual(results[1]['integer_VIF_feature_vif_scale3_score'], 1.0, places=5)

def test_run_float_adm_fextractor(self):
ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing()
self.fextractor = FloatAdmFeatureExtractor(
[asset, asset_original],
None, fifo_mode=False,
result_store=None
)
self.fextractor.run()
results = self.fextractor.results
self.assertAlmostEqual(results[0]['float_ADM_feature_adm2_score'], 0.9345877291666667, places=6)
self.assertAlmostEqual(results[1]['float_ADM_feature_adm2_score'], 1.0, places=6)

def test_run_integer_psnr_fextractor(self):
ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing()
self.fextractor = IntegerPsnrFeatureExtractor(
[asset, asset_original],
None, fifo_mode=False,
result_store=None
)
self.fextractor.run()
results = self.fextractor.results
self.assertAlmostEqual(results[0]['integer_PSNR_feature_psnr_y_score'], 30.755063979166664, places=4)
self.assertAlmostEqual(results[0]['integer_PSNR_feature_psnr_cb_score'], 38.4494410625, places=4)
self.assertAlmostEqual(results[0]['integer_PSNR_feature_psnr_cr_score'], 40.99191027083334, places=4)
self.assertAlmostEqual(results[1]['integer_PSNR_feature_psnr_y_score'], 60.0, places=4)
self.assertAlmostEqual(results[1]['integer_PSNR_feature_psnr_cb_score'], 60.0, places=4)
self.assertAlmostEqual(results[1]['integer_PSNR_feature_psnr_cr_score'], 60.0, places=4)


if __name__ == '__main__':
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion python/vmaf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def call_vmafrc_multi_features(features, yuv_type, ref_path, dis_path, w, h, log
# --reference python/test/resource/yuv/src01_hrc00_576x324.yuv
# --distorted python/test/resource/yuv/src01_hrc01_576x324.yuv
# --width 576 --height 324 --pixel_format 420 --bitdepth 8
# --output /dev/stdout --xml --no_prediction --feature float_motion --feature integer_motion
# --output /dev/stdout --xml --no_prediction --feature float_motion2 --feature integer_motion2

pixel_format, bitdepth = convert_pixel_format_ffmpeg2vmafrc(yuv_type)

Expand Down
181 changes: 181 additions & 0 deletions python/vmaf/core/vmafrc_feature_extractor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
from vmaf import ExternalProgramCaller
from vmaf.core.feature_extractor import VmafrcFeatureExtractorMixin, FeatureExtractor


class FloatMotion2FeatureExtractor(VmafrcFeatureExtractorMixin, FeatureExtractor):

TYPE = "float_motion2_feature"
VERSION = "1.0"

ATOM_FEATURES = ['motion2']

ATOM_FEATURES_TO_VMAFRC_KEY_DICT = {
'motion2': 'motion2',
}

def _generate_result(self, asset):
# routine to call the command-line executable and generate quality
# scores in the log file.

quality_width, quality_height = asset.quality_width_height
log_file_path = self._get_log_file_path(asset)

yuv_type=self._get_workfile_yuv_type(asset)
ref_path=asset.ref_procfile_path
dis_path=asset.dis_procfile_path
w=quality_width
h=quality_height
logger = self.logger

ExternalProgramCaller.call_vmafrc_single_feature('float_motion2', yuv_type, ref_path, dis_path, w, h, log_file_path, logger)


class IntegerMotion2FeatureExtractor(VmafrcFeatureExtractorMixin, FeatureExtractor):

TYPE = "integer_motion2_feature"
VERSION = "1.0"

ATOM_FEATURES = ['motion2']

ATOM_FEATURES_TO_VMAFRC_KEY_DICT = {
'motion2': 'integer_motion2',
}

def _generate_result(self, asset):
# routine to call the command-line executable and generate quality
# scores in the log file.

quality_width, quality_height = asset.quality_width_height
log_file_path = self._get_log_file_path(asset)

yuv_type=self._get_workfile_yuv_type(asset)
ref_path=asset.ref_procfile_path
dis_path=asset.dis_procfile_path
w=quality_width
h=quality_height
logger = self.logger

ExternalProgramCaller.call_vmafrc_single_feature('motion2', yuv_type, ref_path, dis_path, w, h, log_file_path, logger)


class FloatVifFeatureExtractor(VmafrcFeatureExtractorMixin, FeatureExtractor):

TYPE = "float_VIF_feature"
VERSION = "1.0"

ATOM_FEATURES = ['vif_scale0', 'vif_scale1', 'vif_scale2', 'vif_scale3',
]

ATOM_FEATURES_TO_VMAFRC_KEY_DICT = {
'vif_scale0': 'vif_scale0',
'vif_scale1': 'vif_scale1',
'vif_scale2': 'vif_scale2',
'vif_scale3': 'vif_scale3',
}

def _generate_result(self, asset):
# routine to call the command-line executable and generate quality
# scores in the log file.

quality_width, quality_height = asset.quality_width_height
log_file_path = self._get_log_file_path(asset)

yuv_type=self._get_workfile_yuv_type(asset)
ref_path=asset.ref_procfile_path
dis_path=asset.dis_procfile_path
w=quality_width
h=quality_height
logger = self.logger

ExternalProgramCaller.call_vmafrc_single_feature('float_vif', yuv_type, ref_path, dis_path, w, h, log_file_path, logger)


class IntegerVifFeatureExtractor(VmafrcFeatureExtractorMixin, FeatureExtractor):

TYPE = "integer_VIF_feature"
VERSION = "1.0"

ATOM_FEATURES = ['vif_scale0', 'vif_scale1', 'vif_scale2', 'vif_scale3',
]

ATOM_FEATURES_TO_VMAFRC_KEY_DICT = {
'vif_scale0': 'integer_vif_scale0',
'vif_scale1': 'integer_vif_scale1',
'vif_scale2': 'integer_vif_scale2',
'vif_scale3': 'integer_vif_scale3',
}

def _generate_result(self, asset):
# routine to call the command-line executable and generate quality
# scores in the log file.

quality_width, quality_height = asset.quality_width_height
log_file_path = self._get_log_file_path(asset)

yuv_type=self._get_workfile_yuv_type(asset)
ref_path=asset.ref_procfile_path
dis_path=asset.dis_procfile_path
w=quality_width
h=quality_height
logger = self.logger

ExternalProgramCaller.call_vmafrc_single_feature('vif', yuv_type, ref_path, dis_path, w, h, log_file_path, logger)


class FloatAdmFeatureExtractor(VmafrcFeatureExtractorMixin, FeatureExtractor):

TYPE = "float_ADM_feature"
VERSION = "1.0"

ATOM_FEATURES = ['adm2',
]

ATOM_FEATURES_TO_VMAFRC_KEY_DICT = {
'adm2': 'adm2',
}

def _generate_result(self, asset):
# routine to call the command-line executable and generate quality
# scores in the log file.

quality_width, quality_height = asset.quality_width_height
log_file_path = self._get_log_file_path(asset)

yuv_type=self._get_workfile_yuv_type(asset)
ref_path=asset.ref_procfile_path
dis_path=asset.dis_procfile_path
w=quality_width
h=quality_height
logger = self.logger

ExternalProgramCaller.call_vmafrc_single_feature('float_adm', yuv_type, ref_path, dis_path, w, h, log_file_path, logger)


class IntegerPsnrFeatureExtractor(VmafrcFeatureExtractorMixin, FeatureExtractor):

TYPE = 'integer_PSNR_feature'
VERSION = "1.0"

ATOM_FEATURES = ['psnr_y', 'psnr_cb', 'psnr_cr']

ATOM_FEATURES_TO_VMAFRC_KEY_DICT = {
'psnr_y': 'psnr_y',
'psnr_cb': 'psnr_cb',
'psnr_cr': 'psnr_cr',
}

def _generate_result(self, asset):
# routine to call the command-line executable and generate quality
# scores in the log file.

quality_width, quality_height = asset.quality_width_height
log_file_path = self._get_log_file_path(asset)

yuv_type=self._get_workfile_yuv_type(asset)
ref_path=asset.ref_procfile_path
dis_path=asset.dis_procfile_path
w=quality_width
h=quality_height
logger = self.logger

ExternalProgramCaller.call_vmafrc_single_feature('psnr', yuv_type, ref_path, dis_path, w, h, log_file_path, logger)