kopia lustrzana https://github.com/OpenDroneMap/WebODM
Cache orthophoto bands, better support for single band orthophotos in plant health tab
rodzic
c029446f88
commit
82c027226a
|
@ -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),
|
||||
]
|
|
@ -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
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue