Skip to content

Commit ce2ad1a

Browse files
committed
Add PSNR-HVS as third-party feature extractor.
1 parent eea4780 commit ce2ad1a

File tree

7 files changed

+466
-0
lines changed

7 files changed

+466
-0
lines changed

libvmaf/src/feature/feature_extractor.c

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ extern VmafFeatureExtractor vmaf_fex_float_ssim;
3636
extern VmafFeatureExtractor vmaf_fex_float_ms_ssim;
3737
extern VmafFeatureExtractor vmaf_fex_ciede;
3838
extern VmafFeatureExtractor vmaf_fex_psnr;
39+
extern VmafFeatureExtractor vmaf_fex_psnr_hvs;
3940
extern VmafFeatureExtractor vmaf_fex_integer_adm;
4041
extern VmafFeatureExtractor vmaf_fex_integer_motion;
4142
extern VmafFeatureExtractor vmaf_fex_integer_vif;
@@ -53,6 +54,7 @@ static VmafFeatureExtractor *feature_extractor_list[] = {
5354
&vmaf_fex_float_ssim,
5455
&vmaf_fex_ciede,
5556
&vmaf_fex_psnr,
57+
&vmaf_fex_psnr_hvs,
5658
&vmaf_fex_integer_adm,
5759
&vmaf_fex_integer_motion,
5860
&vmaf_fex_integer_vif,

libvmaf/src/feature/third_party/xiph/psnr_hvs.c

+384
Large diffs are not rendered by default.

libvmaf/src/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ vmaf_include = include_directories(
218218
libvmaf_feature_sources = [
219219
feature_src_dir + 'picture_copy.c',
220220
feature_src_dir + 'integer_psnr.c',
221+
feature_src_dir + 'third_party/xiph/psnr_hvs.c',
221222
feature_src_dir + 'feature_extractor.c',
222223
feature_src_dir + 'alias.c',
223224
feature_src_dir + 'integer_adm.c',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import unittest
2+
3+
import numpy as np
4+
5+
from test.testutil import set_default_576_324_videos_for_testing
6+
from vmaf.third_party.xiph.vmafexec_feature_extractor import PsnrhvsFeatureExtractor
7+
8+
9+
class FeatureExtractorTest(unittest.TestCase):
10+
11+
def setUp(self):
12+
self.verificationErrors = []
13+
self.maxDiff = None
14+
15+
def tearDown(self):
16+
if hasattr(self, 'fextractor'):
17+
self.fextractor.remove_results()
18+
pass
19+
self.assertEqual([], self.verificationErrors)
20+
21+
def test_run_psnrhvs_fextractor(self):
22+
ref_path, dis_path, asset, asset_original = set_default_576_324_videos_for_testing()
23+
self.fextractor = PsnrhvsFeatureExtractor(
24+
[asset, asset_original],
25+
None, fifo_mode=False,
26+
result_store=None
27+
)
28+
self.fextractor.run(parallelize=True)
29+
results = self.fextractor.results
30+
try: self.assertAlmostEqual(results[0]['PSNRHVS_feature_psnr_hvs_score'], 31.33044560416667, places=4)
31+
except AssertionError as e: self.verificationErrors.append(str(e))
32+
try: self.assertAlmostEqual(results[0]['PSNRHVS_feature_psnr_hvs_y_score'], 30.578766166666668, places=4)
33+
except AssertionError as e: self.verificationErrors.append(str(e))
34+
try: self.assertAlmostEqual(results[0]['PSNRHVS_feature_psnr_hvs_cb_score'], 37.25849772916666, places=4)
35+
except AssertionError as e: self.verificationErrors.append(str(e))
36+
try: self.assertAlmostEqual(results[0]['PSNRHVS_feature_psnr_hvs_cr_score'], 38.2002601875, places=4)
37+
except AssertionError as e: self.verificationErrors.append(str(e))
38+
try: self.assertAlmostEqual(results[1]['PSNRHVS_feature_psnr_hvs_score'], np.float('inf'), places=4)
39+
except AssertionError as e: self.verificationErrors.append(str(e))
40+
try: self.assertAlmostEqual(results[1]['PSNRHVS_feature_psnr_hvs_y_score'], np.float('inf'), places=4)
41+
except AssertionError as e: self.verificationErrors.append(str(e))
42+
try: self.assertAlmostEqual(results[1]['PSNRHVS_feature_psnr_hvs_cb_score'], np.float('inf'), places=4)
43+
except AssertionError as e: self.verificationErrors.append(str(e))
44+
try: self.assertAlmostEqual(results[1]['PSNRHVS_feature_psnr_hvs_cr_score'], np.float('inf'), places=4)
45+
except AssertionError as e: self.verificationErrors.append(str(e))

python/vmaf/third_party/__init__.py

Whitespace-only changes.

python/vmaf/third_party/xiph/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from vmaf import ExternalProgramCaller
2+
from vmaf.core.feature_extractor import VmafexecFeatureExtractorMixin, FeatureExtractor
3+
4+
5+
class PsnrhvsFeatureExtractor(VmafexecFeatureExtractorMixin, FeatureExtractor):
6+
7+
TYPE = 'PSNRHVS_feature'
8+
VERSION = "1.0"
9+
10+
ATOM_FEATURES = ['psnr_hvs', 'psnr_hvs_y', 'psnr_hvs_cb', 'psnr_hvs_cr']
11+
12+
ATOM_FEATURES_TO_VMAFEXEC_KEY_DICT = {
13+
'psnr_hvs': 'psnr_hvs',
14+
'psnr_hvs_y': 'psnr_hvs_y',
15+
'psnr_hvs_cb': 'psnr_hvs_cb',
16+
'psnr_hvs_cr': 'psnr_hvs_cr',
17+
}
18+
19+
def _generate_result(self, asset):
20+
# routine to call the command-line executable and generate quality
21+
# scores in the log file.
22+
23+
quality_width, quality_height = asset.quality_width_height
24+
log_file_path = self._get_log_file_path(asset)
25+
26+
yuv_type=self._get_workfile_yuv_type(asset)
27+
ref_path=asset.ref_procfile_path
28+
dis_path=asset.dis_procfile_path
29+
w=quality_width
30+
h=quality_height
31+
logger = self.logger
32+
33+
ExternalProgramCaller.call_vmafexec_single_feature('psnr_hvs', yuv_type, ref_path, dis_path, w, h,
34+
log_file_path, logger, options=self.optional_dict)

0 commit comments

Comments
 (0)