feat: rework lens test to account for ambiguous lenses

For each lens, its test target is now defined as the list of all lenses
which are possible given that lenses exif values.
main
Christoph Hasse 4 years ago
parent a70896c1ac
commit cc89dca5a2

@ -4,7 +4,7 @@ import re
import os
import system_tests
import math
from lens_tests.utils import extract_lenses_from_cpp
from lens_tests.utils import extract_lenses_from_cpp, make_test_cases
# get directory of the current file
file_dir = os.path.dirname(os.path.realpath(__file__))
@ -14,38 +14,37 @@ canon_lens_file = os.path.abspath(os.path.join(file_dir, "./../../src/canonmn_in
startpattern = "constexpr TagDetails canonCsLensType[] = {"
# use utils function to extract all lenses
lenses = extract_lenses_from_cpp(canon_lens_file, startpattern)
# use utils function to define test case data
test_cases = make_test_cases(lenses)
# see https://github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/Canon.pm#L9678
def aperture_to_raw_exif(aperture):
#see https://github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/Canon.pm#L9678
aperture = float(aperture)
# for apertures < 1 the below is negative
num = math.log(aperture)*2/math.log(2)
num = math.log(aperture) * 2 / math.log(2)
# temporarily make the number positive
if (num < 0):
if num < 0:
num = -num
sign = -1
else:
sign = 1;
sign = 1
val = int(num)
frac = num - val
if (abs(frac - 0.33) < 0.05):
frac = 0x0c
elif (abs(frac - 0.67) < 0.05):
frac = 0x14;
if abs(frac - 0.33) < 0.05:
frac = 0x0C
elif abs(frac - 0.67) < 0.05:
frac = 0x14
else:
frac = int(frac * 0x20 + 0.5)
return sign * (val * 0x20 + frac);
return sign * (val * 0x20 + frac)
for (lens_id, lens_desc, meta) in lenses:
for lens_tc in test_cases:
tc = float(meta["tc"] or 1)
testname = lens_id + "_" + lens_desc
testname = lens_tc["id"] + "_" + lens_tc["desc"]
globals()[testname] = system_tests.CaseMeta(
"canon_lenses." + testname,
@ -58,10 +57,10 @@ for (lens_id, lens_desc, meta) in lenses:
"stderr": [""],
"stdout": ["Exif.CanonCs.LensType Short 1 $lens_description\n"],
"retval": [0],
"lens_id": lens_id,
"lens_description": lens_desc,
"aperture_max": aperture_to_raw_exif(meta["aperture_max_short"]),
"focal_length_min": int(int(meta["focal_length_min"]) * tc),
"focal_length_max": int(int(meta["focal_length_max"]) * tc),
"lens_id": lens_tc["id"],
"lens_description": lens_tc["target"],
"aperture_max": aperture_to_raw_exif(lens_tc["aperture_max_short"]),
"focal_length_min": int(lens_tc["focal_length_min"] * lens_tc["tc"]),
"focal_length_max": int(lens_tc["focal_length_max"] * lens_tc["tc"]),
},
)

@ -1,6 +1,7 @@
import re
import os
import logging
from itertools import groupby
log = logging.getLogger(__name__)
@ -49,17 +50,54 @@ def extract_meta(text, pattern=LENS_META_DEFAULT_RE):
"""
result = pattern.match(text)
if(not result):
if not result:
# didn't match
return None
ret = result.groupdict()
# set min to max value if we didn't get a range but a single value
ret['focal_length_min'] = ret['focal_length_min'] or ret['focal_length_max']
ret['aperture_max_short'] = ret['aperture_max_short'] or ret['aperture_max_tele']
ret["focal_length_min"] = int(ret["focal_length_min"] or ret["focal_length_max"])
ret["focal_length_max"] = int(ret["focal_length_max"])
ret["aperture_max_short"] = float(ret["aperture_max_short"] or ret["aperture_max_tele"])
ret["aperture_max_tele"] = float(ret["aperture_max_tele"])
ret["tc"] = float(ret["tc"] or 1)
return ret
# FIXME explain somwhere that lens_is_match(l1,l2) does not imply lens_is_match(l2,l1)
# becuse we don't have short and tele aperture values in exif
def lens_is_match(l1, l2):
"""
Test if lens l2 is compatible with lens l1,
assuming we write l1's metadata and apeture_max_short into exif
"""
return (
all([l1[k] == l2[k] for k in ["tc", "focal_length_min", "focal_length_max"]])
and l2["aperture_max_short"] <= l1["aperture_max_short"] <= l2["aperture_max_tele"]
)
def make_test_cases(lenses):
"""
Creates a test case for each lens
Main job of this function is to collect all ambiguous lenses and define a test target
as the " *OR* " joined string of all ambiguous lens descriptions
"""
test_cases = []
for lens_id, group in groupby(lenses, lambda x: x["id"]):
lens_group = list(group)
test_cases += [
{
**lens["meta"],
"id": lens["id"],
"desc": lens["desc"],
"target": " *OR* ".join([l["desc"] for l in lens_group if lens_is_match(lens["meta"], l["meta"])]),
}
for lens in lens_group
]
return test_cases
def extract_lenses_from_cpp(filename, start_pattern):
"""
Extract lens information from the lens descritpions array in a maker note cpp file
@ -99,6 +137,5 @@ def extract_lenses_from_cpp(filename, start_pattern):
log.error(f"Failure extracing metadata from lens description: {lens_entry[0]}: {lens_entry[1]}.")
continue
lenses.append((*lens_entry, meta))
lenses.append({"id": lens_entry[0], "desc": lens_entry[1], "meta": meta})
return lenses

Loading…
Cancel
Save