diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 596e7ed1b2e611de5b21ef6c5f4598f17ab8fe19..4c7c2deae3ee6a73758a2b7634fb121dcf4075e1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -207,6 +207,17 @@ imports: script: - python -m pytest --junitxml=$ARTIFACT_TEST_DIR/report_imports.xml $OTBTF_SRC/test/imports_test.py +numpy_gdal_otb: + extends: .applications_test_base + script: + - python -m pytest --junitxml=$ARTIFACT_TEST_DIR/report_numpy.xml $OTBTF_SRC/test/numpy_test.py + +rio: + extends: .applications_test_base + script: + - sudo pip install rasterio + - python -m pytest --junitxml=$ARTIFACT_TEST_DIR/report_rio.xml $OTBTF_SRC/test/rio_test.py + deploy_cpu-dev-testing: stage: Update dev image extends: .docker_build_base diff --git a/Dockerfile b/Dockerfile index f8b82f7999e159f4ee5ec3eb1fba88a0eb46a449..a612da257648a30ca2cec7ed44578e950d1b1607 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,8 +27,7 @@ RUN ln -s /usr/bin/python3 /usr/local/bin/python && ln -s /usr/bin/pip3 /usr/loc RUN pip install --no-cache-dir pip --upgrade # NumPy version is conflicting with system's gdal dep and may require venv ARG NUMPY_SPEC="==1.22.*" -ARG PROTO_SPEC="==3.20.*" -RUN pip install --no-cache-dir -U wheel mock six future tqdm deprecated "numpy$NUMPY_SPEC" "protobuf$PROTO_SPEC" packaging requests \ +RUN pip install --no-cache-dir -U wheel mock six future tqdm deprecated "numpy$NUMPY_SPEC" packaging requests \ && pip install --no-cache-dir --no-deps keras_applications keras_preprocessing # ---------------------------------------------------------------------------- diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 7cf3b01d4bb68d8d9e26ca9d4f7c75a50fd1da06..e0ac4a4eaebbea499e0464edacc49489c1e3ebdd 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -12,6 +12,7 @@ Version 4.0.0alpha (4 apr 2023) * Tensorflow version: 2.12.0 * Fixed Tensorflow error "Cannot register 2 metrics with the same name" + new test * Faster CI build thanks to bazel remote cache +* /home/otbuser/.local/bin added to user path Version 3.4.0 (22 mar 2023) ---------------------------------------------------------------- diff --git a/doc/api_distributed.md b/doc/api_distributed.md index 1478022c7ea7ce341682a8af3103452d9428bf00..077704e01c3fd70f699d34d9045c517799200292 100644 --- a/doc/api_distributed.md +++ b/doc/api_distributed.md @@ -24,7 +24,7 @@ on all GPUs. ## Python code We can start from the codebase of the fully convolutional model example -described in the OTBTF [Python API tutorial](#api_tutorial.html). +described in the OTBTF [Python API tutorial](api_tutorial.html). ### Dataset diff --git a/doc/deprecated.md b/doc/deprecated.md index c0477962cb43ac9c43e08c336c18beeb6a6c7623..3f76c1dbd1d62e3313da1e85e4d3b8e8ecef8bdf 100644 --- a/doc/deprecated.md +++ b/doc/deprecated.md @@ -35,4 +35,4 @@ training, etc. is done using the so-called `tensorflow.Strategy` !!! Note - Read our [tutorial](#api_tutorial.html) to know more on working with Keras! \ No newline at end of file + Read our [tutorial](api_tutorial.html) to know more on working with Keras! \ No newline at end of file diff --git a/doc/docker_build.md b/doc/docker_build.md index c7a3c1e97e5030760d79c2b1429578b12d32f4cb..debc1ea8d5ae2994949b46a61e70a5ed14290ce3 100644 --- a/doc/docker_build.md +++ b/doc/docker_build.md @@ -49,7 +49,7 @@ be a different branch of OTB, bazel cache will help you to rebuild everything except TF, even if the docker cache was purged (after `docker [system|builder] prune`). In order to recycle the cache, bazel config and TF git tag should be exactly -the same, any change in [build-env-tf.sh](build-env-tf.sh) and `--build-arg` +the same, any change in *tools/docker/build-env-tf.sh* and `--build-arg` (if related to bazel env, cuda, mkl, xla...) may result in a fresh new build. Start a cache daemon - here with max 20GB but 10GB should be enough to save 2 diff --git a/doc/docker_use.md b/doc/docker_use.md index 47749325def9c1ab1ae2d162bcb6abb236909fe6..ebbab5a492f122be2e690c1497544c31a2e4d708 100644 --- a/doc/docker_use.md +++ b/doc/docker_use.md @@ -104,7 +104,7 @@ Troubleshooting: If you want to use optimization flags, change GPUs compute capability, etc. you can build your own docker image using the provided dockerfile. -See the [docker build documentation](#docker_build.html). +See the [docker build documentation](docker_build.html). ## Older images diff --git a/doc/index.md b/doc/index.md index 4bb28c76017bbf1abd6a3c9fddf72b554d848855..f96bb5cb09e46b7302f3d3f463b8f69175707fc2 100644 --- a/doc/index.md +++ b/doc/index.md @@ -16,7 +16,7 @@ This remote module of the [Orfeo ToolBox](https://www.orfeo-toolbox.org) -provides a generic, multi-purpose deep learning framework, targeting remote +provides a generic, multipurpose deep learning framework, targeting remote sensing images processing. It contains a set of new process objects for OTB that internally invoke [Tensorflow](https://www.tensorflow.org/), and new [OTB applications](#otb-applications) to perform deep learning with real-world @@ -50,7 +50,7 @@ set of _patches images_ and delivering samples as `tf.dataset` that can be used in your favorite TensorFlow pipelines, or convert your patches into TFRecords. The `otbtf.TFRecords` enables you train networks from TFRecords files, which is quite suited for distributed training. Read more in the -[tutorial for keras](otbtf/examples/tensorflow_v2x/fcnn/README.md). +[tutorial for keras](api_tutorial.html). ## Examples diff --git a/test/imports_test.py b/test/imports_test.py index a89ab3dc2566d40c95ef05cc109ce8a1939d940a..e745ed5baacd0a8a7a141891e3fb497ad537b81c 100644 --- a/test/imports_test.py +++ b/test/imports_test.py @@ -19,5 +19,16 @@ class ImportsTest(unittest.TestCase): self.assertTrue(tensorflow.__version__) + def test_import_all(self): + import otbApplication + self.assertTrue(otbApplication.Registry_GetAvailableApplications()) + import tensorflow + self.assertTrue(tensorflow.__version__) + from osgeo import gdal + self.assertTrue(gdal.__version__) + import numpy + self.assertTrue(numpy.__version__) + + if __name__ == '__main__': unittest.main() diff --git a/test/numpy_test.py b/test/numpy_test.py new file mode 100644 index 0000000000000000000000000000000000000000..55f0272ce4b2570c4ff0642ded73bf75baaa0d58 --- /dev/null +++ b/test/numpy_test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import pytest +import unittest +import otbApplication +from osgeo import gdal +from test_utils import resolve_paths + +FILENAME = resolve_paths('$DATADIR/fake_spot6.jp2') + +class NumpyTest(unittest.TestCase): + + def test_gdal_as_nparr(self): + gdal_ds = gdal.Open(FILENAME) + band = gdal_ds.GetRasterBand(1) + arr = band.ReadAsArray() + self.assertTrue(arr.shape) + + + def test_otb_as_nparr(self): + app = otbApplication.Registry.CreateApplication('ExtractROI') + app.SetParameterString("in", FILENAME) + app.Execute() + arr = app.GetVectorImageAsNumpyArray('out') + self.assertTrue(arr.shape) + + def test_gdal_and_otb_np(self): + gdal_ds = gdal.Open(FILENAME) + band = gdal_ds.GetRasterBand(1) + arr = band.ReadAsArray() + app = otbApplication.Registry.CreateApplication('ExtractROI') + app.SetImageFromNumpyArray('in', arr) + app.SetParameterInt('startx', 0) + app.SetParameterInt('starty', 0) + app.SetParameterInt('sizex', 10) + app.SetParameterInt('sizey', 10) + app.Execute() + arr2 = app.GetVectorImageAsNumpyArray('out') + self.assertTrue(arr2.shape) + +if __name__ == '__main__': + unittest.main() diff --git a/test/rio_test.py b/test/rio_test.py new file mode 100644 index 0000000000000000000000000000000000000000..c6a0f2f1b4bd0f49ba68266f20005433987919ab --- /dev/null +++ b/test/rio_test.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import pytest +import unittest +import rasterio +import rasterio.features +import rasterio.warp +from test_utils import resolve_paths + +FILENAME = resolve_paths('$DATADIR/fake_spot6.jp2') + +class NumpyTest(unittest.TestCase): + + def test_rio_read_md(self): + with rasterio.open(FILENAME) as dataset: + # Read the dataset's valid data mask as a ndarray. + mask = dataset.dataset_mask() + + # Extract feature shapes and values from the array. + for geom, val in rasterio.features.shapes( + mask, transform=dataset.transform + ): + # Transform shapes from the dataset's own coordinate + # reference system to CRS84 (EPSG:4326). + geom = rasterio.warp.transform_geom( + dataset.crs, 'EPSG:4326', geom, precision=6 + ) + self.assertTrue(geom) + + + def test_import_all(self): + import otbApplication + self.assertTrue(otbApplication.Registry_GetAvailableApplications()) + import tensorflow + self.assertTrue(tensorflow.__version__) + from osgeo import gdal + self.assertTrue(gdal.__version__) + import numpy + self.assertTrue(numpy.__version__) + self.test_rio_read_md() + import otbtf + self.assertTrue(otbtf.__version__) + + +if __name__ == '__main__': + unittest.main()