mapreader 1.2.0__tar.gz → 1.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mapreader-1.2.0 → mapreader-1.3.1}/PKG-INFO +1 -1
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/__init__.py +10 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/_version.py +3 -3
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/download/sheet_downloader.py +73 -26
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/download/tile_merging.py +22 -8
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/load/images.py +1 -1
- mapreader-1.3.1/mapreader/spot_text/deepsolo_runner.py +643 -0
- mapreader-1.3.1/mapreader/spot_text/dptext_detr_runner.py +434 -0
- mapreader-1.3.1/mapreader/utils/__init__.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader.egg-info/PKG-INFO +1 -1
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader.egg-info/SOURCES.txt +3 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/tests/test_sheet_downloader.py +158 -51
- {mapreader-1.2.0 → mapreader-1.3.1}/LICENSE +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/README.md +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/annotate/__init__.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/annotate/annotator.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/annotate/utils.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/classify/__init__.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/classify/classifier.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/classify/custom_models.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/classify/datasets.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/classify/load_annotations.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/download/__init__.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/download/data_structures.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/download/downloader.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/download/downloader_utils.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/download/tile_loading.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/load/__init__.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/load/geo_utils.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/load/loader.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/process/__init__.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/process/post_process.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/process/process.py +0 -0
- {mapreader-1.2.0/mapreader/utils → mapreader-1.3.1/mapreader/spot_text}/__init__.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/utils/compute_and_save_stats.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader/utils/slice_parallel.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader.egg-info/dependency_links.txt +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader.egg-info/entry_points.txt +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader.egg-info/not-zip-safe +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader.egg-info/requires.txt +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/mapreader.egg-info/top_level.txt +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/setup.cfg +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/setup.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/tests/test_annotator.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/tests/test_geo_pipeline.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/tests/test_import.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/tests/test_post_processing.py +0 -0
- {mapreader-1.2.0 → mapreader-1.3.1}/versioneer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mapreader
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: A computer vision pipeline for the semantic exploration of maps/images at scale
|
|
5
5
|
Home-page: https://github.com/Living-with-machines/MapReader
|
|
6
6
|
Download-URL: https://github.com/Living-with-machines/MapReader/archive/refs/heads/main.zip
|
|
@@ -12,6 +12,16 @@ from mapreader.classify.datasets import PatchContextDataset
|
|
|
12
12
|
from mapreader.classify.classifier import ClassifierContainer
|
|
13
13
|
from mapreader.classify import custom_models
|
|
14
14
|
|
|
15
|
+
try:
|
|
16
|
+
from mapreader.spot_text.deepsolo_runner import DeepSoloRunner
|
|
17
|
+
except ImportError:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from mapreader.spot_text.dptext_detr_runner import DPTextDETRRunner
|
|
22
|
+
except ImportError:
|
|
23
|
+
pass
|
|
24
|
+
|
|
15
25
|
from mapreader.process import process
|
|
16
26
|
|
|
17
27
|
from mapreader.annotate.annotator import Annotator
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2024-
|
|
11
|
+
"date": "2024-05-03T13:32:40+0100",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "1.
|
|
14
|
+
"full-revisionid": "3d7ab10b0f7bc0833e122a65a4d4bd608ca62fcd",
|
|
15
|
+
"version": "1.3.1"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -533,7 +533,7 @@ class SheetDownloader:
|
|
|
533
533
|
"""
|
|
534
534
|
self.merger = TileMerger(output_folder=f"{path_save}/")
|
|
535
535
|
|
|
536
|
-
def _check_map_sheet_exists(self, feature: dict) -> bool:
|
|
536
|
+
def _check_map_sheet_exists(self, feature: dict, metadata_fname) -> bool:
|
|
537
537
|
"""
|
|
538
538
|
Checks if a map sheet is already saved.
|
|
539
539
|
|
|
@@ -544,51 +544,87 @@ class SheetDownloader:
|
|
|
544
544
|
Returns
|
|
545
545
|
-------
|
|
546
546
|
bool
|
|
547
|
-
|
|
547
|
+
img_path if file exists, False if not.
|
|
548
548
|
"""
|
|
549
|
-
map_name = str("map_" + feature["properties"]["IMAGE"])
|
|
550
549
|
path_save = self.merger.output_folder
|
|
551
|
-
|
|
550
|
+
|
|
551
|
+
try:
|
|
552
|
+
# get image id with same coords in metadata
|
|
553
|
+
existing_metadata_df = pd.read_csv(
|
|
554
|
+
f"{path_save}{metadata_fname}", sep=",", index_col=0
|
|
555
|
+
)
|
|
556
|
+
except FileNotFoundError:
|
|
557
|
+
return False
|
|
558
|
+
|
|
559
|
+
polygon = get_polygon_from_grid_bb(feature["grid_bb"])
|
|
560
|
+
if str(polygon.bounds) in existing_metadata_df["coordinates"].values:
|
|
561
|
+
image_id = existing_metadata_df[
|
|
562
|
+
existing_metadata_df["coordinates"] == str(polygon.bounds)
|
|
563
|
+
].iloc[0]["name"]
|
|
564
|
+
else:
|
|
565
|
+
return False # coordinates not in metadata means image doesn't exist
|
|
566
|
+
|
|
567
|
+
if os.path.exists(f"{path_save}{image_id}"):
|
|
552
568
|
try:
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
)
|
|
557
|
-
return True
|
|
569
|
+
# check image is valid
|
|
570
|
+
mpimg.imread(f"{path_save}{image_id}")
|
|
571
|
+
return image_id
|
|
558
572
|
except OSError:
|
|
559
573
|
return False
|
|
560
574
|
return False
|
|
561
575
|
|
|
562
|
-
def _download_map(
|
|
576
|
+
def _download_map(
|
|
577
|
+
self,
|
|
578
|
+
feature: dict,
|
|
579
|
+
existing_id: str | bool,
|
|
580
|
+
download_in_parallel: bool = True,
|
|
581
|
+
overwrite: bool = False,
|
|
582
|
+
) -> str | bool:
|
|
563
583
|
"""
|
|
564
584
|
Downloads a single map sheet and saves as png file.
|
|
565
585
|
|
|
566
586
|
Parameters
|
|
567
587
|
----------
|
|
568
588
|
feature : dict
|
|
589
|
+
The feature for which to download the map sheet.
|
|
590
|
+
existing_id : str | bool
|
|
591
|
+
The existing image id if the map sheet already exists.
|
|
592
|
+
download_in_parallel : bool, optional
|
|
593
|
+
Whether to download tiles in parallel, by default ``True``.
|
|
594
|
+
overwrite : bool, optional
|
|
595
|
+
Whether to overwrite existing maps, by default ``False``.
|
|
569
596
|
|
|
570
597
|
Returns
|
|
571
598
|
-------
|
|
572
|
-
bool
|
|
573
|
-
|
|
599
|
+
str or bool
|
|
600
|
+
image path if map was downloaded successfully, False if not.
|
|
574
601
|
"""
|
|
575
|
-
map_name = str("map_" + feature["properties"]["IMAGE"])
|
|
576
602
|
self.downloader.download_tiles(
|
|
577
603
|
feature["grid_bb"], download_in_parallel=download_in_parallel
|
|
578
604
|
)
|
|
579
|
-
|
|
580
|
-
if
|
|
581
|
-
|
|
605
|
+
|
|
606
|
+
if existing_id is False:
|
|
607
|
+
map_name = f"map_{feature['properties']['IMAGE']}"
|
|
608
|
+
else:
|
|
609
|
+
map_name = existing_id[:-4] # remove file extension (assuming .png)
|
|
610
|
+
|
|
611
|
+
img_path = self.merger.merge(
|
|
612
|
+
feature["grid_bb"], file_name=map_name, overwrite=overwrite
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
if img_path is not False:
|
|
616
|
+
print(f'[INFO] Downloaded "{img_path}"')
|
|
582
617
|
else:
|
|
583
|
-
print(f'[WARNING] Download of "{
|
|
618
|
+
print(f'[WARNING] Download of "{img_path}" was unsuccessful.')
|
|
584
619
|
|
|
585
620
|
shutil.rmtree(DEFAULT_TEMP_FOLDER)
|
|
586
|
-
return
|
|
621
|
+
return img_path
|
|
587
622
|
|
|
588
623
|
def _save_metadata(
|
|
589
624
|
self,
|
|
590
625
|
feature: dict,
|
|
591
626
|
out_filepath: str,
|
|
627
|
+
img_path: str,
|
|
592
628
|
metadata_to_save: dict | None = None,
|
|
593
629
|
**kwargs: dict | None,
|
|
594
630
|
) -> None:
|
|
@@ -602,6 +638,8 @@ class SheetDownloader:
|
|
|
602
638
|
The feature for which to extract the metadata from
|
|
603
639
|
out_filepath : str
|
|
604
640
|
The path to save metadata csv.
|
|
641
|
+
img_path : str
|
|
642
|
+
The path to the downloaded map sheet.
|
|
605
643
|
metadata_to_save : dict, optional
|
|
606
644
|
A dictionary containing column names (str) and metadata keys (str or list) to save to metadata csv.
|
|
607
645
|
Multilayer keys should be passed as a list, i.e. ["key1","key2"] will search for ``self.features[i]["key1"]["key2"]``.
|
|
@@ -631,7 +669,7 @@ class SheetDownloader:
|
|
|
631
669
|
metadata_dict = {col: None for col in metadata_cols}
|
|
632
670
|
|
|
633
671
|
# get default metadata
|
|
634
|
-
metadata_dict["name"] =
|
|
672
|
+
metadata_dict["name"] = os.path.basename(img_path)
|
|
635
673
|
metadata_dict["url"] = str(feature["properties"]["IMAGEURL"])
|
|
636
674
|
if not self.published_dates:
|
|
637
675
|
date_col = kwargs.get("date_col", None)
|
|
@@ -705,16 +743,25 @@ class SheetDownloader:
|
|
|
705
743
|
"""
|
|
706
744
|
|
|
707
745
|
for feature in tqdm(features):
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
746
|
+
existing_id = self._check_map_sheet_exists(feature, metadata_fname)
|
|
747
|
+
if (
|
|
748
|
+
not overwrite and existing_id is not False
|
|
749
|
+
): # if map already exists and overwrite is False then skip
|
|
750
|
+
print(f'[INFO] "{existing_id}" already exists. Skipping download.')
|
|
751
|
+
continue
|
|
752
|
+
img_path = self._download_map(
|
|
753
|
+
feature,
|
|
754
|
+
existing_id,
|
|
755
|
+
download_in_parallel=download_in_parallel,
|
|
756
|
+
overwrite=overwrite,
|
|
713
757
|
)
|
|
714
|
-
if
|
|
758
|
+
if img_path is not False:
|
|
715
759
|
metadata_path = f"{path_save}/{metadata_fname}"
|
|
716
760
|
self._save_metadata(
|
|
717
|
-
feature=feature,
|
|
761
|
+
feature=feature,
|
|
762
|
+
out_filepath=metadata_path,
|
|
763
|
+
img_path=img_path,
|
|
764
|
+
**kwargs,
|
|
718
765
|
)
|
|
719
766
|
|
|
720
767
|
def download_all_map_sheets(
|
|
@@ -142,7 +142,12 @@ class TileMerger:
|
|
|
142
142
|
tile_size = img_size[0]
|
|
143
143
|
return tile_size
|
|
144
144
|
|
|
145
|
-
def merge(
|
|
145
|
+
def merge(
|
|
146
|
+
self,
|
|
147
|
+
grid_bb: GridBoundingBox,
|
|
148
|
+
file_name: str | None = None,
|
|
149
|
+
overwrite: bool = False,
|
|
150
|
+
) -> str | bool:
|
|
146
151
|
"""Merges cells contained within GridBoundingBox.
|
|
147
152
|
|
|
148
153
|
Parameters
|
|
@@ -151,11 +156,13 @@ class TileMerger:
|
|
|
151
156
|
GridBoundingBox containing tiles to merge
|
|
152
157
|
file_name : Union[str, None], optional
|
|
153
158
|
Name to use when saving map
|
|
154
|
-
|
|
159
|
+
If None, default name will be used, by default None
|
|
160
|
+
overwrite : bool, optional
|
|
161
|
+
Whether or not to overwrite existing files, by default False
|
|
155
162
|
Returns
|
|
156
163
|
-------
|
|
157
|
-
bool
|
|
158
|
-
|
|
164
|
+
str or bool
|
|
165
|
+
out path if file has successfully downloaded, False if not.
|
|
159
166
|
"""
|
|
160
167
|
os.makedirs(self.output_folder, exist_ok=True)
|
|
161
168
|
|
|
@@ -191,11 +198,18 @@ class TileMerger:
|
|
|
191
198
|
file_name = self._get_output_name(grid_bb)
|
|
192
199
|
|
|
193
200
|
out_path = f"{self.output_folder}{file_name}.{self.img_output_format[0]}"
|
|
201
|
+
if not overwrite:
|
|
202
|
+
i = 1
|
|
203
|
+
while os.path.exists(out_path):
|
|
204
|
+
out_path = (
|
|
205
|
+
f"{self.output_folder}{file_name}_{i}.{self.img_output_format[0]}"
|
|
206
|
+
)
|
|
207
|
+
i += 1
|
|
194
208
|
merged_image.save(out_path, self.img_output_format[1])
|
|
195
|
-
success =
|
|
196
|
-
if success:
|
|
197
|
-
logger.info(f"Merge successful! The image has been stored at '{out_path}'")
|
|
198
|
-
else:
|
|
209
|
+
success = out_path if os.path.exists(out_path) else False
|
|
210
|
+
if success is False:
|
|
199
211
|
logger.warning(f"Merge unsuccessful! '{out_path}' not saved.")
|
|
212
|
+
else:
|
|
213
|
+
logger.info(f"Merge successful! The image has been stored at '{out_path}'")
|
|
200
214
|
|
|
201
215
|
return success
|