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"))
|
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")
|
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"))
|
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:
|
class Meta:
|
||||||
verbose_name = _("Task")
|
verbose_name = _("Task")
|
||||||
|
@ -878,6 +879,7 @@ class Task(models.Model):
|
||||||
|
|
||||||
self.update_available_assets_field()
|
self.update_available_assets_field()
|
||||||
self.update_epsg_field()
|
self.update_epsg_field()
|
||||||
|
self.update_orthophoto_bands_field()
|
||||||
self.potree_scene = {}
|
self.potree_scene = {}
|
||||||
self.running_progress = 1.0
|
self.running_progress = 1.0
|
||||||
self.console_output += gettext("Done!") + "\n"
|
self.console_output += gettext("Done!") + "\n"
|
||||||
|
@ -899,8 +901,9 @@ class Task(models.Model):
|
||||||
|
|
||||||
def get_map_items(self):
|
def get_map_items(self):
|
||||||
types = []
|
types = []
|
||||||
if 'orthophoto.tif' in self.available_assets: types.append('orthophoto')
|
if 'orthophoto.tif' in self.available_assets:
|
||||||
if 'orthophoto.tif' in self.available_assets: types.append('plant')
|
types.append('orthophoto')
|
||||||
|
types.append('plant')
|
||||||
if 'dsm.tif' in self.available_assets: types.append('dsm')
|
if 'dsm.tif' in self.available_assets: types.append('dsm')
|
||||||
if 'dtm.tif' in self.available_assets: types.append('dtm')
|
if 'dtm.tif' in self.available_assets: types.append('dtm')
|
||||||
|
|
||||||
|
@ -919,7 +922,8 @@ class Task(models.Model):
|
||||||
'public': self.public,
|
'public': self.public,
|
||||||
'camera_shots': camera_shots,
|
'camera_shots': camera_shots,
|
||||||
'ground_control_points': ground_control_points,
|
'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()
|
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):
|
def delete(self, using=None, keep_parents=False):
|
||||||
task_id = self.id
|
task_id = self.id
|
||||||
from app.plugins import signals as plugin_signals
|
from app.plugins import signals as plugin_signals
|
||||||
|
|
|
@ -126,8 +126,17 @@ class Map extends React.Component {
|
||||||
|
|
||||||
let metaUrl = url + "metadata";
|
let metaUrl = url + "metadata";
|
||||||
|
|
||||||
if (type == "plant") metaUrl += "?formula=NDVI&bands=RGN&color_map=rdylgn";
|
if (type == "plant"){
|
||||||
if (type == "dsm" || type == "dtm") metaUrl += "?hillshade=6&color_map=viridis";
|
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)
|
this.tileJsonRequests.push($.getJSON(metaUrl)
|
||||||
.done(mres => {
|
.done(mres => {
|
||||||
|
|
|
@ -246,6 +246,9 @@ class TestApiTask(BootTransactionTestCase):
|
||||||
# EPSG should be null
|
# EPSG should be null
|
||||||
self.assertTrue(task.epsg is None)
|
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
|
# tiles.json, bounds, metadata should not be accessible at this point
|
||||||
tile_types = ['orthophoto', 'dsm', 'dtm']
|
tile_types = ['orthophoto', 'dsm', 'dtm']
|
||||||
endpoints = ['tiles.json', 'bounds', 'metadata']
|
endpoints = ['tiles.json', 'bounds', 'metadata']
|
||||||
|
@ -916,6 +919,9 @@ class TestApiTask(BootTransactionTestCase):
|
||||||
# EPSG should be populated
|
# EPSG should be populated
|
||||||
self.assertEqual(task.epsg, 32615)
|
self.assertEqual(task.epsg, 32615)
|
||||||
|
|
||||||
|
# Orthophoto bands should be populated
|
||||||
|
self.assertTrue(len(task.orthophoto_bands) > 0)
|
||||||
|
|
||||||
# Can access only tiles of available assets
|
# Can access only tiles of available assets
|
||||||
res = client.get("/api/projects/{}/tasks/{}/dsm/tiles.json".format(project.id, task.id))
|
res = client.get("/api/projects/{}/tasks/{}/dsm/tiles.json".format(project.id, task.id))
|
||||||
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
||||||
|
|
Ładowanie…
Reference in New Issue