From 92622fd0525b90fe15058b747091d37f7f743b5c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 29 Mar 2026 19:22:25 +0000 Subject: [PATCH 1/2] Add ImagePairsMerging Meshroom node Agent-Logs-Url: https://github.com/alicevision/AliceVision/sessions/8dfc9d40-98b6-47fb-a11a-a3ffdbf8a408 Co-authored-by: fabiencastan <153585+fabiencastan@users.noreply.github.com> --- meshroom/aliceVision/ImagePairsMerging.py | 78 +++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 meshroom/aliceVision/ImagePairsMerging.py diff --git a/meshroom/aliceVision/ImagePairsMerging.py b/meshroom/aliceVision/ImagePairsMerging.py new file mode 100644 index 0000000000..96637824b8 --- /dev/null +++ b/meshroom/aliceVision/ImagePairsMerging.py @@ -0,0 +1,78 @@ +__version__ = "1.0" + +from meshroom.core import desc +from meshroom.core.utils import VERBOSE_LEVEL + + +class ImagePairsMerging(desc.Node): + + category = "Utils" + documentation = """Merge multiple image pairs files into a single one.""" + + inputs = [ + desc.ListAttribute( + elementDesc=desc.File( + name="input", + label="Input Image Pairs File", + description="A file containing a list of image pairs.", + value="", + ), + name="inputs", + label="Inputs", + description="Set of image pairs files (at least 1 is required).", + exposed=True, + ), + desc.ChoiceParam( + name="verboseLevel", + label="Verbose Level", + description="Verbosity level (fatal, error, warning, info, debug, trace).", + values=VERBOSE_LEVEL, + value="info", + ), + ] + + outputs = [ + desc.File( + name="output", + label="Image Pairs", + description="Filepath to the output file with the merged list of image pairs.", + value="{nodeCacheFolder}/imageMatches.txt", + ), + ] + + def processChunk(self, chunk): + from pyalicevision import matchingImageCollection as mic + + try: + chunk.logManager.start(chunk.node.verboseLevel.value) + + inputFiles = [f.value for f in chunk.node.inputs.value if f.value] + + if not inputFiles: + error = "No input image pairs files provided." + chunk.logger.error(error) + raise RuntimeError(error) + + mergedPairs = mic.PairSet() + + for inputFile in inputFiles: + chunk.logger.info(f"Loading image pairs from: {inputFile}") + sizeBefore = len(mergedPairs) + if not mic.loadPairsFromFile(inputFile, mergedPairs): + error = f"Failed to load image pairs from file: {inputFile}" + chunk.logger.error(error) + raise RuntimeError(error) + chunk.logger.info(f"Loaded {len(mergedPairs) - sizeBefore} pairs from {inputFile}") + + chunk.logger.info(f"Total merged pairs: {len(mergedPairs)}") + chunk.logger.info(f"Saving merged image pairs to: {chunk.node.output.value}") + + if not mic.savePairsToFile(chunk.node.output.value, mergedPairs): + error = f"Failed to save merged image pairs to: {chunk.node.output.value}" + chunk.logger.error(error) + raise RuntimeError(error) + + chunk.logger.info("Image pairs merging done.") + + finally: + chunk.logManager.end() From 97864496a96ef85d0b51dcbf5891af1696b498a3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 18:22:17 +0000 Subject: [PATCH 2/2] Remove logManager and use logging module in ImagePairsMerging Agent-Logs-Url: https://github.com/alicevision/AliceVision/sessions/2dd3c226-4d10-4313-b9c3-ae99548e9f07 Co-authored-by: fabiencastan <153585+fabiencastan@users.noreply.github.com> --- meshroom/aliceVision/ImagePairsMerging.py | 49 +++++++++++------------ 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/meshroom/aliceVision/ImagePairsMerging.py b/meshroom/aliceVision/ImagePairsMerging.py index 96637824b8..8ffec5ed67 100644 --- a/meshroom/aliceVision/ImagePairsMerging.py +++ b/meshroom/aliceVision/ImagePairsMerging.py @@ -42,37 +42,34 @@ class ImagePairsMerging(desc.Node): def processChunk(self, chunk): from pyalicevision import matchingImageCollection as mic + import logging - try: - chunk.logManager.start(chunk.node.verboseLevel.value) + logging.getLogger().setLevel(chunk.node.verboseLevel.value.upper()) - inputFiles = [f.value for f in chunk.node.inputs.value if f.value] + inputFiles = [f.value for f in chunk.node.inputs.value if f.value] - if not inputFiles: - error = "No input image pairs files provided." - chunk.logger.error(error) - raise RuntimeError(error) - - mergedPairs = mic.PairSet() + if not inputFiles: + error = "No input image pairs files provided." + logging.error(error) + raise RuntimeError(error) - for inputFile in inputFiles: - chunk.logger.info(f"Loading image pairs from: {inputFile}") - sizeBefore = len(mergedPairs) - if not mic.loadPairsFromFile(inputFile, mergedPairs): - error = f"Failed to load image pairs from file: {inputFile}" - chunk.logger.error(error) - raise RuntimeError(error) - chunk.logger.info(f"Loaded {len(mergedPairs) - sizeBefore} pairs from {inputFile}") + mergedPairs = mic.PairSet() - chunk.logger.info(f"Total merged pairs: {len(mergedPairs)}") - chunk.logger.info(f"Saving merged image pairs to: {chunk.node.output.value}") - - if not mic.savePairsToFile(chunk.node.output.value, mergedPairs): - error = f"Failed to save merged image pairs to: {chunk.node.output.value}" - chunk.logger.error(error) + for inputFile in inputFiles: + logging.info(f"Loading image pairs from: {inputFile}") + sizeBefore = len(mergedPairs) + if not mic.loadPairsFromFile(inputFile, mergedPairs): + error = f"Failed to load image pairs from file: {inputFile}" + logging.error(error) raise RuntimeError(error) + logging.info(f"Loaded {len(mergedPairs) - sizeBefore} pairs from {inputFile}") + + logging.info(f"Total merged pairs: {len(mergedPairs)}") + logging.info(f"Saving merged image pairs to: {chunk.node.output.value}") - chunk.logger.info("Image pairs merging done.") + if not mic.savePairsToFile(chunk.node.output.value, mergedPairs): + error = f"Failed to save merged image pairs to: {chunk.node.output.value}" + logging.error(error) + raise RuntimeError(error) - finally: - chunk.logManager.end() + logging.info("Image pairs merging done.")