Skip to content

Commit

Permalink
test for two_calibration tags
Browse files Browse the repository at this point in the history
fix #111
  • Loading branch information
HowcanoeWang committed May 21, 2024
1 parent 2af7776 commit b16fa09
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 21 deletions.
4 changes: 4 additions & 0 deletions easyidp/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ def __init__(self, test_out="./tests/out"):
* ``.metashape.wheat_param``
* ``.metashape.multichunk_psx``
* ``.metashape.multichunk_param``
* ``.metashape.two_calib``
**pix4d test module**
Expand Down Expand Up @@ -564,6 +565,9 @@ def __init__(self, data_dir, test_out):
self.camera_disorder_psx = data_dir / "metashape" / "camera_disorder.psx"
self.camera_disorder_param = data_dir / "metashape" / "camera_disorder.files"

self.two_calib_psx = data_dir / "metashape" / "two_calib.psx"
self.two_calib_param = data_dir / "metashape" / "two_calib.files"


class Pix4Dataset():

Expand Down
53 changes: 35 additions & 18 deletions easyidp/metashape.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,11 @@ def _open_whole_project(self, project_path):

chunk_id2label = {}
label2chunk_id = {}
remove_chunk_id = []
for chunk_id in project_dict.keys():
chunk_dict = read_chunk_zip(folder_path, project_name, chunk_id, return_label_only=True)

if chunk_dict['enabled']:
if chunk_dict and chunk_dict['enabled']:
lb = chunk_dict['label']
lb_len = len(lb)
# judge if two chunks have the same label
Expand All @@ -298,6 +299,11 @@ def _open_whole_project(self, project_path):
chunk_id2label[chunk_id] = lb
label2chunk_id[lb] = chunk_id
else: # ignore the disabled chunk.
remove_chunk_id.append(chunk_id)
continue

if len(remove_chunk_id) > 0:
for chunk_id in remove_chunk_id:
project_dict.pop(chunk_id)

# open the first chunk if chunk_id not given.
Expand All @@ -309,12 +315,14 @@ def _open_whole_project(self, project_path):
f"[{first_chunk_id}] '{chunk_id2label[first_chunk_id]}', "
f"ignore the wrong chunk_id [{self.chunk_id}] specified by user.")
self.chunk_id = first_chunk_id
else: # has multiple chunks
elif len(project_dict) > 1: # has multiple chunks
if self.chunk_id is None:
warnings.warn(
f"The project has [{len(project_dict)}] chunks, however no chunk_id has been specified, "
f"open the first chunk [{first_chunk_id}] '{chunk_id2label[first_chunk_id]}' by default.")
self.chunk_id = first_chunk_id
else: # has zero chunk available
raise IndexError(f"Metashape project has no chunk folder (e.g. './0/', './1/') at [{folder_path}/{project_name}.files]")

# save to project parameters
self.project_folder = folder_path
Expand Down Expand Up @@ -1195,6 +1203,11 @@ def read_chunk_zip(project_folder, project_name, chunk_id, skip_disabled=False,
"""
frame_zip_file = f"{project_folder}/{project_name}.files/{chunk_id}/chunk.zip"
# for test data, some metashape projects are not complete, then skip and return None
if not os.path.exists(frame_zip_file):
print(f'[Warning] Metashape project {project_folder} Chunk {chunk_id} folder missing')
return None

xml_str = _get_xml_str_from_zip_file(frame_zip_file, "doc.xml")
xml_tree = ElementTree.fromstring(xml_str)

Expand Down Expand Up @@ -1573,27 +1586,31 @@ def _decode_sensor_tag(xml_obj, debug_meta={}):
sensor.pixel_height_unit = "mm"
sensor.focal_length = float(xml_obj.findall("./property/[@name='focal_length']")[0].attrib["value"])

calib_tag = xml_obj.findall("./calibration")
if len(calib_tag) != 1:
# load the debug info
if len(debug_meta) == 0: # not specify input
debug_meta = {
"project_folder": 'project_folder',
"project_name" : 'project_name',
"chunk_id": 'chunk_id',
"chunk_path": 'chunk_id/chunk.zip'
}
calib_tags = xml_obj.findall("./calibration")

# check if has <calibration type="frame" class="adjusted"> tag
has_adjusted_tag = False
for c in calib_tags:
if c.attrib['class'] == 'adjusted':
has_adjusted_tag = True
sensor.calibration = _decode_calibration_tag(c)
sensor.calibration.sensor = sensor
break

if len(calib_tags) != 1:
if has_adjusted_tag:
warnings.warn(f'Detect {len(calib_tags)} <calibration> tags in <sensor label={sensor.label}> tag, using <calibration class="adjusted">')


if not has_adjusted_tag:
xml_str = minidom.parseString(ElementTree.tostring(xml_obj)).toprettyxml(indent=" ")
# remove the first line <?xml version="1.0" ?> and empty lines
xml_str = os.linesep.join([s for s in xml_str.splitlines() if s.strip() and '?xml version=' not in s])
warnings.warn(f"The sensor tag in [{debug_meta['chunk_path']}] has {len(calib_tag)} <calibration> tags, but expected 1\n"
f"\n{xml_str}\n\nThis may cause by importing photos but delete them before align processing in metashape, "
f"and leave the 'ghost' empty sensor tag, this is just a warning and should have no effect to you")
warnings.warn(
f'No expected <calibration class="adjusted"> tag found in <sensor label={sensor.label}> tag\n'
f'Problemed XML tags for debugging reference: \n{xml_str}\n')

sensor.calibration = None
else:
sensor.calibration = _decode_calibration_tag(xml_obj.findall("./calibration")[0])
sensor.calibration.sensor = sensor

return sensor

Expand Down
45 changes: 42 additions & 3 deletions tests/test_metashape.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ def test_class_init_metashape_multi_folder():
assert ms.photos[0].label == "[0]100MEDIA-DJI_0001"
assert len(ms.photos) == 218


def test_class_init_metashape_warns_errors():
# warning init with chunk_id without project_path
with pytest.warns(UserWarning, match=re.escape("Unable to open chunk_id [0] for empty project with project_path=None")):
Expand Down Expand Up @@ -189,6 +188,13 @@ def test_class_init_metashape_warns_errors():
roi = idp.ROI()
roi['plot1'] = plot
m5.back2raw(roi)


def test_class_init_metashape_with_missing_chunk_folders():
m6 = idp.Metashape(project_path=test_data.metashape.two_calib_psx)
assert len(m6._chunk_id2label) == 1
assert '0' in m6._chunk_id2label.keys()
assert 'RGB_230923_20m' in m6._chunk_id2label.values()


def test_class_fetch_by_label():
Expand Down Expand Up @@ -582,7 +588,7 @@ def test_debug_calibration_tag_error():
for i, sensor_tag in enumerate(sensors_search):

if i == 0:
with pytest.warns(UserWarning, match=re.escape("The sensor tag in [chunk_id/chunk.zip] has 0 <calibration> tags")):
with pytest.warns(UserWarning, match=re.escape('No expected <calibration class="adjusted"> tag found in <sensor label=Test_Pro (10.26mm)> tag')):
sensor = idp.metashape._decode_sensor_tag(sensor_tag)

assert sensor.calibration is None
Expand Down Expand Up @@ -707,4 +713,37 @@ def test_metashape_disordered_image_xml():

assert ms.photos[0].label == "80m/e-w/card01/100MEDIA/DJI_0001.JPG"

assert ms.photos[1].label == '80m/e-w/card01/101MEDIA/DJI_0538.JPG'
assert ms.photos[1].label == '80m/e-w/card01/101MEDIA/DJI_0538.JPG'


def test_parse_sensor_tags_with_multiple_calibration():
"""
<calibration type="frame" class="initial">
<resolution width="5280" height="3956"/>
<f>3713.29</f>
<cx>7.0199999999999996</cx>
<cy>-8.7200000000000006</cy>
<k1>-0.11257523999999999</k1>
<k2>0.014874429999999999</k2>
<k3>-0.027064109999999999</k3>
<p1>9.9999999999999995e-08</p1>
<p2>-8.5719999999999999e-05</p2>
</calibration>
<calibration type="frame" class="adjusted">
<resolution width="5280" height="3956"/>
<f>4758.8543529678982</f>
<cx>14.842273128715597</cx>
<cy>-2.8329842300848433</cy>
<k1>-0.15762331681570707</k1>
<k2>-0.16432342601626651</k2>
<k3>0.43042327353025245</k3>
<k4>-0.49918757322065133</k4>
<p1>-0.0012357946245061236</p1>
<p2>-0.0011496526754087306</p2>
</calibration>
"""
with pytest.warns(UserWarning, match=re.escape('Detect 2 <calibration> tags in <sensor label=M3M (12.29mm)> tag, using <calibration class="adjusted">')):
m6 = idp.Metashape(project_path=test_data.metashape.two_calib_psx)

assert m6.sensors[0].calibration.f == 4758.8543529678982
assert m6.sensors[0].calibration.cx == 14.842273128715597

0 comments on commit b16fa09

Please sign in to comment.