Java 将笛卡尔像素数据阵列转换为lat/lon像素数据阵列

Java 将笛卡尔像素数据阵列转换为lat/lon像素数据阵列,java,geotools,Java,Geotools,我有一个图像(基本上,我得到的原始图像数据是1024x1024像素)和图像中心像素的lat/lon位置 每个像素以米为单位表示相同的固定像素比例(例如,每像素30米) 现在,我想将图像绘制到使用坐标参考系“EPSG:4326”(WGS84)的地图上 当我通过在图像的lat/lon中定义角点,根据“像素*像素比例的图像大小”计算并转换从中心点到每个角点的lat/lon坐标的距离来绘制它时,我想,图像没有正确地绘制到地图上。 所谓“未正确绘制”,我的意思是,图像似乎发生了移动,而且图像的内容也不在我

我有一个图像(基本上,我得到的原始图像数据是1024x1024像素)和图像中心像素的lat/lon位置

每个像素以米为单位表示相同的固定像素比例(例如,每像素30米)

现在,我想将图像绘制到使用坐标参考系“EPSG:4326”(WGS84)的地图上

当我通过在图像的lat/lon中定义角点,根据“像素*像素比例的图像大小”计算并转换从中心点到每个角点的lat/lon坐标的距离来绘制它时,我想,图像没有正确地绘制到地图上。 所谓“未正确绘制”,我的意思是,图像似乎发生了移动,而且图像的内容也不在我预期的地图位置

我想这是因为我“混合”了一个像素比例的图像和一个“EPSG:4326”坐标系

现在,根据我给出的信息,我可以使用Geotools在“EPSG:4326”坐标系中将整个像素矩阵从固定的像素比例基准转换为新的像素矩阵吗? 当然,变换必须取决于我已经给出的lat/lon中的中心位置以及像素比例

我想知道这样做是否能为我指明正确的方向:

MathTransform transform = CRS.findMathTransform(DefaultGeocentricCRS.CARTESIAN, DefaultGeographicCRS.WGS84, true);

  DirectPosition2D srcDirectPosition2D = new DirectPosition2D(DefaultGeocentricCRS.CARTESIAN, degreeLat.getDegree(), degreeLon.getDegree());
  DirectPosition2D destDirectPosition2D = new DirectPosition2D();
  transform.transform(srcDirectPosition2D, destDirectPosition2D);

  double transX = destDirectPosition2D.x;
  double transY = destDirectPosition2D.y;

  int kmPerPixel = mapImage.getWidth / 1024; // It is known to me that my map is 1024x1024km ...

  double x = zeroPointX + ((transX * 0.001) * kmPerPixel);
  double y = zeroPointY + (((transX * -1) * 0.001) * kmPerPixel);
(从另一个SO线程获取此代码,并已对其进行了一些修改,但仍不知道这是否是解决我的问题的正确起点。)

我只假设我的原始图像坐标系是DefaultGeocentricCRS.CARTESIAN类型。有人能证实这一点吗

从现在开始,这是使用Geotools解决此类问题的正确开始,还是我完全走错了路

此外,我想补充一点,这将用于安静的动态系统。因此,我的图像更新频率大约为10Hz,因此必须经常进行相应的转换。 再说一次,是我最初的想法导致了一个解决方案,还是你有其他解决我问题的方法

多谢各位,
Kiamur

这并不像听起来那么简单。您实际上是在尝试使用平面正方形定义球体(技术上为椭球体)上的区域。因此,没有“正确”的方法来做这件事,所以你总是会以一些扭曲而告终。如果不知道您的图像来自何处,则无法准确回答此问题,但以下代码为您提供了3种可能的答案:

前两种方法利用GeoTools的大地测量计算器使用方位和距离计算角点。上面是蓝色的“正方形”和绿色的“正方形”。蓝色直接计算角点,而绿色计算边点并从交点推断角点(这就是为什么它是正方形)

使用哪种解决方案是一个品味问题,这取决于你的图像来自何处,但我怀疑红色或蓝色将是最好的。如果你需要在10Hz下进行测试,那么你需要测试它们的速度,但我怀疑转换图像将是一个瓶颈

一旦您满意地设置了边界框,就可以使用以下方法将(未参照的)图像转换为地理参照覆盖:

GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(null);
GridCoverage2D gc = factory.create("name", image, new ReferencedEnvelope(bbox.getEnvelopeInternal(),DefaultGeographicCRS.WGS84));
String fileName = "myImage.tif";
AbstractGridFormat format = GridFormatFinder.findFormat(fileName);
File out = new File(fileName);
GridCoverageWriter writer = format.getWriter(out);
try {
  writer.write(gc, null);
  writer.dispose();
} catch (IllegalArgumentException | IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

谢谢@iant,我将在明天访问完整的开发环境后查看此内容。老实说,我担心会有一点暴风雨降临到我身上,但最后,似乎我问了一个合理的问题。这对我来说仍然是一个谜,仅仅因为你提到的原因,如何正确地做这件事。也许,为了完整起见,你能谈谈把整个图像,一个像素一个像素地,从我的(我怎么称呼它)catesian坐标系转换成“EPSG:4326”坐标系的可能性吗?。我想知道Geotools是否提供了这样的功能。我在coveragesiant上添加了更多内容,再次感谢,我目前正在努力实现我的geo-refed coverage。不幸的是,当我试图通过
GridCoverageFactory
创建我的
gridcoverage2d
时,我遇到了一个类转换异常:
com.livitsolutions.jts.geom.Envelope无法转换为org.opengis.geometry.Envelope
。我有点迷路了,因为其他一切,我已经开始工作了。不幸的是,到目前为止,我的处境没有任何改善。唯一积极的事情是:您对红色/蓝色正方形的角点计算的结果与我之前的角点定义完全相同…对不起,我的错误是直接在SE中键入代码-您需要一个引用的Env so新的ReferenceDevelope(bbox.getEnvelopeInternal(),DefaultGeography CCRS.WGS84);安特,谢谢你的大力支持!这解决了我提到的问题。现在,似乎缺少的是正确的JAI LIB。我包括了我在Geotool库文件夹中找到的所有thre JAI JAR。不幸的是,行
AbstractGridFormat=GridFormatFinder.findFormat(文件名)以一个
IllegalArgumentException:input==null爆炸。我必须承认,我没有使用Maven,只是通过Eclipse中的构建路径编辑器导入我认为需要的库。我想我已经很接近了,但我不得不再次请求你的帮助,我很抱歉。。。。。。
String code = "AUTO:42003," + centre.getX() + "," + centre.getY();
// System.out.println(code);
CoordinateReferenceSystem auto = CRS.decode(code);
// System.out.println(auto);
MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84,
    auto);
MathTransform rtransform = CRS.findMathTransform(auto,DefaultGeographicCRS.WGS84);
Point g = (Point)JTS.transform(centre, transform);

width2 *=1000.0;
height2 *= 1000.0;
corners[0] = new Coordinate(g.getX()-width2,g.getY()-height2);
corners[1] = new Coordinate(g.getX()+width2,g.getY()-height2);
corners[2] = new Coordinate(g.getX()+width2,g.getY()+height2);
corners[3] = new Coordinate(g.getX()-width2,g.getY()+height2);
corners[4] = corners[0];
bbox = gf.createPolygon(corners);
bbox = (Polygon)JTS.transform(bbox, rtransform);
System.out.println(writer.write(bbox));
GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(null);
GridCoverage2D gc = factory.create("name", image, new ReferencedEnvelope(bbox.getEnvelopeInternal(),DefaultGeographicCRS.WGS84));
String fileName = "myImage.tif";
AbstractGridFormat format = GridFormatFinder.findFormat(fileName);
File out = new File(fileName);
GridCoverageWriter writer = format.getWriter(out);
try {
  writer.write(gc, null);
  writer.dispose();
} catch (IllegalArgumentException | IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}