Updated rio-tiler to v2. Added custom NDVI indexes. Started develop of cropping plugin.

pull/1063/head
teslov 2021-09-30 22:37:30 +03:00
rodzic af32e3aa29
commit e84f1e194b
2 zmienionych plików z 414 dodań i 139 usunięć

Wyświetl plik

@ -1,15 +1,19 @@
import rasterio
import json
import numpy
from rasterio.enums import ColorInterp
import urllib
import os
from django.http import HttpResponse
from rio_tiler.errors import TileOutsideBounds
from rio_tiler.mercator import get_zooms
from rio_tiler import main
from rio_tiler.utils import array_to_image, get_colormap, expression, linear_rescale, _chunks, _apply_discrete_colormap, has_alpha_band, \
from rio_tiler.utils import has_alpha_band, \
non_alpha_indexes
from rio_tiler.utils import _stats as raster_stats
from rio_tiler.models import ImageStatistics
from rio_tiler.models import Metadata as RioMetadata
from rio_tiler.profiles import img_profiles
from rio_tiler.colormap import cmap as colormap
from rio_tiler.io import COGReader
import numpy as np
from app.raster_utils import export_raster_index
@ -23,13 +27,297 @@ from worker.tasks import export_raster_index
ZOOM_EXTRA_LEVELS = 2
colormap = colormap.register(
{
"discrete_ndvi": {
0: [174, 0, 40, 255],
1: [174, 0, 40, 255],
2: [174, 0, 40, 255],
3: [174, 0, 40, 255],
4: [174, 0, 40, 255],
5: [174, 0, 40, 255],
6: [174, 0, 40, 255],
7: [174, 0, 40, 255],
8: [174, 0, 40, 255],
9: [174, 0, 40, 255],
10: [174, 0, 40, 255],
11: [174, 0, 40, 255],
12: [174, 0, 40, 255],
13: [174, 0, 40, 255],
14: [174, 0, 40, 255],
15: [174, 0, 40, 255],
16: [174, 0, 40, 255],
17: [174, 0, 40, 255],
18: [174, 0, 40, 255],
19: [174, 0, 40, 255],
20: [174, 0, 40, 255],
21: [174, 0, 40, 255],
22: [174, 0, 40, 255],
23: [174, 0, 40, 255],
24: [174, 0, 40, 255],
25: [174, 0, 40, 255],
26: [174, 0, 40, 255],
27: [174, 0, 40, 255],
28: [174, 0, 40, 255],
29: [174, 0, 40, 255],
30: [174, 0, 40, 255],
31: [174, 0, 40, 255],
32: [174, 0, 40, 255],
33: [174, 0, 40, 255],
34: [174, 0, 40, 255],
35: [174, 0, 40, 255],
36: [174, 0, 40, 255],
37: [174, 0, 40, 255],
38: [174, 0, 40, 255],
39: [174, 0, 40, 255],
40: [174, 0, 40, 255],
41: [174, 0, 40, 255],
42: [174, 0, 40, 255],
43: [174, 0, 40, 255],
44: [174, 0, 40, 255],
45: [174, 0, 40, 255],
46: [174, 0, 40, 255],
47: [174, 0, 40, 255],
48: [174, 0, 40, 255],
49: [174, 0, 40, 255],
50: [174, 0, 40, 255],
51: [254, 142, 86, 255],
52: [254, 142, 86, 255],
53: [254, 142, 86, 255],
54: [254, 142, 86, 255],
55: [254, 142, 86, 255],
56: [254, 142, 86, 255],
57: [254, 142, 86, 255],
58: [254, 142, 86, 255],
59: [254, 142, 86, 255],
60: [254, 142, 86, 255],
61: [254, 142, 86, 255],
62: [254, 142, 86, 255],
63: [254, 142, 86, 255],
64: [254, 142, 86, 255],
65: [254, 142, 86, 255],
66: [254, 142, 86, 255],
67: [254, 142, 86, 255],
68: [254, 142, 86, 255],
69: [254, 142, 86, 255],
70: [254, 142, 86, 255],
71: [254, 142, 86, 255],
72: [254, 142, 86, 255],
73: [254, 142, 86, 255],
74: [254, 142, 86, 255],
75: [254, 142, 86, 255],
76: [254, 142, 86, 255],
77: [254, 142, 86, 255],
78: [254, 142, 86, 255],
79: [254, 142, 86, 255],
80: [254, 142, 86, 255],
81: [254, 142, 86, 255],
82: [254, 142, 86, 255],
83: [254, 142, 86, 255],
84: [254, 142, 86, 255],
85: [254, 142, 86, 255],
86: [254, 142, 86, 255],
87: [254, 142, 86, 255],
88: [254, 142, 86, 255],
89: [254, 142, 86, 255],
90: [254, 142, 86, 255],
91: [254, 142, 86, 255],
92: [254, 142, 86, 255],
93: [254, 142, 86, 255],
94: [254, 142, 86, 255],
95: [254, 142, 86, 255],
96: [254, 142, 86, 255],
97: [254, 142, 86, 255],
98: [254, 142, 86, 255],
99: [254, 142, 86, 255],
100: [254, 142, 86, 255],
101: [254, 142, 86, 255],
102: [236, 246, 177, 255],
103: [236, 246, 177, 255],
104: [236, 246, 177, 255],
105: [236, 246, 177, 255],
106: [236, 246, 177, 255],
107: [236, 246, 177, 255],
108: [236, 246, 177, 255],
109: [236, 246, 177, 255],
110: [236, 246, 177, 255],
111: [236, 246, 177, 255],
112: [236, 246, 177, 255],
113: [236, 246, 177, 255],
114: [236, 246, 177, 255],
115: [236, 246, 177, 255],
116: [236, 246, 177, 255],
117: [236, 246, 177, 255],
118: [236, 246, 177, 255],
119: [236, 246, 177, 255],
120: [236, 246, 177, 255],
121: [236, 246, 177, 255],
122: [236, 246, 177, 255],
123: [236, 246, 177, 255],
124: [236, 246, 177, 255],
125: [236, 246, 177, 255],
126: [236, 246, 177, 255],
127: [236, 246, 177, 255],
128: [236, 246, 177, 255],
129: [236, 246, 177, 255],
130: [236, 246, 177, 255],
131: [236, 246, 177, 255],
132: [236, 246, 177, 255],
133: [236, 246, 177, 255],
134: [236, 246, 177, 255],
135: [236, 246, 177, 255],
136: [236, 246, 177, 255],
137: [236, 246, 177, 255],
138: [236, 246, 177, 255],
139: [236, 246, 177, 255],
140: [236, 246, 177, 255],
141: [236, 246, 177, 255],
142: [236, 246, 177, 255],
143: [236, 246, 177, 255],
144: [236, 246, 177, 255],
145: [236, 246, 177, 255],
146: [236, 246, 177, 255],
147: [236, 246, 177, 255],
148: [236, 246, 177, 255],
149: [236, 246, 177, 255],
150: [236, 246, 177, 255],
151: [236, 246, 177, 255],
152: [236, 246, 177, 255],
153: [84, 188, 108, 255],
154: [1, 126, 71, 255],
155: [1, 126, 71, 255],
156: [1, 126, 71, 255],
157: [1, 126, 71, 255],
158: [1, 126, 71, 255],
159: [1, 126, 71, 255],
160: [1, 126, 71, 255],
161: [1, 126, 71, 255],
162: [1, 126, 71, 255],
163: [1, 126, 71, 255],
164: [1, 126, 71, 255],
165: [1, 126, 71, 255],
166: [1, 126, 71, 255],
167: [1, 126, 71, 255],
168: [1, 126, 71, 255],
169: [1, 126, 71, 255],
170: [1, 126, 71, 255],
171: [1, 126, 71, 255],
172: [1, 126, 71, 255],
173: [1, 126, 71, 255],
174: [1, 126, 71, 255],
175: [1, 126, 71, 255],
176: [1, 126, 71, 255],
177: [1, 126, 71, 255],
178: [1, 126, 71, 255],
179: [1, 126, 71, 255],
180: [1, 126, 71, 255],
181: [1, 126, 71, 255],
182: [1, 126, 71, 255],
183: [1, 126, 71, 255],
184: [1, 126, 71, 255],
185: [1, 126, 71, 255],
186: [1, 126, 71, 255],
187: [1, 126, 71, 255],
188: [1, 126, 71, 255],
189: [1, 126, 71, 255],
190: [1, 126, 71, 255],
191: [1, 126, 71, 255],
192: [1, 126, 71, 255],
193: [1, 126, 71, 255],
194: [1, 126, 71, 255],
195: [1, 126, 71, 255],
196: [1, 126, 71, 255],
197: [1, 126, 71, 255],
198: [1, 126, 71, 255],
199: [1, 126, 71, 255],
200: [1, 126, 71, 255],
201: [1, 126, 71, 255],
202: [1, 126, 71, 255],
203: [1, 126, 71, 255],
204: [1, 126, 71, 255],
205: [1, 126, 71, 255],
206: [1, 126, 71, 255],
207: [1, 126, 71, 255],
208: [1, 126, 71, 255],
209: [1, 126, 71, 255],
210: [1, 126, 71, 255],
211: [1, 126, 71, 255],
212: [1, 126, 71, 255],
213: [1, 126, 71, 255],
214: [1, 126, 71, 255],
215: [1, 126, 71, 255],
216: [1, 126, 71, 255],
217: [1, 126, 71, 255],
218: [1, 126, 71, 255],
219: [1, 126, 71, 255],
220: [1, 126, 71, 255],
221: [1, 126, 71, 255],
222: [1, 126, 71, 255],
223: [1, 126, 71, 255],
224: [1, 126, 71, 255],
225: [1, 126, 71, 255],
226: [1, 126, 71, 255],
227: [1, 126, 71, 255],
228: [1, 126, 71, 255],
229: [1, 126, 71, 255],
230: [1, 126, 71, 255],
231: [1, 126, 71, 255],
232: [1, 126, 71, 255],
233: [1, 126, 71, 255],
234: [1, 126, 71, 255],
235: [1, 126, 71, 255],
236: [1, 126, 71, 255],
237: [1, 126, 71, 255],
238: [1, 126, 71, 255],
239: [1, 126, 71, 255],
240: [1, 126, 71, 255],
241: [1, 126, 71, 255],
242: [1, 126, 71, 255],
243: [1, 126, 71, 255],
244: [1, 126, 71, 255],
245: [1, 126, 71, 255],
246: [1, 126, 71, 255],
247: [1, 126, 71, 255],
248: [1, 126, 71, 255],
249: [1, 126, 71, 255],
250: [1, 126, 71, 255],
251: [1, 126, 71, 255],
252: [1, 126, 71, 255],
253: [1, 126, 71, 255],
254: [1, 126, 71, 255],
255: [1, 126, 71, 255]
}
}
)
colormap = colormap.register({
"better_discrete_ndvi": {
0: [174, 0, 40, 255],
17: [223, 45, 44, 255],
34: [254, 109, 72, 255],
51: [254, 199, 125, 255],
68: [255, 223, 146, 255],
85: [255, 239, 173, 255],
102: [234, 248, 171, 255],
119: [212, 240, 148, 255],
136: [182, 227, 136, 255],
153: [155, 216, 114, 255],
170: [120, 202, 111, 255],
187: [121, 200, 115, 255],
204: [83, 189, 108, 255],
221: [22, 170, 94, 255],
238: [0, 151, 84, 255],
255: [1, 126, 71, 255],
}
})
def get_zoom_safe(src_dst):
minzoom, maxzoom = get_zooms(src_dst)
minzoom, maxzoom = src_dst.spatial_info["minzoom"], src_dst.spatial_info["maxzoom"]
if maxzoom < minzoom:
maxzoom = minzoom
return minzoom, maxzoom
def get_tile_url(task, tile_type, query_params):
url = '/api/projects/{}/tasks/{}/{}/tiles/{{z}}/{{x}}/{{y}}.png'.format(task.project.id, task.id, tile_type)
params = {}
@ -43,13 +331,13 @@ def get_tile_url(task, tile_type, query_params):
return url
def get_extent(task, tile_type):
extent_map = {
'orthophoto': task.orthophoto_extent,
'dsm': task.dsm_extent,
'dtm': task.dtm_extent,
}
if not tile_type in extent_map:
raise exceptions.NotFound()
@ -60,47 +348,11 @@ def get_extent(task, tile_type):
return extent
def get_raster_path(task, tile_type):
return task.get_asset_download_path(tile_type + ".tif")
def rescale_tile(tile, mask, rescale = None):
if rescale:
try:
rescale_arr = list(map(float, rescale.split(",")))
except ValueError:
raise exceptions.ValidationError("Invalid rescale value")
rescale_arr = list(_chunks(rescale_arr, 2))
if len(rescale_arr) != tile.shape[0]:
rescale_arr = ((rescale_arr[0]),) * tile.shape[0]
for bdx in range(tile.shape[0]):
if mask is not None:
tile[bdx] = np.where(
mask,
linear_rescale(
tile[bdx], in_range=rescale_arr[bdx], out_range=[0, 255]
),
0,
)
else:
tile[bdx] = linear_rescale(
tile[bdx], in_range=rescale_arr[bdx], out_range=[0, 255]
)
tile = tile.astype(np.uint8)
return tile, mask
def apply_colormap(tile, color_map = None):
if color_map is not None and isinstance(color_map, dict):
tile = _apply_discrete_colormap(tile, color_map)
elif color_map is not None:
tile = np.transpose(color_map[tile][0], [2, 0, 1]).astype(np.uint8)
return tile
class TileJson(TaskNestedView):
def get(self, request, pk=None, project_pk=None, tile_type=""):
"""
@ -112,8 +364,8 @@ class TileJson(TaskNestedView):
if not os.path.isfile(raster_path):
raise exceptions.NotFound()
with rasterio.open(raster_path) as src_dst:
minzoom, maxzoom = get_zoom_safe(src_dst)
with COGReader(raster_path) as src:
minzoom, maxzoom = get_zoom_safe(src)
return Response({
'tilejson': '2.1.0',
@ -126,6 +378,7 @@ class TileJson(TaskNestedView):
'bounds': get_extent(task, tile_type).extent
})
class Bounds(TaskNestedView):
def get(self, request, pk=None, project_pk=None, tile_type=""):
"""
@ -138,13 +391,13 @@ class Bounds(TaskNestedView):
'bounds': get_extent(task, tile_type).extent
})
class Metadata(TaskNestedView):
def get(self, request, pk=None, project_pk=None, tile_type=""):
"""
Get the metadata for this tasks's asset type
"""
task = self.get_and_check_task(request, pk)
formula = self.request.query_params.get('formula')
bands = self.request.query_params.get('bands')
@ -161,19 +414,34 @@ class Metadata(TaskNestedView):
if not os.path.isfile(raster_path):
raise exceptions.NotFound()
try:
with rasterio.open(raster_path, "r") as src:
band_count = src.meta['count']
if has_alpha_band(src):
with COGReader(raster_path) as src:
band_count = src.metadata()['count']
if has_alpha_band(src.dataset):
band_count -= 1
nodata = None
# Workaround for https://github.com/OpenDroneMap/WebODM/issues/894
if tile_type == 'orthophoto':
nodata = 0
info = main.metadata(src, pmin=pmin, pmax=pmax, histogram_bins=255, histogram_range=hrange, expr=expr, nodata=nodata)
# info = src.metadata(pmin=pmin, pmax=pmax, histogram_bins=255, histogram_range=hrange, expr=expr,
# nodata=nodata)
histogram_options = {"bins": 255, "range": hrange}
metadata = src.metadata(pmin=pmin, pmax=pmax, hist_options=histogram_options, nodata=nodata)
if expr is not None:
data, mask = src.preview(expression=expr)
data = numpy.ma.array(data)
data.mask = mask == 0
expression_bloc = expr.lower().split(",")
stats = {
f"{expression_bloc[b]}": raster_stats(data[b], percentiles=(2, 98))
for b in range(data.shape[0])
}
stats = {b: ImageStatistics(**s) for b, s in stats.items()}
metadata = RioMetadata(statistics=stats, **src.info().dict())
print(metadata)
print(metadata.json())
info = json.loads(metadata.json())
except IndexError as e:
# Caught when trying to get an invalid raster metadata
raise exceptions.ValidationError("Cannot retrieve raster metadata: %s" % str(e))
@ -191,6 +459,9 @@ class Metadata(TaskNestedView):
"rdylgn": "RdYlGn",
"rdylgn_r": "RdYlGn (Reverse)",
"spectral": "Spectral",
"discrete_ndvi": "Contrast NDVI",
"better_discrete_ndvi": "Custom NDVI Index",
"rplumbo": "Rplumbo (Better NDVI)",
"spectral_r": "Spectral (Reverse)",
"pastel1": "Pastel",
}
@ -200,7 +471,8 @@ class Metadata(TaskNestedView):
if tile_type in ['dsm', 'dtm']:
colormaps = ['jet', 'terrain', 'gist_earth', 'pastel1']
elif formula and bands:
colormaps = ['rdylgn', 'spectral', 'rdylgn_r', 'spectral_r']
colormaps = ['rdylgn', 'spectral', 'rdylgn_r', 'spectral_r', 'rplumbo', 'discrete_ndvi',
'better_discrete_ndvi']
algorithms = *get_algorithm_list(band_count),
info['color_maps'] = []
@ -211,13 +483,12 @@ class Metadata(TaskNestedView):
try:
info['color_maps'].append({
'key': cmap,
'color_map': get_colormap(cmap, format="gdal"),
'color_map': colormap.get(cmap).values(),
'label': cmap_labels.get(cmap, cmap)
})
except FileNotFoundError:
raise exceptions.ValidationError("Not a valid color_map value: %s" % cmap)
del info['address']
info['name'] = task.name
info['scheme'] = 'xyz'
info['tiles'] = [get_tile_url(task, tile_type, self.request.query_params)]
@ -226,41 +497,40 @@ class Metadata(TaskNestedView):
info['maxzoom'] = info['minzoom']
info['maxzoom'] += ZOOM_EXTRA_LEVELS
info['minzoom'] -= ZOOM_EXTRA_LEVELS
info['bounds'] = {'value': src.bounds, 'crs': src.dataset.crs}
return Response(info)
def get_elevation_tiles(elevation, url, x, y, z, tilesize, nodata, resampling, padding):
tile = np.full((tilesize * 3, tilesize * 3), nodata, dtype=elevation.dtype)
with COGReader(url) as src:
try:
left, _ = src.tile(x - 1, y, z, indexes=1, tilesize=tilesize, nodata=nodata,
resampling_method=resampling, padding=padding)
tile[tilesize:tilesize * 2, 0:tilesize] = left
except TileOutsideBounds:
pass
try:
left, _ = main.tile(url, x - 1, y, z, indexes=1, tilesize=tilesize, nodata=nodata,
resampling_method=resampling, tile_edge_padding=padding)
tile[tilesize:tilesize*2,0:tilesize] = left
except TileOutsideBounds:
pass
try:
right, _ = src.tile(x + 1, y, z, indexes=1, tilesize=tilesize, nodata=nodata,
resampling_method=resampling, padding=padding)
tile[tilesize:tilesize * 2, tilesize * 2:tilesize * 3] = right
except TileOutsideBounds:
pass
try:
bottom, _ = src.tile(x, y + 1, z, indexes=1, tilesize=tilesize, nodata=nodata,
resampling_method=resampling, padding=padding)
tile[tilesize * 2:tilesize * 3, tilesize:tilesize * 2] = bottom
except TileOutsideBounds:
pass
try:
top, _ = src.tile(x, y - 1, z, indexes=1, tilesize=tilesize, nodata=nodata,
resampling_method=resampling, padding=padding)
tile[0:tilesize, tilesize:tilesize * 2] = top
except TileOutsideBounds:
pass
try:
right, _ = main.tile(url, x + 1, y, z, indexes=1, tilesize=tilesize, nodata=nodata,
resampling_method=resampling, tile_edge_padding=padding)
tile[tilesize:tilesize*2,tilesize*2:tilesize*3] = right
except TileOutsideBounds:
pass
try:
bottom, _ = main.tile(url, x, y + 1, z, indexes=1, tilesize=tilesize, nodata=nodata,
resampling_method=resampling, tile_edge_padding=padding)
tile[tilesize*2:tilesize*3,tilesize:tilesize*2] = bottom
except TileOutsideBounds:
pass
try:
top, _ = main.tile(url, x, y - 1, z, indexes=1, tilesize=tilesize, nodata=nodata,
resampling_method=resampling, tile_edge_padding=padding)
tile[0:tilesize,tilesize:tilesize*2] = top
except TileOutsideBounds:
pass
tile[tilesize:tilesize*2,tilesize:tilesize*2] = elevation
tile[tilesize:tilesize * 2, tilesize:tilesize * 2] = elevation
return tile
@ -315,67 +585,63 @@ class Tiles(TaskNestedView):
if nodata is not None:
nodata = np.nan if nodata == "nan" else float(nodata)
tilesize = scale * 256
url = get_raster_path(task, tile_type)
with COGReader(url) as src:
if not src.tile_exists(z, x, y):
raise exceptions.NotFound("Outside of bounds")
if not os.path.isfile(url):
raise exceptions.NotFound()
with rasterio.open(url) as src:
with COGReader(url) as src:
minzoom, maxzoom = get_zoom_safe(src)
has_alpha = has_alpha_band(src)
has_alpha = has_alpha_band(src.dataset)
if z < minzoom - ZOOM_EXTRA_LEVELS or z > maxzoom + ZOOM_EXTRA_LEVELS:
raise exceptions.NotFound()
# Handle N-bands datasets for orthophotos (not plant health)
if tile_type == 'orthophoto' and expr is None:
ci = src.colorinterp
ci = src.dataset.colorinterp
# More than 4 bands?
if len(ci) > 4:
# Try to find RGBA band order
if ColorInterp.red in ci and \
ColorInterp.green in ci and \
ColorInterp.blue in ci:
ColorInterp.green in ci and \
ColorInterp.blue in ci:
indexes = (ci.index(ColorInterp.red) + 1,
ci.index(ColorInterp.green) + 1,
ci.index(ColorInterp.blue) + 1,)
else:
# Fallback to first three
indexes = (1, 2, 3, )
indexes = (1, 2, 3,)
elif has_alpha:
indexes = non_alpha_indexes(src)
indexes = non_alpha_indexes(src.dataset)
# Workaround for https://github.com/OpenDroneMap/WebODM/issues/894
if nodata is None and tile_type =='orthophoto':
if nodata is None and tile_type == 'orthophoto':
nodata = 0
resampling="nearest"
padding=0
resampling = "nearest"
padding = 0
if tile_type in ["dsm", "dtm"]:
resampling="bilinear"
padding=16
resampling = "bilinear"
padding = 16
try:
if expr is not None:
tile, mask = expression(
url, x, y, z, expr=expr, tilesize=tilesize, nodata=nodata, tile_edge_padding=padding, resampling_method=resampling
)
else:
tile, mask = main.tile(
url, x, y, z, indexes=indexes, tilesize=tilesize, nodata=nodata, tile_edge_padding=padding, resampling_method=resampling
)
with COGReader(url) as src:
if expr is not None:
tile = src.tile(x, y, z, expression=expr, tilesize=tilesize, nodata=nodata,
padding=padding,
resampling_method=resampling)
else:
tile = src.tile(x, y, z, indexes=indexes, tilesize=tilesize, nodata=nodata,
padding=padding, resampling_method=resampling)
except TileOutsideBounds:
raise exceptions.NotFound("Outside of bounds")
if color_map:
try:
color_map = get_colormap(color_map, format="gdal")
colormap.get(color_map)
except FileNotFoundError:
raise exceptions.ValidationError("Not a valid color_map value")
intensity = None
if hillshade is not None:
try:
hillshade = float(hillshade)
@ -385,7 +651,8 @@ class Tiles(TaskNestedView):
raise exceptions.ValidationError("Invalid hillshade value")
if tile.shape[0] != 1:
raise exceptions.ValidationError("Cannot compute hillshade of non-elevation raster (multiple bands found)")
raise exceptions.ValidationError(
"Cannot compute hillshade of non-elevation raster (multiple bands found)")
delta_scale = (maxzoom + ZOOM_EXTRA_LEVELS + 1 - z) * 4
dx = src.meta["transform"][0] * delta_scale
@ -397,26 +664,34 @@ class Tiles(TaskNestedView):
# requires neighbor tiles to be rendered seamlessly
elevation = get_elevation_tiles(tile[0], url, x, y, z, tilesize, nodata, resampling, padding)
intensity = ls.hillshade(elevation, dx=dx, dy=dy, vert_exag=hillshade)
intensity = intensity[tilesize:tilesize*2,tilesize:tilesize*2]
rgb, rmask = rescale_tile(tile, mask, rescale=rescale)
rgb = apply_colormap(rgb, color_map)
intensity = intensity[tilesize:tilesize * 2, tilesize:tilesize * 2]
if intensity is not None:
# Quick check
if rgb.shape[0] != 3:
raise exceptions.ValidationError("Cannot process tile: intensity image provided, but no RGB data was computed.")
if tile.data.shape[0] != 3:
raise exceptions.ValidationError(
"Cannot process tile: intensity image provided, but no RGB data was computed.")
intensity = intensity * 255.0
rgb = hsv_blend(rgb, intensity)
rgb = hsv_blend(tile.data, intensity)
options = img_profiles.get(driver, {})
rescale_arr = tuple(map(float, rescale.split(",")))
if color_map is not None and isinstance(color_map, dict):
return HttpResponse(
tile.post_process(in_range=(rescale_arr,)).render(img_format=driver, colormap=color_map, **options),
content_type="image/{}".format(ext)
)
elif color_map is not None:
return HttpResponse(
tile.post_process(in_range=(rescale_arr,)).render(img_format=driver, colormap=colormap.get(color_map),
**options),
content_type="image/{}".format(ext)
)
return HttpResponse(
array_to_image(rgb, rmask, img_format=driver, **options),
tile.post_process(in_range=(rescale_arr,)).render(img_format=driver, **options),
content_type="image/{}".format(ext)
)
class Export(TaskNestedView):
def post(self, request, pk=None, project_pk=None):
"""
@ -452,4 +727,4 @@ class Export(TaskNestedView):
raise exceptions.NotFound()
celery_task_id = export_raster_index.delay(url, expr).task_id
return Response({'celery_task_id': celery_task_id})
return Response({'celery_task_id': celery_task_id})

Wyświetl plik

@ -20,7 +20,7 @@ djangorestframework==3.9.1
djangorestframework-jwt==1.9.0
drf-nested-routers==0.11.1
funcsigs==1.0.2
futures==3.0.5
futures==3.1.1
geojson==2.3.0
gunicorn==19.7.1
itypes==1.1.0
@ -32,10 +32,10 @@ openapi-codec==1.1.7
packaging==16.8
piexif==1.0.13
pilkit==2.0
Pillow==6.2.2
Pillow==8.3.2
pip-autoremove==0.9.0
psycopg2==2.8.4
psycopg2-binary==2.8.4
psycopg2==2.8.6
psycopg2-binary==2.8.6
PyJWT==1.5.3
pyodm==1.5.6
pyparsing==2.1.10
@ -53,13 +53,13 @@ tzlocal==1.3
uritemplate==3.0.0
vine==1.3.0
webcolors==1.5
-e git://github.com/OpenDroneMap/rio-tiler.git#egg=rio-tiler
rio-color==1.0.0
rio-cogeo==1.1.8
rasterio==1.1.5 ; sys_platform == 'linux' or sys_platform == 'darwin'
https://download.lfd.uci.edu/pythonlibs/s2jqpv5t/rasterio-1.1.3-cp37-cp37m-win_amd64.whl ; sys_platform == "win32"
https://download.lfd.uci.edu/pythonlibs/s2jqpv5t/GDAL-3.0.4-cp37-cp37m-win_amd64.whl ; sys_platform == "win32"
rio-tiler==2.1.2
rio-color==1.0.4
rio-cogeo==2.3.1
rasterio==1.2.8
Shapely==1.7.0 ; sys_platform == "win32"
eventlet==0.25.1 ; sys_platform == "win32"
pyopenssl==19.1.0 ; sys_platform == "win32"
numpy==1.21.1
numpy==1.21.1
urllib3~=1.24.1
numexpr~=2.7.3