当前位置:   article > 正文

java20 通过gdal3.6.4,geotools实现遥感影像分类,坐标转换,输出_java后台4326和32649坐标转换

java后台4326和32649坐标转换

前台是openlayer vue 项目,后台是spring boot 。需求是前台页面通过设置空间范围,然后对范围内的影像,进行分类输出。中间踩过一些坑,将新路历程记录下来,一来是回顾记录下来,二来,也希望给其他人一些参考。

一、前台传入geojson图形和影像,以及分类等相关参数

  1. //获取geojson数据
  2. new GeoJSON().writeFeatures(layer.getSource().getFeatures())
{"geoJSON":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[122.75304112963302,42.499201220100524],[122.8043874485347,42.499201220100524],[122.8043874485347,42.52820855610342],[122.75304112963302,42.52820855610342],[122.75304112963302,42.499201220100524]]]},"properties":null}]}}

二、利用gdal,用geojson数据裁剪影像。

  1. public void imageCutByShp() throws Exception {
  2. gdal.AllRegister()//注册驱动,否则下边执行报错
  3. Dataset source = gdal.Open("E:\\a.tif"); //tif文件路径
  4. Vector vector = new Vector();
  5. vector.add("-cutline");
  6. vector.add("E:\\cut.shp");//shp文件路径
  7. //或者是geojson字符串都可以
  8. //String jsonObject = JSONObject.toJSONString(geoJSON);
  9. // vector.add(jsonObject); //geojson的字符串
  10. vector.add("-crop_to_cutline");
  11. WarpOptions warpAppOptions = new WarpOptions(vector);
  12. Dataset[] datasets = new Dataset[]{source};
  13. Dataset output = gdal.Warp("E:\\output.tif", datasets, warpAppOptions); //第一个参数是生成结果路径和文件名
  14. }

三、调用分类算法,将原始影像tif生成分类后的tif。

(小编是集成用其他小伙伴利用python深度学习完成的工具,对应的exe,实现分类)

四、通过gdal将栅格矢量化输出

  1. try {
  2. String output = "E:\\a.shp";
  3. Dataset dataset = gdal.Open(output);
  4. Band band = dataset.GetRasterBand(1);
  5. SpatialReference prj = new SpatialReference();
  6. if (!dataset.GetProjectionRef().isEmpty()) {
  7. prj.ImportFromWkt(dataset.GetProjectionRef());
  8. }
  9. Driver driver = gdal.GetDriverByName("ESRI Shapefile");
  10. Dataset dsOut = driver.Create(output, dataset.getRasterXSize(),
  11. dataset.getRasterYSize(), 1, gdalconst.GDT_Byte);
  12. Layer layer = dsOut.CreateLayer("layer", prj);
  13. FieldDefn field = new FieldDefn("value", ogr.OFTReal);
  14. //第二个参数是字段类型,ogr.OFTInteger和ogr.OFTReal都是属性字段的数据类型,但它们的区别在于存储的数据类型不同。ogr.OFTInteger表示整数类型,而ogr.OFTReal表示浮点数类型。如果您需要存储整数类型的属性值,可以使用ogr.OFTInteger,如果需要存储浮点数类型的属性值,可以使用ogr.OFTReal。在创建属性字段时,需要根据实际情况选择合适的数据类型。
  15. layer.CreateField(field);
  16. //矢量化
  17. gdal.Polygonize(band, null, layer, 0);
  18. Feature feature = layer.GetNextFeature();
  19. while (null != feature) {
  20. int value = feature.GetFieldAsInteger("value");
  21. if (value == 0) {
  22. layer.DeleteFeature(feature.GetFID());
  23. }
  24. feature = layer.GetNextFeature();
  25. }
  26. layer.SyncToDisk();
  27. File[] files = new File[5];
  28. files[0] = new File(output);
  29. files[1] = new File(output.replace(".shp", ".dbf"));
  30. files[2] = new File(output.replace(".shp", ".prj"));
  31. files[3] = new File(output.replace(".shp", ".shx"));
  32. dataset.delete();
  33. dsOut.delete();
  34. } catch (Exception exception) {
  35. log.error("影像转shp失败:" + exception.toString());
  36. }

以上是tif转shp,小编也试过tif直接转geojson,将驱动改成GeoJSON的,Driver driver = gdal.GetDriverByName("GeoJSON");File[] files = new File[1];files[0] = new File(output);也能转成功,但是layer.GetNextFeature()一直是null,得到的数据里也没有将栅格像素值转到geojson属性里。

五、坐标转换

由于前台openlayer显示的坐标系统是4326的,分析的影像坐标系统是cgcs2000的,前台页面通过openlayer转坐标系统,图形偏的好远,不成功,所以在后台利用geotools中的JTS进行坐标转换

5.1从shp中读取SimpleFeatureCollection 

  1. public SimpleFeatureCollection readShp() throws Exception {
  2. SimpleFeatureCollection simpleFeatureCollection = null;
  3. ShapefileDataStore shpDataStore = null;
  4. try {
  5. String input = "E:\\a.shp'";
  6. File file = new File(input);
  7. shpDataStore = new ShapefileDataStore(file.toURL());
  8. //设置字符编码
  9. Charset charset = "GBK"
  10. shpDataStore.setCharset(charset);
  11. String typeName = shpDataStore.getTypeNames()[0];
  12. SimpleFeatureSource featureSource = null;
  13. featureSource = shpDataStore.getFeatureSource(typeName);
  14. simpleFeatureCollection = featureSource.getFeatures();
  15. } catch (Exception exception) {
  16. log.error("读取shp失败:" + exception.toString());
  17. throw new Exception ("读取shp失败:" + exception.toString());
  18. }
  19. return simpleFeatureCollection;
  20. }

5.2坐标转换

  1. /**
  2. * @param simpleFeatureCollection 要素集
  3. * @param currentCRS 当前的坐标系统
  4. * @param targetCRS 转换的坐标系统
  5. */
  6. public SimpleFeatureCollection project(SimpleFeatureCollection simpleFeatureCollection, CoordinateReferenceSystem currentCRS, CoordinateReferenceSystem targetCRS) throws MismatchedDimensionException, TransformException, FactoryException, TemplateException {
  7. // 当前要素集空间参考
  8. if (null == simpleFeatureCollection || simpleFeatureCollection.size() == 0) {
  9. return simpleFeatureCollection;
  10. }
  11. if (null == targetCRS) {
  12. throw new Exception("坐标转换错误:targetCRS 空了");
  13. }
  14. if(currentCRS==null){
  15. currentCRS = CRS.decode(CRS.lookupIdentifier(simpleFeatureCollection.getSchema().getCoordinateReferenceSystem(), false), true);
  16. }
  17. MathTransform transform = null;
  18. if (!currentCRS.equals(targetCRS)) {
  19. // 判断是否可直接转换
  20. if (CRS.isCompatible(currentCRS, targetCRS, true)) {
  21. // 如果可直接转换 转换完成再叠加
  22. transform = CRS.findMathTransform(currentCRS, targetCRS, true);
  23. } else {
  24. // 否则抛出异常 坐标系不能直接转换。
  25. throw new Exception("坐标转换错误");
  26. }
  27. }
  28. // transform 不为空说明需要转换坐标
  29. SimpleFeatureType resultFeatureType = null;
  30. if (transform != null) {
  31. resultFeatureType = SimpleFeatureTypeBuilder.retype(simpleFeatureCollection.getSchema(), targetCRS);
  32. SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(resultFeatureType);
  33. try (SimpleFeatureIterator iterator1 = simpleFeatureCollection.features()) {
  34. List<SimpleFeature> resultFeatures = new ArrayList<>();
  35. while (iterator1.hasNext()) {
  36. SimpleFeature feature = iterator1.next();
  37. Geometry geometry = (Geometry) feature.getDefaultGeometry();
  38. Geometry newGeometry = JTS.transform(geometry, transform);
  39. featureBuilder.add(newGeometry);
  40. if (feature.getAttributes().size() > 1) {
  41. featureBuilder.addAll(feature.getAttributes().subList(1, feature.getAttributes().size()));
  42. }
  43. SimpleFeature newFeature = featureBuilder.buildFeature(null);
  44. resultFeatures.add(newFeature);
  45. }
  46. simpleFeatureCollection = new ListFeatureCollection(resultFeatureType, resultFeatures);
  47. }
  48. }
  49. return simpleFeatureCollection;
  50. }

使用featureBuilder.add()方式添加,一定要注意一定按照SimpleFeatureType给的字段顺序进行赋值!!! 

六、将simpleFeatureCollection 转换成geojson返回

  1. public String featureCollection2GeoJsonStr(SimpleFeatureCollection featureCollection) throws IOException {
  2. FeatureJSON featureJSON = new FeatureJSON(new GeometryJSON(15));// 避免精度丢失
  3. FeatureCollection features = (FeatureCollection) featureCollection;
  4. return featureJSON.toString(features);
  5. }
  1. //显示geojson数据
  2. resultLayer.getSource().addFeatures(new GeoJSON().readFeatures(geojson))

这里需要注意的是由于SimpleFeatureCollection 是 org.geotools.data.simple命名空间下的,featureJSON.toString()方法需要传入的参数FeatureCollection是org.geotools.feature命名空间下的,所以将org.geotools.data.simple.SimpleFeatureCollection 转成org.geotools.feature.FeatureCollection 。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/515371
推荐阅读
相关标签
  

闽ICP备14008679号