From 6ad3d612dbc00c4afce53f8b12e2a89fed8af124 Mon Sep 17 00:00:00 2001 From: Realcat Date: Sun, 7 Jul 2024 10:31:59 +0800 Subject: [PATCH] Dev (#41) * update: ci * update: download model from HF * update: ci * del: sgmnet * update: submodule sgmnet * update: ci * Remove submodule * update: ci * update: submodule darkfeat * update: submodule lanet --- .github/workflows/ci.yml | 32 +++++++++++++++++++++++++ .gitmodules | 12 +++++----- README.md | 1 + activate.sh | 6 +++++ common/config.yaml | 7 ++++++ env-docker.txt | 6 ++++- hloc/__init__.py | 3 ++- hloc/extractors/d2net.py | 3 ++- hloc/extractors/darkfeat.py | 25 +++++++------------- hloc/extractors/lanet.py | 23 +++++++++--------- hloc/extractors/r2d2.py | 2 +- hloc/extractors/rord.py | 28 ++++++++++++---------- hloc/extractors/sfd2.py | 9 +++---- hloc/matchers/aspanformer.py | 46 ++++++++++++------------------------ hloc/matchers/imp.py | 12 +++++----- hloc/matchers/sgmnet.py | 31 +++++++----------------- requirements.txt | 4 +++- test_app_cli.py | 7 +++--- third_party/ASpanFormer | 2 +- third_party/COTR | 2 +- third_party/DarkFeat | 2 +- third_party/DeDoDe | 2 +- third_party/GlueStick | 2 +- third_party/RoMa | 2 +- third_party/RoRD | 2 +- third_party/SGMNet | 2 +- third_party/SOLD2 | 2 +- third_party/d2net | 2 +- third_party/dust3r | 2 +- third_party/lanet | 2 +- third_party/omniglue | 2 +- 31 files changed, 152 insertions(+), 131 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 activate.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6818fc5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: CI_CPU + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install dependencies + run: | + pip install -r env-docker.txt + sudo apt-get update && sudo apt-get install ffmpeg libsm6 libxext6 -y + + - name: Run tests + run: python test_app_cli.py diff --git a/.gitmodules b/.gitmodules index f128b21..336af93 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,12 +25,6 @@ [submodule "third_party/LightGlue"] path = third_party/LightGlue url = https://github.com/cvg/LightGlue.git -[submodule "third_party/SGMNet"] - path = third_party/SGMNet - url = https://github.com/vdvchen/SGMNet.git -[submodule "third_party/DarkFeat"] - path = third_party/DarkFeat - url = https://github.com/THU-LYJ-Lab/DarkFeat.git [submodule "third_party/DeDoDe"] path = third_party/DeDoDe url = https://github.com/Parskatt/DeDoDe.git @@ -64,3 +58,9 @@ [submodule "third_party/pram"] path = third_party/pram url = https://github.com/feixue94/pram.git +[submodule "third_party/SGMNet"] + path = third_party/SGMNet + url = https://github.com/agipro/SGMNet.git +[submodule "third_party/DarkFeat"] + path = third_party/DarkFeat + url = https://github.com/agipro/DarkFeat.git diff --git a/README.md b/README.md index 94437e2..c789192 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ I provide an example to add local feature in [hloc/extractors/example.py](hloc/e External contributions are very much welcome. Please follow the [PEP8 style guidelines](https://www.python.org/dev/peps/pep-0008/) using a linter like flake8 (reformat using command `python -m black .`). This is a non-exhaustive list of features that might be valuable additions: +- [x] add [CPU CI](.github/workflows/ci.yml) - [x] add webcam support - [x] add [line feature matching](https://github.com/Vincentqyw/LineSegmentsDetection) algorithms - [x] example to add a new feature extractor / matcher diff --git a/activate.sh b/activate.sh new file mode 100644 index 0000000..4b04849 --- /dev/null +++ b/activate.sh @@ -0,0 +1,6 @@ +# download submodules +git submodule update --init --recursive + +# configuration envs +pip install -r env-docker.txt +sudo apt-get update && sudo apt-get install ffmpeg libsm6 libxext6 -y \ No newline at end of file diff --git a/common/config.yaml b/common/config.yaml index 9bb904c..b50682d 100644 --- a/common/config.yaml +++ b/common/config.yaml @@ -30,6 +30,7 @@ matcher_zoo: DUSt3R: # TODO: duster is under development enable: true + skip_ci: true matcher: duster dense: true info: @@ -41,6 +42,7 @@ matcher_zoo: display: true GIM(dkm): enable: true + skip_ci: true matcher: gim(dkm) dense: true info: @@ -52,6 +54,7 @@ matcher_zoo: display: true RoMa: matcher: roma + skip_ci: true dense: true info: name: RoMa #dispaly name @@ -62,6 +65,7 @@ matcher_zoo: display: true dkm: matcher: dkm + skip_ci: true dense: true info: name: DKM #dispaly name @@ -82,6 +86,7 @@ matcher_zoo: display: true cotr: enable: false + skip_ci: true matcher: cotr dense: true info: @@ -368,6 +373,7 @@ matcher_zoo: matcher: imp feature: sfd2 dense: false + skip_ci: true info: name: SFD2+IMP #dispaly name source: "CVPR 2023" @@ -380,6 +386,7 @@ matcher_zoo: matcher: NN-mutual feature: sfd2 dense: false + skip_ci: true info: name: SFD2+MNN #dispaly name source: "CVPR 2023" diff --git a/env-docker.txt b/env-docker.txt index 27f41ae..b2ef6bc 100644 --- a/env-docker.txt +++ b/env-docker.txt @@ -30,4 +30,8 @@ torchmetrics==0.6.0 torchvision==0.17.1 tqdm==4.65.0 yacs==0.1.8 -onnxruntime \ No newline at end of file +onnxruntime +poselib +roma +huggingface_hub +psutil \ No newline at end of file diff --git a/hloc/__init__.py b/hloc/__init__.py index b7f35f4..bfe28b5 100644 --- a/hloc/__init__.py +++ b/hloc/__init__.py @@ -1,5 +1,6 @@ import logging from packaging import version +import torch __version__ = "1.3" @@ -30,4 +31,4 @@ minimal_version, found_version, ) -checkpoints_hub = "https://huggingface.co/spaces/Realcat/image-matching-webui/resolve/main/third_party" \ No newline at end of file +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") \ No newline at end of file diff --git a/hloc/extractors/d2net.py b/hloc/extractors/d2net.py index 8c8b6bc..7d2a549 100644 --- a/hloc/extractors/d2net.py +++ b/hloc/extractors/d2net.py @@ -11,6 +11,7 @@ from lib.model_test import D2Net as _D2Net from lib.pyramid import process_multiscale + class D2Net(BaseModel): default_conf = { "model_name": "d2_tf.pth", @@ -61,4 +62,4 @@ def _forward(self, data): "keypoints": torch.from_numpy(keypoints)[None], "scores": torch.from_numpy(scores)[None], "descriptors": torch.from_numpy(descriptors.T)[None], - } \ No newline at end of file + } diff --git a/hloc/extractors/darkfeat.py b/hloc/extractors/darkfeat.py index 2e461e7..11f2edb 100644 --- a/hloc/extractors/darkfeat.py +++ b/hloc/extractors/darkfeat.py @@ -1,6 +1,7 @@ import sys from pathlib import Path import subprocess +from huggingface_hub import hf_hub_download from ..utils.base_model import BaseModel from hloc import logger @@ -25,24 +26,14 @@ class DarkFeat(BaseModel): def _init(self, conf): model_path = darkfeat_path / "checkpoints" / conf["model_name"] link = self.weight_urls[conf["model_name"]] - if not model_path.exists(): - model_path.parent.mkdir(exist_ok=True) - cmd_wo_proxy = ["gdown", link, "-O", str(model_path)] - cmd = ["gdown", link, "-O", str(model_path), "--proxy", self.proxy] - logger.info( - f"Downloading the DarkFeat model with `{cmd_wo_proxy}`." - ) - try: - subprocess.run(cmd_wo_proxy, check=True) - except subprocess.CalledProcessError as e: - logger.info(f"Downloading the DarkFeat model with `{cmd}`.") - try: - subprocess.run(cmd, check=True) - except subprocess.CalledProcessError as e: - logger.error(f"Failed to download the DarkFeat model.") - raise e - self.net = DarkFeat_(model_path) + cached_file = hf_hub_download( + repo_type="space", + repo_id="Realcat/image-matching-webui", + filename="third_party/DarkFeat/checkpoints/DarkFeat.pth", + ) + + self.net = DarkFeat_(cached_file) logger.info(f"Load DarkFeat model done.") def _forward(self, data): diff --git a/hloc/extractors/lanet.py b/hloc/extractors/lanet.py index fe0ed90..d93e507 100644 --- a/hloc/extractors/lanet.py +++ b/hloc/extractors/lanet.py @@ -2,12 +2,13 @@ from pathlib import Path import torch import subprocess -from hloc import logger, checkpoints_hub +from huggingface_hub import hf_hub_download from ..utils.base_model import BaseModel - +from hloc import logger lib_path = Path(__file__).parent / "../../third_party" sys.path.append(str(lib_path)) from lanet.network_v0.model import PointModel + lanet_path = Path(__file__).parent / "../../third_party/lanet" device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -27,16 +28,16 @@ def _init(self, conf): ) if not model_path.exists(): logger.warning(f"No model found at {model_path}, start downloading") - model_link = "{}/lanet/checkpoints/{}".format( - checkpoints_hub, f'PointModel_{conf["model_name"]}.pth' - ) model_path.parent.mkdir(exist_ok=True) - cmd = [ - "wget", - model_link, - "-O", - str(model_path), - ] + cached_file = hf_hub_download( + repo_type="space", + repo_id="Realcat/image-matching-webui", + filename="third_party/lanet/checkpoints/PointModel_{}.pth".format( + conf["model_name"] + ), + ) + cmd = ["cp", str(cached_file), str(model_path.parent)] + logger.info(f"copy model file `{cmd}`.") subprocess.run(cmd, check=True) self.net = PointModel(is_test=True) diff --git a/hloc/extractors/r2d2.py b/hloc/extractors/r2d2.py index e66527f..df10320 100644 --- a/hloc/extractors/r2d2.py +++ b/hloc/extractors/r2d2.py @@ -1,7 +1,7 @@ import sys from pathlib import Path import torchvision.transforms as tvf - +from hloc import logger from ..utils.base_model import BaseModel r2d2_path = Path(__file__).parent / "../../third_party/r2d2" diff --git a/hloc/extractors/rord.py b/hloc/extractors/rord.py index d7c3f36..582c247 100644 --- a/hloc/extractors/rord.py +++ b/hloc/extractors/rord.py @@ -2,6 +2,7 @@ from pathlib import Path import subprocess import torch +from huggingface_hub import hf_hub_download from ..utils.base_model import BaseModel from hloc import logger @@ -29,20 +30,23 @@ class RoRD(BaseModel): def _init(self, conf): model_path = conf["checkpoint_dir"] / conf["model_name"] link = self.weight_urls[conf["model_name"]] + if not model_path.exists(): model_path.parent.mkdir(exist_ok=True) - cmd_wo_proxy = ["gdown", link, "-O", str(model_path)] - cmd = ["gdown", link, "-O", str(model_path), "--proxy", self.proxy] - logger.info(f"Downloading the RoRD model with `{cmd_wo_proxy}`.") - try: - subprocess.run(cmd_wo_proxy, check=True) - except subprocess.CalledProcessError as e: - logger.info(f"Downloading the RoRD model with `{cmd}`.") - try: - subprocess.run(cmd, check=True) - except subprocess.CalledProcessError as e: - logger.error(f"Failed to download the RoRD model.") - raise e + cached_file_0 = hf_hub_download( + repo_type="space", + repo_id="Realcat/image-matching-webui", + filename="third_party/RoRD/models/d2net.pth", + ) + cached_file_1 = hf_hub_download( + repo_type="space", + repo_id="Realcat/image-matching-webui", + filename="third_party/RoRD/models/rord.pth", + ) + + subprocess.run(["cp", cached_file_0, model_path], check=True) + subprocess.run(["cp", cached_file_1, model_path], check=True) + self.net = _RoRD( model_file=model_path, use_relu=conf["use_relu"], use_cuda=False ) diff --git a/hloc/extractors/sfd2.py b/hloc/extractors/sfd2.py index 4039b38..e4eb2a5 100644 --- a/hloc/extractors/sfd2.py +++ b/hloc/extractors/sfd2.py @@ -17,9 +17,8 @@ class SFD2(BaseModel): default_conf = { "max_keypoints": 4096, - "model_name": 'sfd2_20230511_210205_resnet4x.79.pth', + "model_name": "sfd2_20230511_210205_resnet4x.79.pth", "conf_th": 0.001, - } required_inputs = ["image"] @@ -28,13 +27,15 @@ def _init(self, conf): self.norm_rgb = tvf.Normalize( mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] ) - model_fn = pram_path / 'weights' / self.conf['model_name'] + model_fn = pram_path / "weights" / self.conf["model_name"] self.net = load_sfd2(weight_path=model_fn).cuda().eval() logger.info(f"Load SFD2 model done.") def _forward(self, data): - pred = self.net.extract_local_global(data={'image': self.norm_rgb(data['image'])}, config=self.conf) + pred = self.net.extract_local_global( + data={"image": self.norm_rgb(data["image"])}, config=self.conf + ) out = { "keypoints": pred["keypoints"][0][None], "scores": pred["scores"][0][None], diff --git a/hloc/matchers/aspanformer.py b/hloc/matchers/aspanformer.py index c242091..3864340 100644 --- a/hloc/matchers/aspanformer.py +++ b/hloc/matchers/aspanformer.py @@ -4,6 +4,7 @@ from ..utils import do_system from pathlib import Path import subprocess +from huggingface_hub import hf_hub_download from .. import logger @@ -37,37 +38,20 @@ def _init(self, conf): ) # Download the model. if not model_path.exists(): - # model_path.parent.mkdir(exist_ok=True) - tar_path = aspanformer_path / conf["model_name"] - if not tar_path.exists(): - link = self.aspanformer_models[conf["model_name"]] - cmd = [ - "gdown", - link, - "-O", - str(tar_path), - "--proxy", - self.proxy, - ] - cmd_wo_proxy = ["gdown", link, "-O", str(tar_path)] - logger.info( - f"Downloading the Aspanformer model with `{cmd_wo_proxy}`." - ) - try: - subprocess.run(cmd_wo_proxy, check=True) - except subprocess.CalledProcessError as e: - logger.info( - f"Downloading the Aspanformer model with `{cmd}`." - ) - try: - subprocess.run(cmd, check=True) - except subprocess.CalledProcessError as e: - logger.error( - f"Failed to download the Aspanformer model." - ) - raise e - - do_system(f"cd {str(aspanformer_path)} & tar -xvf {str(tar_path)}") + cached_file = hf_hub_download( + repo_type="space", + repo_id="Realcat/image-matching-webui", + filename="third_party/ASpanFormer/weights_aspanformer.tar", + ) + cmd = [ + "tar", + "-xvf", + str(cached_file), + "-C", + str(aspanformer_path / "weights"), + ] + logger.info(f"Unzip model file `{cmd}`.") + subprocess.run(cmd, check=True) config = get_cfg_defaults() config.merge_from_file(conf["config_path"]) diff --git a/hloc/matchers/imp.py b/hloc/matchers/imp.py index 7e4ef0a..adb6816 100644 --- a/hloc/matchers/imp.py +++ b/hloc/matchers/imp.py @@ -5,7 +5,7 @@ import torch from ..utils.base_model import BaseModel -from .. import logger +from .. import logger, device pram_path = Path(__file__).parent / "../../third_party/pram" sys.path.append(str(pram_path)) @@ -18,7 +18,7 @@ class IMP(BaseModel): "match_threshold": 0.2, "features": "sfd2", "model_name": "imp_gml.920.pth", - 'sinkhorn_iterations': 20, + "sinkhorn_iterations": 20, } required_inputs = [ "image0", @@ -34,12 +34,12 @@ class IMP(BaseModel): def _init(self, conf): self.conf = {**self.default_conf, **conf} weight_path = pram_path / "weights" / self.conf["model_name"] - self.net = GML(self.conf).eval().cuda() - self.net.load_state_dict(torch.load(weight_path)['model'], strict=True) + self.net = GML(self.conf).eval().to(device) + self.net.load_state_dict(torch.load(weight_path)["model"], strict=True) logger.info(f"Load IMP model done.") def _forward(self, data): - data['descriptors0'] = data['descriptors0'].transpose(2, 1).float() - data['descriptors1'] = data['descriptors1'].transpose(2, 1).float() + data["descriptors0"] = data["descriptors0"].transpose(2, 1).float() + data["descriptors1"] = data["descriptors1"].transpose(2, 1).float() return self.net.produce_matches(data, p=0.2) diff --git a/hloc/matchers/sgmnet.py b/hloc/matchers/sgmnet.py index 7931a6b..c138965 100644 --- a/hloc/matchers/sgmnet.py +++ b/hloc/matchers/sgmnet.py @@ -4,6 +4,7 @@ import torch from PIL import Image from collections import OrderedDict, namedtuple +from huggingface_hub import hf_hub_download from ..utils.base_model import BaseModel from .. import logger @@ -47,31 +48,15 @@ def _init(self, conf): link = self.weight_urls[conf["model_name"]] tar_path = sgmnet_path / "weights.tar.gz" + # Download the model. if not sgmnet_weights.exists(): - if not tar_path.exists(): - cmd = [ - "gdown", - link, - "-O", - str(tar_path), - "--proxy", - self.proxy, - ] - cmd_wo_proxy = ["gdown", link, "-O", str(tar_path)] - logger.info( - f"Downloading the SGMNet model with `{cmd_wo_proxy}`." - ) - try: - subprocess.run(cmd_wo_proxy, check=True) - except subprocess.CalledProcessError as e: - logger.info(f"Downloading the SGMNet model with `{cmd}`.") - try: - subprocess.run(cmd, check=True) - except subprocess.CalledProcessError as e: - logger.error(f"Failed to download the SGMNet model.") - raise e - cmd = ["tar", "-xvf", str(tar_path), "-C", str(sgmnet_path)] + cached_file = hf_hub_download( + repo_type="space", + repo_id="Realcat/image-matching-webui", + filename="third_party/SGMNet/weights.tar.gz", + ) + cmd = ["tar", "-xvf", str(cached_file), "-C", str(sgmnet_path)] logger.info(f"Unzip model file `{cmd}`.") subprocess.run(cmd, check=True) diff --git a/requirements.txt b/requirements.txt index 4745b74..af9473a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,4 +17,6 @@ loguru==0.7.0 e2cnn==0.2.3 onnxruntime poselib -roma \ No newline at end of file +roma +huggingface_hub +psutil \ No newline at end of file diff --git a/test_app_cli.py b/test_app_cli.py index 9329bc0..e3e30b6 100644 --- a/test_app_cli.py +++ b/test_app_cli.py @@ -23,7 +23,8 @@ def test_all(config: dict = None): if image0 is None or image1 is None: logger.error("Error: No images found! Please upload two images.") enable = config["matcher_zoo"][k].get("enable", True) - if enable: + skip_ci = config["matcher_zoo"][k].get("skip_ci", False) + if enable and not skip_ci: logger.info(f"Testing {k} ...") api = ImageMatchingAPI(conf=v, device=device) api(image0, image1) @@ -32,6 +33,7 @@ def test_all(config: dict = None): api.visualize(log_path=log_path) else: logger.info(f"Skipping {k} ...") + return 0 def test_one(): @@ -103,11 +105,10 @@ def test_one(): log_path = ROOT / "experiments" / "one" log_path.mkdir(exist_ok=True, parents=True) api.visualize(log_path=log_path) + return 0 if __name__ == "__main__": - import argparse - config = load_config(ROOT / "common/config.yaml") test_one() test_all(config) diff --git a/third_party/ASpanFormer b/third_party/ASpanFormer index 29be52d..f87b1e5 160000 --- a/third_party/ASpanFormer +++ b/third_party/ASpanFormer @@ -1 +1 @@ -Subproject commit 29be52d6c4b0136b7e533fc5dd455efecb77d9f2 +Subproject commit f87b1e59bbbf729ad0d8d30fb0cfa27e9bf8d14b diff --git a/third_party/COTR b/third_party/COTR index f673d74..2a5025b 160000 --- a/third_party/COTR +++ b/third_party/COTR @@ -1 +1 @@ -Subproject commit f673d74d5227600d72af4cc8eac3f3a837156c7f +Subproject commit 2a5025b6737c1586fd9879cec44aba5b1a6c4451 diff --git a/third_party/DarkFeat b/third_party/DarkFeat index 443ae61..60e296e 160000 --- a/third_party/DarkFeat +++ b/third_party/DarkFeat @@ -1 +1 @@ -Subproject commit 443ae61caf139156f4247dfd11834552565d6021 +Subproject commit 60e296eb7705ed473cdaae70b150e4432862c517 diff --git a/third_party/DeDoDe b/third_party/DeDoDe index fe5991e..0928deb 160000 --- a/third_party/DeDoDe +++ b/third_party/DeDoDe @@ -1 +1 @@ -Subproject commit fe5991ee3b79ab6c30172c92f0e69b7b003df621 +Subproject commit 0928debd09de6e814c90647a639a7219437bf49a diff --git a/third_party/GlueStick b/third_party/GlueStick index 56a1350..2f54613 160000 --- a/third_party/GlueStick +++ b/third_party/GlueStick @@ -1 +1 @@ -Subproject commit 56a13507ca128f4be280c787a0dcd0095db8b45f +Subproject commit 2f546130de35ab962ee12239ec55b457bed32edc diff --git a/third_party/RoMa b/third_party/RoMa index 116537a..97d6254 160000 --- a/third_party/RoMa +++ b/third_party/RoMa @@ -1 +1 @@ -Subproject commit 116537a1849f26b1ecf8e1b7ac0980a51befdc07 +Subproject commit 97d62548a365a5828ad9bd171af1ed93f627569a diff --git a/third_party/RoRD b/third_party/RoRD index 7d52d71..0f23320 160000 --- a/third_party/RoRD +++ b/third_party/RoRD @@ -1 +1 @@ -Subproject commit 7d52d71768d564021a61223d10c7054a395845bc +Subproject commit 0f2332045a027a42b00f1b771ef200698791d9ce diff --git a/third_party/SGMNet b/third_party/SGMNet index 52a1ebe..7a9fefc 160000 --- a/third_party/SGMNet +++ b/third_party/SGMNet @@ -1 +1 @@ -Subproject commit 52a1ebebb33b4ba952f95d239d25e600b5b8d989 +Subproject commit 7a9fefc2b07cfa89406e78f68c66a9ad586cacee diff --git a/third_party/SOLD2 b/third_party/SOLD2 index 525dcd4..b2e49f2 160000 --- a/third_party/SOLD2 +++ b/third_party/SOLD2 @@ -1 +1 @@ -Subproject commit 525dcd42134cc5981fbe8491d80cd4914b89ddec +Subproject commit b2e49f24511afe7f910d7e8f0623902c6b00dc6c diff --git a/third_party/d2net b/third_party/d2net index 318795f..688d3e0 160000 --- a/third_party/d2net +++ b/third_party/d2net @@ -1 +1 @@ -Subproject commit 318795fbc7a83d6dafda3faa9562cd6499dcd19c +Subproject commit 688d3e049a4679749f6a9941f7da00b297adbf8f diff --git a/third_party/dust3r b/third_party/dust3r index 01b2f1d..c267f72 160000 --- a/third_party/dust3r +++ b/third_party/dust3r @@ -1 +1 @@ -Subproject commit 01b2f1d1e6c6c386f95a007406defb5b8a5d2042 +Subproject commit c267f72ba845108be1d2bd5ea98c641f2835cbc7 diff --git a/third_party/lanet b/third_party/lanet index 9e02ced..99435f2 160000 --- a/third_party/lanet +++ b/third_party/lanet @@ -1 +1 @@ -Subproject commit 9e02ced98b6c5978affc0dc172785c8bb33a1ecb +Subproject commit 99435f2136ef75ca50c3e2b42f6b24928a10c5c2 diff --git a/third_party/omniglue b/third_party/omniglue index 7c24906..5ddeeb9 160000 --- a/third_party/omniglue +++ b/third_party/omniglue @@ -1 +1 @@ -Subproject commit 7c249062235eebf7d8815985ec0817ffd71b2626 +Subproject commit 5ddeeb930626f01105b8cb887879522f91c85477