Commit 4e688168 authored by PACANOWSKI Romain's avatar PACANOWSKI Romain
Browse files

Merge branch 'gf_np2envi_py' into 'master'

Add python tool to convert numpy array to envi spectral image

See merge request mrf-devteam/mrf!252
parents f2bedefc 7cd99513
Pipeline #525539 failed with stages
in 34 minutes and 56 seconds
#########################################################################################
#
# Auteur: Pierre Hubert-Brierre - Gary Fourneau Copyright INRIA : 2021-2022
#
#########################################################################################
import warnings
import numpy as np
class Header(object):
"""
Header de l'image spectrale
"""
def __init__(self):
self.desc = ""
self.width = 0
self.height = 0
self.bands = 0
self.interleave = ""
self.data_type = 0
self.byte_order = ""
self.waves = []
self.path = ""
def __copy__(self):
cls = self.__class__
result = cls.__new__(cls)
result.__dict__.update(self.__dict__)
return result
def __add__(self, other):
if self.width != other.width:
return None
if self.height != other.height:
return None
if self.interleave != other.interleave:
return None
if self.data_type != other.data_type:
return None
if self.byte_order != other.byte_order:
return None
header = Header()
header.desc = self.desc + "\n" + other.desc
header.width = self.width
header.height = self.height
header.interleave = self.interleave
header.data_type = self.data_type
header.byte_order = self.byte_order
header.waves = self.waves + other.waves
header.bands = self.bands + other.bands
return header
def write_file(self):
with open(self.path, "w") as file:
file.write("ENVI\n")
file.write(f"description = {self.desc}")
file.write("file type = ENVI \n")
file.write("sensor type = \n")
file.write(f"interleave = {self.interleave}\n")
file.write(f"samples = {self.width}\n")
file.write(f"lines = {self.height}\n")
file.write(f"bands = {self.bands}\n")
file.write(f"data type = {self.data_type}\n")
file.write(f"byte order = {self.byte_order}\n")
file.write(f"header offset = 0\n")
file.write("x start = 0\n")
file.write("y start = 0\n")
file.write("errors = {none}\n")
file.write("Wavelength = {\n")
for w in self.waves:
file.write(f"{w}\n")
file.write("}\n")
class SpectralImage(object):
"""
Object decrivant l'image spectrale
"""
def __init__(self, first_image):
# Pour initialiser la structure, il faut une premiere image a placer
self.header = Header()
height, width = first_image.shape
self.header.width = width
self.header.height = height
self.header.bands = 1
self.header.interleave = "bsq"
self.header.data_type = 4
self.header.byte_order = 0
self.data = np.zeros([1, height, width], np.single)
self.data[0] = first_image
def add_image(self, image):
# permet d'empiler des images, TOUTES LES IMAGES DOIVENT AVOIR LES MEMES DIMENSIONS
h, w = image.shape
image.shape = (1, h, w)
self.data = np.concatenate((self.data, image), axis=0)
image.shape = (h, w)
self.header.bands += 1
def export(self, file, wl_list=None):
# exporte les donnees au format envi
if (self.header.bands < 3): warnings.warn("L'image spectrale a moins de 2 canaux, elle ne pourra pas etre lue")
self.header.bands = max(self.header.bands, 3)
if type(wl_list) == type(None):
self.header.waves = list(range(self.header.bands))
else:
if (len(wl_list) != len(self.data)):
warnings.warn("wl_list n'a pas la bonne taille wl_list de taille :", len(wl_list), "taille attendue :",
len(self.data))
self.header.waves = list(range(self.header.bands))
else:
self.header.waves = wl_list
self.header.path = file + ".hdr"
self.header.write_file()
self.data.tofile(file + ".raw")
# fonction pour interchanger les axes.
# il est conseille de n'utiliser ces fonctions qu'après avoir insere toutes les images
def swap_axis_0_1(self):
# echange le premier et deuxieme axe
self.data = np.moveaxis(self.data, 0, 1)
self.header.bands, self.header.height = self.header.height, self.header.bands
def swap_axis_1_2(self):
# echange le deuxieme et troisieme axe
self.data = np.moveaxis(self.data, 1, 2)
self.header.width, self.header.height = self.header.height, self.header.width
def swap_axis_2_0(self):
# echange le premier et troisieme axe
self.data = np.moveaxis(self.data, 1, 0)
self.data = np.moveaxis(self.data, 1, 2)
self.data = np.moveaxis(self.data, 1, 0)
self.header.bands, self.header.width, = self.header.width, self.header.bands
def export_array(spectral_array, filename, wl_list, **kwargs):
"""input :
- spectral_array : 3D numpy array of size Nb_wl x height x width
- filename : name of the file created, without extension
- wl_list : list or 1D array containing the different wavelengths used, must be of length Nb_wl
- **kgwars : 'desc' : description of the image, 'interleave', 'data_type' (4 = 32bit float; 5 = 64bit float), 'byte_order'
Create a .hdr and a .raw files describing a .envi spectral image from a 3D numpy array
"""
shape = spectral_array.shape
image = SpectralImage(spectral_array[0,:,:])
for key in ('desc', 'interleave', 'data_type', 'byte_order'):
if key in kwargs:
setattr(image.header,key,kwargs[key])
for i in range(shape[0]-1):
image.add_image(spectral_array[i+1,:,:])
image.export(filename,wl_list)
import np2envi as envi
import numpy as np
def main():
A = np.zeros((100,20,50)) #black image, 100 wl, heigth = 20, width = 50
A[50,10,:] = 1
envi.export_array(A,"test",range(600,700),data_type = 5) # create envi image
if __name__ =="__main__" :
main()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment