easyidp 2.0.0__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.
- easyidp-2.0.0/LICENSE +21 -0
- easyidp-2.0.0/PKG-INFO +147 -0
- easyidp-2.0.0/README.md +90 -0
- easyidp-2.0.0/easyidp/__init__.py +241 -0
- easyidp-2.0.0/easyidp/cvtools.py +356 -0
- easyidp-2.0.0/easyidp/data.py +746 -0
- easyidp-2.0.0/easyidp/geotiff.py +1719 -0
- easyidp-2.0.0/easyidp/geotools.py +280 -0
- easyidp-2.0.0/easyidp/jsonfile.py +579 -0
- easyidp-2.0.0/easyidp/metashape.py +1999 -0
- easyidp-2.0.0/easyidp/pix4d.py +1903 -0
- easyidp-2.0.0/easyidp/pointcloud.py +1298 -0
- easyidp-2.0.0/easyidp/reconstruct.py +776 -0
- easyidp-2.0.0/easyidp/roi.py +1184 -0
- easyidp-2.0.0/easyidp/shp.py +472 -0
- easyidp-2.0.0/easyidp/visualize.py +349 -0
- easyidp-2.0.0/easyidp.egg-info/PKG-INFO +147 -0
- easyidp-2.0.0/easyidp.egg-info/SOURCES.txt +35 -0
- easyidp-2.0.0/easyidp.egg-info/dependency_links.txt +1 -0
- easyidp-2.0.0/easyidp.egg-info/requires.txt +33 -0
- easyidp-2.0.0/easyidp.egg-info/top_level.txt +2 -0
- easyidp-2.0.0/setup.cfg +7 -0
- easyidp-2.0.0/setup.py +65 -0
- easyidp-2.0.0/tests/__init__.py +30 -0
- easyidp-2.0.0/tests/test_cvtools.py +387 -0
- easyidp-2.0.0/tests/test_data.py +39 -0
- easyidp-2.0.0/tests/test_geotiff.py +636 -0
- easyidp-2.0.0/tests/test_init_class_func.py +135 -0
- easyidp-2.0.0/tests/test_jsonfile.py +132 -0
- easyidp-2.0.0/tests/test_metashape.py +852 -0
- easyidp-2.0.0/tests/test_pix4d.py +297 -0
- easyidp-2.0.0/tests/test_pointcloud.py +524 -0
- easyidp-2.0.0/tests/test_reconstruct.py +328 -0
- easyidp-2.0.0/tests/test_roi.py +349 -0
- easyidp-2.0.0/tests/test_shp.py +241 -0
- easyidp-2.0.0/tests/test_visualize.py +117 -0
easyidp-2.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 UTokyo-FieldPhenomics-Lab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
easyidp-2.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: easyidp
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: A handy tool for dealing with region of interest (ROI) on the image reconstruction (Metashape & Pix4D) outputs, mainly in agriculture applications
|
|
5
|
+
Home-page: https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP
|
|
6
|
+
Author: Haozhou Wang
|
|
7
|
+
Author-email: howcanoewang@gmail.com
|
|
8
|
+
Project-URL: Documentation, https://easyidp.readthedocs.io/en/latest/
|
|
9
|
+
Project-URL: Source, https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP
|
|
10
|
+
Project-URL: Tracker, https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/issues
|
|
11
|
+
Project-URL: forum, https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/discussions
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
24
|
+
Requires-Python: >=3.7, <4
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: numpy>=1.18.1
|
|
28
|
+
Requires-Dist: matplotlib>=3.2.2
|
|
29
|
+
Requires-Dist: scikit-image>=0.19.2
|
|
30
|
+
Requires-Dist: tabulate>=0.8.9
|
|
31
|
+
Requires-Dist: tqdm>=4.64.0
|
|
32
|
+
Requires-Dist: pyproj>=3.4.0
|
|
33
|
+
Requires-Dist: tifffile>=2020.09.03
|
|
34
|
+
Requires-Dist: imagecodecs>=2021.11.20
|
|
35
|
+
Requires-Dist: shapely~=1.8.0
|
|
36
|
+
Requires-Dist: lazrs>=0.1.1
|
|
37
|
+
Requires-Dist: laspy>=2.1.2
|
|
38
|
+
Requires-Dist: plyfile==0.7.2
|
|
39
|
+
Requires-Dist: pyshp==2.1.3
|
|
40
|
+
Requires-Dist: geojson>=3.1.0
|
|
41
|
+
Requires-Dist: gdown>=4.7.3
|
|
42
|
+
Provides-Extra: docs
|
|
43
|
+
Requires-Dist: sphinx==5.3.0; extra == "docs"
|
|
44
|
+
Requires-Dist: sphinx-intl==2.0.1; extra == "docs"
|
|
45
|
+
Requires-Dist: sphinx-inline-tabs==2022.1.2b11; extra == "docs"
|
|
46
|
+
Requires-Dist: furo==2022.12.7; extra == "docs"
|
|
47
|
+
Requires-Dist: nbsphinx==0.8.11; extra == "docs"
|
|
48
|
+
Requires-Dist: sphinx-gallery==0.10.1; extra == "docs"
|
|
49
|
+
Requires-Dist: ipython==8.10.0; extra == "docs"
|
|
50
|
+
Provides-Extra: test
|
|
51
|
+
Requires-Dist: pytest>=7.1.2; extra == "test"
|
|
52
|
+
Provides-Extra: build
|
|
53
|
+
Requires-Dist: packaging>=20.0; extra == "build"
|
|
54
|
+
Requires-Dist: wheel; extra == "build"
|
|
55
|
+
Requires-Dist: numpy>=1.19; extra == "build"
|
|
56
|
+
Requires-Dist: build; extra == "build"
|
|
57
|
+
|
|
58
|
+
<div align="center">
|
|
59
|
+
|
|
60
|
+
<p>
|
|
61
|
+
<!-- <a align="left" href="https://ultralytics.com/yolov5" target="_blank"> -->
|
|
62
|
+
<img width="850" src="https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/raw/v2.0/docs/_static/images/header_v2.0.png"></a>
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
<p align="center">
|
|
66
|
+
<img alt="GitHub Actions Badge" src="https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/actions/workflows/pytest.yml/badge.svg?style=plastic">
|
|
67
|
+
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/easyidp?style=plastic">
|
|
68
|
+
<img alt="GitHub" src="https://img.shields.io/github/license/UTokyo-FieldPhenomics-Lab/EasyIDP?style=plastic">
|
|
69
|
+
<img alt="GitHub top language" src="https://img.shields.io/github/languages/top/UTokyo-FieldPhenomics-Lab/EasyIDP?style=plastic">
|
|
70
|
+
<img alt="GitHub Downloads" src="https://img.shields.io/github/downloads/UTokyo-FieldPhenomics-Lab/EasyIDP/total?label=github%20downloads&style=plastic">
|
|
71
|
+
<img alt="GitHub Downloads" src="https://img.shields.io/pypi/dm/easyidp?color=%233775A9&label=pypi%20downloads&style=plastic">
|
|
72
|
+
</p>
|
|
73
|
+
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
EasyIDP (Easy Intermediate Data Processor), A handy tool for dealing with region of interest (ROI) on the image reconstruction (Metashape & Pix4D) outputs, mainly in agriculture applications. It provides the following functions:
|
|
77
|
+
|
|
78
|
+
1. Backward Projection ROI to original images (`Backward Projector`).
|
|
79
|
+
2. Crop ROI on GeoTiff Maps (DOM & DSM) and Point Cloud (`ROI Cropper`).
|
|
80
|
+
3. Save cropped results to corresponding files (`ROI Saver`).
|
|
81
|
+
|
|
82
|
+
This project tried to use packges based on pure-python, instead of installing some heavy packages (Open3D, OpenCV) and hard to install packages (GDAL dependices) for one or two individual functions. This may cause efficiency loss and differences in coding habit.
|
|
83
|
+
|
|
84
|
+
<p align="center">
|
|
85
|
+
<img alt="GitHub Downloads" height="400px" src="https://api.star-history.com/svg?repos=UTokyo-FieldPhenomics-Lab/EasyIDP&type=Date">
|
|
86
|
+
</p>
|
|
87
|
+
|
|
88
|
+
## <div align="center">Documentation</div>
|
|
89
|
+
|
|
90
|
+
Please check [Official Documents](https://easyidp.readthedocs.io/en/latest/) ( [中文](https://easyidp.readthedocs.io/zh_CN/latest/) | [日本語(翻訳募集)](https://easyidp.readthedocs.io/ja/latest/) ) for full documentations. And please also use the [Github Discussion](https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/discussions) when you meet any problems.
|
|
91
|
+
|
|
92
|
+
## <div align="center">References</div>
|
|
93
|
+
|
|
94
|
+
Please cite this paper if this project helps you:
|
|
95
|
+
|
|
96
|
+
```latex
|
|
97
|
+
@Article{wang_easyidp_2021,
|
|
98
|
+
AUTHOR = {Wang, Haozhou and Duan, Yulin and Shi, Yun and Kato, Yoichiro and Ninomiya, Seish and Guo, Wei},
|
|
99
|
+
TITLE = {EasyIDP: A Python Package for Intermediate Data Processing in UAV-Based Plant Phenotyping},
|
|
100
|
+
JOURNAL = {Remote Sensing},
|
|
101
|
+
VOLUME = {13},
|
|
102
|
+
YEAR = {2021},
|
|
103
|
+
NUMBER = {13},
|
|
104
|
+
ARTICLE-NUMBER = {2622},
|
|
105
|
+
URL = {https://www.mdpi.com/2072-4292/13/13/2622},
|
|
106
|
+
ISSN = {2072-4292},
|
|
107
|
+
DOI = {10.3390/rs13132622}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
We also thanks the benefits from the following open source projects:
|
|
112
|
+
|
|
113
|
+
* package main (**for users**)
|
|
114
|
+
* numpy: [https://numpy.org/](https://numpy.org/)
|
|
115
|
+
* matplotlib:[https://matplotlib.org/](https://matplotlib.org/)
|
|
116
|
+
* scikit-image: [https://github.com/scikit-image/scikit-image](https://github.com/scikit-image/scikit-image)
|
|
117
|
+
* pyproj: [https://github.com/pyproj4/pyproj](https://github.com/pyproj4/pyproj)
|
|
118
|
+
* tifffile: [https://github.com/cgohlke/tifffile](https://github.com/cgohlke/tifffile)
|
|
119
|
+
* imagecodecs: [https://github.com/cgohlke/imagecodecs](https://github.com/cgohlke/imagecodecs)
|
|
120
|
+
* shapely: [https://github.com/shapely/shapely](https://github.com/shapely/shapely)
|
|
121
|
+
* laspy/lasrs/lasio: [https://github.com/laspy/laspy](https://github.com/laspy/laspy)
|
|
122
|
+
* geojson: [https://github.com/jazzband/geojson](https://github.com/jazzband/geojson)
|
|
123
|
+
* plyfile: [https://github.com/dranjan/python-plyfile](https://github.com/dranjan/python-plyfile)
|
|
124
|
+
* pyshp: [https://github.com/GeospatialPython/pyshp](https://github.com/GeospatialPython/pyshp)
|
|
125
|
+
* tabulate: [https://github.com/astanin/python-tabulate](https://github.com/astanin/python-tabulate)
|
|
126
|
+
* tqdm: [https://github.com/tqdm/tqdm](https://github.com/tqdm/tqdm)
|
|
127
|
+
* gdown: [https://github.com/wkentaro/gdown](https://github.com/wkentaro/gdown)
|
|
128
|
+
* package documentation (**for developers**)
|
|
129
|
+
* sphinx: [https://github.com/sphinx-doc/sphinx](https://github.com/sphinx-doc/sphinx)
|
|
130
|
+
* nbsphinx: [https://github.com/spatialaudio/nbsphinx](https://github.com/spatialaudio/nbsphinx)
|
|
131
|
+
* sphinx-gallery: [https://github.com/sphinx-gallery/sphinx-gallery](https://github.com/sphinx-gallery/sphinx-gallery)
|
|
132
|
+
* sphinx-inline-tabs: [https://github.com/pradyunsg/sphinx-inline-tabs](https://github.com/pradyunsg/sphinx-inline-tabs)
|
|
133
|
+
* sphinx-intl: [https://github.com/sphinx-doc/sphinx-intl](https://github.com/sphinx-doc/sphinx-intl)
|
|
134
|
+
* sphinx-rtc-theme: [https://github.com/readthedocs/sphinx_rtd_theme](https://github.com/readthedocs/sphinx_rtd_theme)
|
|
135
|
+
* furo: [https://github.com/pradyunsg/furo](https://github.com/pradyunsg/furo)
|
|
136
|
+
* package testing and releasing (**for developers**)
|
|
137
|
+
* pytest: [https://github.com/pytest-dev/pytest](https://github.com/pytest-dev/pytest)
|
|
138
|
+
* packaging: [https://github.com/pypa/packaging](https://github.com/pypa/packaging)
|
|
139
|
+
* wheel: [https://github.com/pypa/wheel](https://github.com/pypa/wheel)
|
|
140
|
+
|
|
141
|
+
This project was partially funded by:
|
|
142
|
+
|
|
143
|
+
* the JST AIP Acceleration Research “Studies of CPS platform to raise big-data-driven AI agriculture”;
|
|
144
|
+
* the SICORP Program JPMJSC16H2;
|
|
145
|
+
* CREST Programs JPMJCR16O2 and JPMJCR16O1;
|
|
146
|
+
* the International Science & Technology Innovation Program of Chinese Academy of Agricultural Sciences (CAASTIP);
|
|
147
|
+
* the National Natural Science Foundation of China U19A2061.
|
easyidp-2.0.0/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<!-- <a align="left" href="https://ultralytics.com/yolov5" target="_blank"> -->
|
|
5
|
+
<img width="850" src="https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/raw/v2.0/docs/_static/images/header_v2.0.png"></a>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<img alt="GitHub Actions Badge" src="https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/actions/workflows/pytest.yml/badge.svg?style=plastic">
|
|
10
|
+
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/easyidp?style=plastic">
|
|
11
|
+
<img alt="GitHub" src="https://img.shields.io/github/license/UTokyo-FieldPhenomics-Lab/EasyIDP?style=plastic">
|
|
12
|
+
<img alt="GitHub top language" src="https://img.shields.io/github/languages/top/UTokyo-FieldPhenomics-Lab/EasyIDP?style=plastic">
|
|
13
|
+
<img alt="GitHub Downloads" src="https://img.shields.io/github/downloads/UTokyo-FieldPhenomics-Lab/EasyIDP/total?label=github%20downloads&style=plastic">
|
|
14
|
+
<img alt="GitHub Downloads" src="https://img.shields.io/pypi/dm/easyidp?color=%233775A9&label=pypi%20downloads&style=plastic">
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
EasyIDP (Easy Intermediate Data Processor), A handy tool for dealing with region of interest (ROI) on the image reconstruction (Metashape & Pix4D) outputs, mainly in agriculture applications. It provides the following functions:
|
|
20
|
+
|
|
21
|
+
1. Backward Projection ROI to original images (`Backward Projector`).
|
|
22
|
+
2. Crop ROI on GeoTiff Maps (DOM & DSM) and Point Cloud (`ROI Cropper`).
|
|
23
|
+
3. Save cropped results to corresponding files (`ROI Saver`).
|
|
24
|
+
|
|
25
|
+
This project tried to use packges based on pure-python, instead of installing some heavy packages (Open3D, OpenCV) and hard to install packages (GDAL dependices) for one or two individual functions. This may cause efficiency loss and differences in coding habit.
|
|
26
|
+
|
|
27
|
+
<p align="center">
|
|
28
|
+
<img alt="GitHub Downloads" height="400px" src="https://api.star-history.com/svg?repos=UTokyo-FieldPhenomics-Lab/EasyIDP&type=Date">
|
|
29
|
+
</p>
|
|
30
|
+
|
|
31
|
+
## <div align="center">Documentation</div>
|
|
32
|
+
|
|
33
|
+
Please check [Official Documents](https://easyidp.readthedocs.io/en/latest/) ( [中文](https://easyidp.readthedocs.io/zh_CN/latest/) | [日本語(翻訳募集)](https://easyidp.readthedocs.io/ja/latest/) ) for full documentations. And please also use the [Github Discussion](https://github.com/UTokyo-FieldPhenomics-Lab/EasyIDP/discussions) when you meet any problems.
|
|
34
|
+
|
|
35
|
+
## <div align="center">References</div>
|
|
36
|
+
|
|
37
|
+
Please cite this paper if this project helps you:
|
|
38
|
+
|
|
39
|
+
```latex
|
|
40
|
+
@Article{wang_easyidp_2021,
|
|
41
|
+
AUTHOR = {Wang, Haozhou and Duan, Yulin and Shi, Yun and Kato, Yoichiro and Ninomiya, Seish and Guo, Wei},
|
|
42
|
+
TITLE = {EasyIDP: A Python Package for Intermediate Data Processing in UAV-Based Plant Phenotyping},
|
|
43
|
+
JOURNAL = {Remote Sensing},
|
|
44
|
+
VOLUME = {13},
|
|
45
|
+
YEAR = {2021},
|
|
46
|
+
NUMBER = {13},
|
|
47
|
+
ARTICLE-NUMBER = {2622},
|
|
48
|
+
URL = {https://www.mdpi.com/2072-4292/13/13/2622},
|
|
49
|
+
ISSN = {2072-4292},
|
|
50
|
+
DOI = {10.3390/rs13132622}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
We also thanks the benefits from the following open source projects:
|
|
55
|
+
|
|
56
|
+
* package main (**for users**)
|
|
57
|
+
* numpy: [https://numpy.org/](https://numpy.org/)
|
|
58
|
+
* matplotlib:[https://matplotlib.org/](https://matplotlib.org/)
|
|
59
|
+
* scikit-image: [https://github.com/scikit-image/scikit-image](https://github.com/scikit-image/scikit-image)
|
|
60
|
+
* pyproj: [https://github.com/pyproj4/pyproj](https://github.com/pyproj4/pyproj)
|
|
61
|
+
* tifffile: [https://github.com/cgohlke/tifffile](https://github.com/cgohlke/tifffile)
|
|
62
|
+
* imagecodecs: [https://github.com/cgohlke/imagecodecs](https://github.com/cgohlke/imagecodecs)
|
|
63
|
+
* shapely: [https://github.com/shapely/shapely](https://github.com/shapely/shapely)
|
|
64
|
+
* laspy/lasrs/lasio: [https://github.com/laspy/laspy](https://github.com/laspy/laspy)
|
|
65
|
+
* geojson: [https://github.com/jazzband/geojson](https://github.com/jazzband/geojson)
|
|
66
|
+
* plyfile: [https://github.com/dranjan/python-plyfile](https://github.com/dranjan/python-plyfile)
|
|
67
|
+
* pyshp: [https://github.com/GeospatialPython/pyshp](https://github.com/GeospatialPython/pyshp)
|
|
68
|
+
* tabulate: [https://github.com/astanin/python-tabulate](https://github.com/astanin/python-tabulate)
|
|
69
|
+
* tqdm: [https://github.com/tqdm/tqdm](https://github.com/tqdm/tqdm)
|
|
70
|
+
* gdown: [https://github.com/wkentaro/gdown](https://github.com/wkentaro/gdown)
|
|
71
|
+
* package documentation (**for developers**)
|
|
72
|
+
* sphinx: [https://github.com/sphinx-doc/sphinx](https://github.com/sphinx-doc/sphinx)
|
|
73
|
+
* nbsphinx: [https://github.com/spatialaudio/nbsphinx](https://github.com/spatialaudio/nbsphinx)
|
|
74
|
+
* sphinx-gallery: [https://github.com/sphinx-gallery/sphinx-gallery](https://github.com/sphinx-gallery/sphinx-gallery)
|
|
75
|
+
* sphinx-inline-tabs: [https://github.com/pradyunsg/sphinx-inline-tabs](https://github.com/pradyunsg/sphinx-inline-tabs)
|
|
76
|
+
* sphinx-intl: [https://github.com/sphinx-doc/sphinx-intl](https://github.com/sphinx-doc/sphinx-intl)
|
|
77
|
+
* sphinx-rtc-theme: [https://github.com/readthedocs/sphinx_rtd_theme](https://github.com/readthedocs/sphinx_rtd_theme)
|
|
78
|
+
* furo: [https://github.com/pradyunsg/furo](https://github.com/pradyunsg/furo)
|
|
79
|
+
* package testing and releasing (**for developers**)
|
|
80
|
+
* pytest: [https://github.com/pytest-dev/pytest](https://github.com/pytest-dev/pytest)
|
|
81
|
+
* packaging: [https://github.com/pypa/packaging](https://github.com/pypa/packaging)
|
|
82
|
+
* wheel: [https://github.com/pypa/wheel](https://github.com/pypa/wheel)
|
|
83
|
+
|
|
84
|
+
This project was partially funded by:
|
|
85
|
+
|
|
86
|
+
* the JST AIP Acceleration Research “Studies of CPS platform to raise big-data-driven AI agriculture”;
|
|
87
|
+
* the SICORP Program JPMJSC16H2;
|
|
88
|
+
* CREST Programs JPMJCR16O2 and JPMJCR16O1;
|
|
89
|
+
* the International Science & Technology Innovation Program of Chinese Academy of Agricultural Sciences (CAASTIP);
|
|
90
|
+
* the National Natural Science Foundation of China U19A2061.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
__version__ = "2.0.0"
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import warnings
|
|
5
|
+
import numpy as np
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
|
|
10
|
+
##############
|
|
11
|
+
# dict tools #
|
|
12
|
+
##############
|
|
13
|
+
|
|
14
|
+
class Container(dict):
|
|
15
|
+
"""Self designed dictionary class to fetch items by id or label
|
|
16
|
+
|
|
17
|
+
Caution
|
|
18
|
+
-------
|
|
19
|
+
This object can not be saved by ``pickle``, it will cause problem when loading [1]_
|
|
20
|
+
|
|
21
|
+
References
|
|
22
|
+
----------
|
|
23
|
+
.. [1] https://stackoverflow.com/questions/4014621/a-python-class-that-acts-like-dict
|
|
24
|
+
"""
|
|
25
|
+
def __init__(self, suffix=''):
|
|
26
|
+
super().__init__()
|
|
27
|
+
self.id_item = {} # {0: item1, 1: item2}
|
|
28
|
+
self.item_label = {} #{"N1W1": 0, "N1W2": 1}, just index it position
|
|
29
|
+
self._suffix = str(suffix)
|
|
30
|
+
|
|
31
|
+
def __setitem__(self, key, item):
|
|
32
|
+
if isinstance(key, int):
|
|
33
|
+
# default method to set values
|
|
34
|
+
# Container[0] = A, while A.label = "N1W1"
|
|
35
|
+
|
|
36
|
+
if key < len(self.item_label):
|
|
37
|
+
if 'label' in dir(item): # has item.label
|
|
38
|
+
# delete old label
|
|
39
|
+
# e.g. {'empty 0': 0, 'empty 1': 1}
|
|
40
|
+
# 0 -> IMG_0001;
|
|
41
|
+
# {'empty 0': 0, 'empty 1': 1, 'IMG_0001': 0}
|
|
42
|
+
old_key = self.id_item[key].label
|
|
43
|
+
del self.item_label[old_key]
|
|
44
|
+
|
|
45
|
+
# add new label
|
|
46
|
+
self.item_label[item.label] = key
|
|
47
|
+
# change the value of one item
|
|
48
|
+
self.id_item[key] = item
|
|
49
|
+
|
|
50
|
+
elif key == len(self.item_label):
|
|
51
|
+
# add a new item
|
|
52
|
+
self.id_item[key] = item
|
|
53
|
+
if 'label' in dir(item):
|
|
54
|
+
# sometimes two items has the same label
|
|
55
|
+
if item.label in self.item_label.keys():
|
|
56
|
+
raise KeyError(f"The given item's label [{item.label}] already exists -> {self.item_label.keys()}")
|
|
57
|
+
else:
|
|
58
|
+
self.item_label[item.label] = key
|
|
59
|
+
else:
|
|
60
|
+
self.item_label[key] = key
|
|
61
|
+
else:
|
|
62
|
+
raise IndexError(f"Index [{key}] out of range (0, {len(self.item_label)})")
|
|
63
|
+
|
|
64
|
+
elif isinstance(key, str):
|
|
65
|
+
# advanced method to change items
|
|
66
|
+
# Container["N1W1"] = B, here assuemt B.label already == "N1W1"
|
|
67
|
+
|
|
68
|
+
# item already exists
|
|
69
|
+
if key in self.item_label.keys():
|
|
70
|
+
idx = self.item_label[key]
|
|
71
|
+
self.id_item[idx] = item
|
|
72
|
+
else: # add new item
|
|
73
|
+
idx = len(self.id_item)
|
|
74
|
+
self.id_item[idx] = item
|
|
75
|
+
if 'label' in dir(item): # has item.label
|
|
76
|
+
self.item_label[item.label] = idx
|
|
77
|
+
else: # act as common dictionary
|
|
78
|
+
self.item_label[key] = idx
|
|
79
|
+
else:
|
|
80
|
+
raise KeyError(f"Key should be 'int', 'str', not {key}")
|
|
81
|
+
|
|
82
|
+
def __getitem__(self, key):
|
|
83
|
+
if isinstance(key, int): # index by photo order
|
|
84
|
+
if key < len(self.item_label):
|
|
85
|
+
return self.id_item[key]
|
|
86
|
+
else:
|
|
87
|
+
raise IndexError(f"Index [{key}] out of range (0, {len(self.item_label)})")
|
|
88
|
+
elif isinstance(key, str): # index by photo name
|
|
89
|
+
if key in self.item_label.keys():
|
|
90
|
+
return self.id_item[self.item_label[key]]
|
|
91
|
+
elif self._suffix in key and os.path.splitext(key)[0] in self.item_label.keys():
|
|
92
|
+
return self.id_item[self.item_label[os.path.splitext(key)[0]]]
|
|
93
|
+
else:
|
|
94
|
+
raise KeyError(f"Can not find key [{key}]")
|
|
95
|
+
elif isinstance(key, slice):
|
|
96
|
+
idx_list = list(self.id_item.keys())[key]
|
|
97
|
+
|
|
98
|
+
out = self.copy()
|
|
99
|
+
out.id_item = {k:v for k, v in self.id_item.items() if k in idx_list}
|
|
100
|
+
out.item_label = {k:v for k, v in self.item_label.items() if v in idx_list}
|
|
101
|
+
|
|
102
|
+
return out
|
|
103
|
+
else:
|
|
104
|
+
raise KeyError(f"Key should be 'int', 'str', 'slice', not {key}")
|
|
105
|
+
|
|
106
|
+
def __repr__(self) -> str:
|
|
107
|
+
return self._btf_print()
|
|
108
|
+
|
|
109
|
+
def __str__(self) -> str:
|
|
110
|
+
return self._btf_print()
|
|
111
|
+
|
|
112
|
+
def _btf_print(self):
|
|
113
|
+
title = f'easyidp.{self.__class__.__name__}'
|
|
114
|
+
key_list = list(self.item_label.keys())
|
|
115
|
+
num = len(key_list)
|
|
116
|
+
out_str = f'<{title}> with {num} items\n'
|
|
117
|
+
|
|
118
|
+
# limit the numpy print out
|
|
119
|
+
default_np_thresh = np.get_printoptions()['threshold']
|
|
120
|
+
default_np_suppress = np.get_printoptions()['suppress']
|
|
121
|
+
np.set_printoptions(threshold=4, suppress=True)
|
|
122
|
+
if num == 0:
|
|
123
|
+
out_str = "<Empty easyidp.Container object>"
|
|
124
|
+
elif num > 5:
|
|
125
|
+
for i, k in enumerate(key_list[:2]):
|
|
126
|
+
out_str += f"[{i}]\t{k}\n"
|
|
127
|
+
out_str += repr(self.id_item[self.item_label[k]])
|
|
128
|
+
out_str += '\n'
|
|
129
|
+
out_str += '...\n'
|
|
130
|
+
for i, k in enumerate(key_list[-2:]):
|
|
131
|
+
out_str += f"[{num-2+i}]\t{k}\n"
|
|
132
|
+
out_str += repr(self.id_item[self.item_label[k]])
|
|
133
|
+
out_str += '\n'
|
|
134
|
+
else:
|
|
135
|
+
for i, k in enumerate(key_list):
|
|
136
|
+
out_str += f"[{i}]\t{k}\n"
|
|
137
|
+
out_str += repr(self.id_item[self.item_label[k]])
|
|
138
|
+
out_str += '\n'
|
|
139
|
+
np.set_printoptions(threshold=default_np_thresh, suppress=default_np_suppress)
|
|
140
|
+
|
|
141
|
+
out_str = out_str[:-1]
|
|
142
|
+
return out_str
|
|
143
|
+
|
|
144
|
+
def __len__(self):
|
|
145
|
+
return len(self.id_item)
|
|
146
|
+
|
|
147
|
+
def __delitem__(self, key):
|
|
148
|
+
if isinstance(key, int):
|
|
149
|
+
k = key
|
|
150
|
+
del self.item_label[self.id_item[key]]
|
|
151
|
+
del self.id_item[key]
|
|
152
|
+
elif isinstance(key, str):
|
|
153
|
+
k = self.item_label[key]
|
|
154
|
+
del self.id_item[self.item_label[key]]
|
|
155
|
+
del self.item_label[key]
|
|
156
|
+
else:
|
|
157
|
+
raise KeyError(f"Key should be 'int', 'str', 'slice', not {key}")
|
|
158
|
+
|
|
159
|
+
# update the id
|
|
160
|
+
# a[5] = a.pop(1)
|
|
161
|
+
# https://stackoverflow.com/questions/4406501/change-the-name-of-a-key-in-dictionary
|
|
162
|
+
id_item_keys = list(self.id_item.keys())
|
|
163
|
+
for idx in id_item_keys:
|
|
164
|
+
# e,g. k = 3, idx in [0, 1, 2, 4, 5]
|
|
165
|
+
if idx > k:
|
|
166
|
+
self.id_item[idx-1] = self.id_item.pop(idx)
|
|
167
|
+
|
|
168
|
+
# e.g. {"N1W1": 0, "N1W2": 1},
|
|
169
|
+
label = _find_key(self.item_label, idx)
|
|
170
|
+
self.item_label[label] = idx - 1
|
|
171
|
+
|
|
172
|
+
def __iter__(self):
|
|
173
|
+
return iter(self.id_item.values())
|
|
174
|
+
|
|
175
|
+
def keys(self):
|
|
176
|
+
return self.item_label.keys()
|
|
177
|
+
|
|
178
|
+
def values(self):
|
|
179
|
+
return self.id_item.values()
|
|
180
|
+
|
|
181
|
+
def items(self):
|
|
182
|
+
out_dict = {}
|
|
183
|
+
for k, idx in self.item_label.items():
|
|
184
|
+
out_dict[k] = self.id_item[idx]
|
|
185
|
+
return out_dict.items()
|
|
186
|
+
|
|
187
|
+
def copy(self):
|
|
188
|
+
return deepcopy(self)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _find_key(mydict, value):
|
|
192
|
+
"""a simple function to using dict value to find key
|
|
193
|
+
e.g.
|
|
194
|
+
>>> mydict = {"a": 233, "b": 456}
|
|
195
|
+
>>> _find_key(mydict, 233)
|
|
196
|
+
"a"
|
|
197
|
+
"""
|
|
198
|
+
key_idx = list(mydict.values()).index(value)
|
|
199
|
+
return list(mydict.keys())[key_idx]
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
##############
|
|
203
|
+
# path tools #
|
|
204
|
+
##############
|
|
205
|
+
|
|
206
|
+
def get_full_path(short_path):
|
|
207
|
+
if isinstance(short_path, str):
|
|
208
|
+
return Path(short_path)
|
|
209
|
+
elif isinstance(short_path, Path):
|
|
210
|
+
return short_path
|
|
211
|
+
else:
|
|
212
|
+
return None
|
|
213
|
+
|
|
214
|
+
def parse_relative_path(root_path, relative_path):
|
|
215
|
+
# for metashape frame.zip path use only
|
|
216
|
+
if r"../../" in relative_path:
|
|
217
|
+
frame_path = os.path.dirname(os.path.abspath(root_path))
|
|
218
|
+
merge = os.path.join(frame_path, relative_path)
|
|
219
|
+
return os.path.abspath(merge)
|
|
220
|
+
else:
|
|
221
|
+
warnings.warn(f"Seems it is an absolute path [{relative_path}]")
|
|
222
|
+
return relative_path
|
|
223
|
+
|
|
224
|
+
###############
|
|
225
|
+
# import APIs #
|
|
226
|
+
###############
|
|
227
|
+
|
|
228
|
+
from . import (
|
|
229
|
+
visualize,
|
|
230
|
+
cvtools,
|
|
231
|
+
geotools,
|
|
232
|
+
shp,
|
|
233
|
+
jsonfile,
|
|
234
|
+
data,
|
|
235
|
+
)
|
|
236
|
+
from .reconstruct import ProjectPool
|
|
237
|
+
from .pointcloud import PointCloud
|
|
238
|
+
from .geotiff import GeoTiff
|
|
239
|
+
from .pix4d import Pix4D
|
|
240
|
+
from .metashape import Metashape
|
|
241
|
+
from .roi import ROI
|