Cache orthophoto bands, better support for single band orthophotos in plant health tab

pull/1345/head
Piero Toffanin 2023-05-19 11:57:32 -04:00
rodzic c029446f88
commit 82c027226a
4 zmienionych plików z 84 dodań i 5 usunięć

Wyświetl plik

@ -0,0 +1,44 @@
# Generated by Django 2.2.27 on 2023-05-19 15:38
import rasterio
import os
import django.contrib.postgres.fields.jsonb
from django.db import migrations
from webodm import settings
def update_orthophoto_bands_fields(apps, schema_editor):
Task = apps.get_model('app', 'Task')
for t in Task.objects.all():
bands = []
orthophoto_path = os.path.join(settings.MEDIA_ROOT, "project", str(t.project.id), "task", str(t.id), "assets", "odm_orthophoto", "odm_orthophoto.tif")
if os.path.isfile(orthophoto_path):
try:
with rasterio.open(orthophoto_path) as f:
bands = [c.name for c in f.colorinterp]
except Exception as e:
print(e)
print("Updating {} (with orthophoto bands: {})".format(t, str(bands)))
t.orthophoto_bands = bands
t.save()
class Migration(migrations.Migration):
dependencies = [
('app', '0034_delete_imageupload'),
]
operations = [
migrations.AddField(
model_name='task',
name='orthophoto_bands',
field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=list, help_text='List of orthophoto bands', verbose_name='Orthophoto Bands'),
),
migrations.RunPython(update_orthophoto_bands_fields),
]

Wyświetl plik

@ -278,6 +278,7 @@ class Task(models.Model):
potree_scene = fields.JSONField(default=dict, blank=True, help_text=_("Serialized potree scene information used to save/load measurements and camera view angle"), verbose_name=_("Potree Scene"))
epsg = models.IntegerField(null=True, default=None, blank=True, help_text=_("EPSG code of the dataset (if georeferenced)"), verbose_name="EPSG")
tags = models.TextField(db_index=True, default="", blank=True, help_text=_("Task tags"), verbose_name=_("Tags"))
orthophoto_bands = fields.JSONField(default=list, blank=True, help_text=_("List of orthophoto bands"), verbose_name=_("Orthophoto Bands"))
class Meta:
verbose_name = _("Task")
@ -878,6 +879,7 @@ class Task(models.Model):
self.update_available_assets_field()
self.update_epsg_field()
self.update_orthophoto_bands_field()
self.potree_scene = {}
self.running_progress = 1.0
self.console_output += gettext("Done!") + "\n"
@ -899,8 +901,9 @@ class Task(models.Model):
def get_map_items(self):
types = []
if 'orthophoto.tif' in self.available_assets: types.append('orthophoto')
if 'orthophoto.tif' in self.available_assets: types.append('plant')
if 'orthophoto.tif' in self.available_assets:
types.append('orthophoto')
types.append('plant')
if 'dsm.tif' in self.available_assets: types.append('dsm')
if 'dtm.tif' in self.available_assets: types.append('dtm')
@ -919,7 +922,8 @@ class Task(models.Model):
'public': self.public,
'camera_shots': camera_shots,
'ground_control_points': ground_control_points,
'epsg': self.epsg
'epsg': self.epsg,
'orthophoto_bands': self.orthophoto_bands,
}
}
}
@ -993,6 +997,22 @@ class Task(models.Model):
if commit: self.save()
def update_orthophoto_bands_field(self, commit=False):
"""
Updates the orthophoto bands field with the correct value
:param commit: when True also saves the model, otherwise the user should manually call save()
"""
bands = []
orthophoto_path = self.assets_path(self.ASSETS_MAP['orthophoto.tif'])
if os.path.isfile(orthophoto_path):
with rasterio.open(orthophoto_path) as f:
bands = [c.name for c in f.colorinterp]
self.orthophoto_bands = bands
if commit: self.save()
def delete(self, using=None, keep_parents=False):
task_id = self.id
from app.plugins import signals as plugin_signals

Wyświetl plik

@ -126,8 +126,17 @@ class Map extends React.Component {
let metaUrl = url + "metadata";
if (type == "plant") metaUrl += "?formula=NDVI&bands=RGN&color_map=rdylgn";
if (type == "dsm" || type == "dtm") metaUrl += "?hillshade=6&color_map=viridis";
if (type == "plant"){
if (meta.task && meta.task.orthophoto_bands && meta.task.orthophoto_bands.length === 2){
// Single band, probably thermal dataset, in any case we can't render NDVI
// because it requires 3 bands
metaUrl += "?formula=Celsius&bands=L&color_map=magma";
}else{
metaUrl += "?formula=NDVI&bands=RGN&color_map=rdylgn";
}
}else if (type == "dsm" || type == "dtm"){
metaUrl += "?hillshade=6&color_map=viridis";
}
this.tileJsonRequests.push($.getJSON(metaUrl)
.done(mres => {

Wyświetl plik

@ -246,6 +246,9 @@ class TestApiTask(BootTransactionTestCase):
# EPSG should be null
self.assertTrue(task.epsg is None)
# Orthophoto bands field should be an empty list
self.assertEqual(len(task.orthophoto_bands), 0)
# tiles.json, bounds, metadata should not be accessible at this point
tile_types = ['orthophoto', 'dsm', 'dtm']
endpoints = ['tiles.json', 'bounds', 'metadata']
@ -916,6 +919,9 @@ class TestApiTask(BootTransactionTestCase):
# EPSG should be populated
self.assertEqual(task.epsg, 32615)
# Orthophoto bands should be populated
self.assertTrue(len(task.orthophoto_bands) > 0)
# Can access only tiles of available assets
res = client.get("/api/projects/{}/tasks/{}/dsm/tiles.json".format(project.id, task.id))
self.assertEqual(res.status_code, status.HTTP_200_OK)