Lisez les données de Shizuoka Prefecture Point Cloud DB avec Java et essayez de détecter la hauteur de l'arbre.

■ Aperçu

À partir de l'image PNG d'élévation créée dans "Lire les données de la base de données du nuage de points de la préfecture de Shizuoka avec Java et générer une photographie aérienne et une élévation PNG." , "Création de données sur la hauteur des arbres à l'aide de données de levés aériens au laser" présenté au National Land Research Institute Essayez de détecter la canopée.

■ Création d'un DEM estimé

Le PNG d'élévation créé dans "Lire les données de la base de données de nuage de points de la préfecture de Shizuoka avec Java et générer une photographie aérienne et un PNG d'élévation." est DSM. Puisqu'il semble correspondre à (modèle numérique de surface), il est nécessaire d'extraire les données de la partie terrain à partir d'ici. En regardant le "Aerial Laser Survey Mechanism" sur le site Web de l'Institut national de recherche foncière, dans la zone forestière, le laser est bloqué par des arbres et autres et se trouve au sol. Il peut ne pas atteindre et il semble que cela puisse arriver. Pour cette raison, cette fois, nous avons défini un maillage de 2 m pour l'élévation PNG et avons considéré le point avec l'élévation la plus basse dans chaque maillage comme l'élévation de la surface du sol. J'ai créé la classe DemMeshImterpolationProcesser suivante et généré un PNG d'élévation équivalent à DEM. ImageProcessingObservable est une interface observable pour vérifier la progression.

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Observable;
import javax.imageio.ImageIO;

public class DemMeshImterpolationProcesser extends Observable implements ImageProcessingObservable{
	private double[][] dem;
	private Cell[][] cell;
	private BufferedImage image;
	private String message;

	public DemMeshImterpolationProcesser(BufferedImage img){
		dem=ElevationPngUtil.imgToDouble(img);
		image=new BufferedImage(img.getWidth(),img.getHeight(),BufferedImage.TYPE_INT_RGB);
	}

	public BufferedImage getImage(){
		return image;
	}

	public void drawMinH(){
		for(int i=0;i<cell.length;i++){
			for(int j=0;j<cell[i].length;j++){
				cell[i][j].setRGB(ElevationPngUtil.getRGB(cell[i][j].getMinH()));
			}
		}
	}

	public void createImageCell(int size){
		int ww=dem.length;
		int hh=dem[0].length;
		cell=new Cell[ww/size][hh/size];
		int x=0;
		int y=0;
		for(int i=0;i<cell.length;i++){
			for(int j=0;j<cell[i].length;j++){
				cell[i][j]=new Cell();
				cell[i][j].x=new int[size];
				cell[i][j].y=new int[size];
				for(int m=0;m<size;m++){
					cell[i][j].y[m]=y;
					y=(y+1)%hh;
				}
				for(int m=0;m<size;m++){
					cell[i][j].x[m]=x+m;
				}
				if(y==0)x=x+size;
			}
		}
	}

	public void output(File f)throws Exception{
		ImageIO.write(image, "png", f);
 update ("Fin de sortie");
	}

	protected void update(String mes){
		message=mes;
		setChanged();
		notifyObservers();
	}

	@Override
	public String progress() {
		return message;
	}

	protected class Cell{
		int[] x;
		int[] y;

		double getMinH(){
			double min=Double.MAX_VALUE;
			for(int i=0;i<x.length;i++){
				for(int j=0;j<y.length;j++){
 					if(Double.isNaN(dem[x[i]][y[j]])||dem[x[i]][y[j]]<0)continue;
					min=Math.min(min, dem[x[i]][y[j]]);
				}
			}
			if(min==Double.MAX_VALUE){
				return 0;
			}else{
				return min;
			}
		}

		void setRGB(int rgb){
			for(int i=0;i<x.length;i++){
				for(int j=0;j<y.length;j++){
					image.setRGB(x[i], y[j], rgb);
				}
			}
		}
	}
}

Il s'agit du PNG d'élévation DEM généré ci-dessus. (Ce qui suit est un JPG de taille réduite.) Après avoir généré le PNG d'élévation, il a été lissé avec un filtre Garcian 5x5.

■ Création d'un DSM estimé

Comme il y a beaucoup de pixels sans données dans le PNG d'élévation créé la dernière fois, j'ai généré un TIN et je l'ai interpolé. «Tinfour» a été utilisé pour créer et interpoler le TIN. La licence pour «Tinfour» est «la licence Apache, version 2.0».

	/**
 * Génération TIN
	 */
	public void process(){
		for(int i=0;i<img.getWidth();i++){
			for(int j=0;j<img.getHeight();j++){
				int rgb=img.getRGB(i, j);
				double hh=ElevationPngUtil.getZ(rgb);
				if(Double.isNaN(hh))continue;
				Vertex v=new Vertex(i,j,hh,index++);
				list.add(v);
			}
		}
		tin=new IncrementalTin();
		tin.add(list, null);
	}

	/**
 * Interpolation par TIN
	 * @return
	 */
	public BufferedImage interpolation(){
		BufferedImage ret=new BufferedImage(img.getWidth(),img.getHeight(),BufferedImage.TYPE_INT_RGB);
		setInitVal(ret);
		TriangularFacetInterpolator tfi=new TriangularFacetInterpolator(tin);
		VertexValuatorDefault vvd=new VertexValuatorDefault();
		double n=img.getWidth()*img.getHeight();
		for(int i=0;i<img.getWidth();i++){
			for(int j=0;j<img.getHeight();j++){
				double hh=tfi.interpolate(i, j, vvd);
				if(hh>0)ret.setRGB(i, j, ElevationPngUtil.getRGB(hh));
			}
		}
		return ret;
	}

L'élévation DSM PNG interne en couches par TIN est la suivante. (Ce qui suit est un JPG de taille réduite.)

■ Création d'un DCHM estimé

Le modèle d'élévation (DCHM) de la hauteur des arbres, etc. est obtenu en soustrayant DEM de DSM. Le PNG d'élévation DCHM créé en soustrayant les données d'élévation DEM des données d'élévation DSM est le suivant. (Ce qui suit est un JPG de taille réduite.)

La carte d'élévation (carte de hauteur d'arbre) créée à partir du PNG d'élévation DCHM est la suivante.

■ Détection des pics d'arbres

"Aerial Laser Survey Mechanism" introduit une méthode pour détecter le point de valeur maximale avec un maillage de 3 m. Cette fois, j'ai défini un cercle de recherche avec un rayon de 2,0 m et détecté la position du sommet avec le code suivant.

	private void findPeaks(){
		for(double z=highH;z>=lowH;z=z-1){
			double dv=(++vv)/nn*100;
			for(int i=0;i<width;i++){
				for(int j=0;j<height;j++){
					if(ck[i][j]!=0)continue;
					if(val[i][j]>=z){
						Ellipse2D e=new Ellipse2D.Double(i-this.radius, j-this.radius, this.radius*2, this.radius*2);
						if(isHiMax(e,val[i][j])){
							setPeak(e);
							points.add(new Point3d(e.getCenterX(),e.getCenterY(),val[i][j]));
						}
					}
				}
			}
		}
	}

	private boolean isHiMax(Ellipse2D e,double v){
		int xs=(int)Math.max(e.getX(), 0);
		int ys=(int)Math.max(e.getY(), 0);
		int xe=(int )Math.min(e.getX()+e.getWidth(), width);
		int ye=(int)Math.min(e.getY()+e.getHeight(),height);
		for(int i=xs;i<xe;i++){
			for(int j=ys;j<ye;j++){
				if(val[i][j]>v)return false;
			}
		}
		return true;
	}

	private void setPeak(Ellipse2D e){
		int xs=(int)Math.max(e.getX(), 0);
		int ys=(int)Math.max(e.getY(), 0);
		int xe=(int )Math.min(e.getX()+e.getWidth(), width);
		int ye=(int)Math.min(e.getY()+e.getHeight(),height);
		for(int i=xs;i<xe;i++){
			for(int j=ys;j<ye;j++){
				if(ck[i][j]!=0)continue;
				if(e.contains(i, j))ck[i][j]=1;
			}
		}
	}

Les points de crête HCHM (position de l'arbre debout?) Détectés ci-dessus sont les suivants. 12392 points de crête (position de l'arbre debout?) Ont été détectés dans la plage de l'image (674 mx 600 m).

■ Estimation de la canopée

La division de bore a été réalisée en utilisant "Tinfour" avec le point de pic HCHM comme position de l'arbre.

	public List<ThiessenPolygon> process(){
		BoundedVoronoiBuildOptions options = new BoundedVoronoiBuildOptions();
        	options.enableAutomaticColorAssignment(true);
        	BoundedVoronoiDiagram diagram = new BoundedVoronoiDiagram(vertList, options);
        	List<ThiessenPolygon>  polyList=diagram.getPolygons();
		return polyList;
	}

Les résultats suivants de la division Boronoi sont présentés. Lorsqu'ils sont agrandis, les ombres et les sommets / régions de la canopée visibles sur la photographie semblent être grossièrement divisés.

■ Confirmation des points de crête

Afin de confirmer si le pic est détecté correctement, j'ai visualisé les informations de pixel DCHM estimées comme la canopée avec Jyz3d. J'ai vérifié certains endroits, mais le pic a été détecté sous la forme indiquée dans la figure ci-dessous.

■ Enfin

J'ai essayé d'analyser la hauteur des arbres, etc. avec Java des données de base de données de nuages de points de la préfecture de Shizuoka, mais je pouvais le détecter comme ça. Comme il n'y a pas de données de vérification, c'est dans la plage de jeu, mais c'est difficile pour les arbres à larges feuilles, etc., mais j'ai senti qu'il était possible de détecter le nombre d'arbres et de canopée comme c'est le cas dans la plantation de cèdres, etc. En outre, dans "Création de données de hauteur d'arbre à l'aide de données de levé laser aérien", "Les données de hauteur d'arbre par levé laser aérien sont la densité du groupe de points. Sauf pour les données des forêts de conifères à feuilles persistantes avec une haute, il ne correspond généralement pas aux valeurs mesurées des arbres individuels. "Cependant, si vous prenez la valeur moyenne dans la plage d'environ 30 mètres carrés, la corrélation sera meilleure. ] Est déclaré.

Si les résultats d'enquêtes et d'enquêtes sont rendus plus largement disponibles, comme Shizuoka Prefecture Point Cloud DB, cela sera utile à diverses fins.

Recommended Posts

Lisez les données de Shizuoka Prefecture Point Cloud DB avec Java et essayez de détecter la hauteur de l'arbre.
Lisez les données de la base de données de nuages de points de la préfecture de Shizuoka avec Java et générez une photographie aérienne et une élévation PNG.
Exécutez logstash avec Docker et essayez de télécharger des données sur Elastic Cloud
Revenir au début et démarrer avec Java ① Types de données et modificateurs d'accès
Agrégation de fenêtres de données de capteurs avec Apache Flink et Java 8
J'ai essayé de résumer les bases de kotlin et java
Commande pour vérifier le nombre et l'état des threads Java
[Java] Simplifiez la mise en œuvre de la gestion de l'historique des données avec Reladomo
Essayez la connexion DB avec Java
Connectez-vous à DB avec Java
Une évolution de l'énumération et des instructions switch! ?? Essayez d'obtenir des types de données algébriques et des correspondances de modèles en Java
Convertissez Excel en Blob avec java, enregistrez-le, lisez-le à partir de DB et exportez-le sous forme de fichier!
[Java] Divers résumés joints aux chefs de classe et aux membres
Je veux revenir à l'écran précédent avec kotlin et java!
Essayez HelloWorld avec la configuration minimale de Heroku Java spring-boot
Lire les 4 premiers octets du fichier de classe Java et générer CAFEBABE
Le point addictif lors de l'authentification de base avec Java URLConnection
[Rails] Lire le RSS du site et renvoyer le contenu au premier plan
De Java naissant (3 ans) à Node.js (4 ans). Et l'impression de retourner à Java
[Java] Affiche le résultat de ffprobe -show_streams dans JSON et mappe-le à un objet dans Jackson
L'histoire de l'oubli de fermer un fichier en Java et de l'échec
Je veux afficher des images avec REST Controller de Java et Spring!
Comment modifier le nombre maximum et maximum de données POST dans Spark
Développement Android-Accès WEB (GET) Essayez d'obtenir des données en communiquant avec l'extérieur. ~
[Cas d'amélioration Java] Comment atteindre la limite de l'auto-apprentissage et au-delà
J'ai essayé de traduire la grammaire de R et Java [Mis à jour de temps en temps]
J'ai essayé de mesurer et de comparer la vitesse de Graal VM avec JMH
Protégez les API REST créées avec Cloud Functions avec l'authentification Firebase. Et appliquez l'authentification Firebase à l'API de votre propre serveur REST.
Essayons WebSocket avec Java et javascript!
Sortie du livre "Introduction à Java"
Essayez d'utiliser la télécommande Wii en Java
J'ai reçu les données du voyage (application agenda) en Java et j'ai essayé de les visualiser # 001
Essayez de vous connecter à la base de données autonome avec JDK6 (Java) + pilote JDBC OCI (type 2).
Mémo: [Java] Traiter le csv lu (extraire et modifier selon les conditions) et sortir
Différence entre Java, C # et JavaScript (comment trouver le degré d'obésité)
Essayez d'accéder au système sur site à partir de SAP Cloud Platform --JAVA App Edition
Essayez d'enregistrer les données pouvant être lues par JavaFX au format PNG
[Java] Que faire si le contenu enregistré dans la base de données et le nom de l’énumération sont différents dans l’énumération qui reflète la définition de la base de données