【问题标题】:Conversion of Latitude/Longitude into image coordinates (Pixel coordinates) on a simple cylindrical projection在简单的圆柱投影上将纬度/经度转换为图像坐标(像素坐标)
【发布时间】:2014-07-21 21:02:05
【问题描述】:

我从 Google 地球拍摄了一张图片,它的所有 4 个角的纬度/经度都是已知的。我正在使用 GPS 传感器捕获纬度/经度。我必须使用 java 将这些捕获的纬度/经度转换为图像坐标(像素坐标)。我将使用图像坐标模拟车辆在静态地图上移动(图片取自 Google 地球)。

我找到了这个公式并尝试实现它

  1. 确定 1653x1012 图像中最左侧的经度 (X)
  2. 确定 1653x1012 图像 (Y) 中的最东经度
  3. 确定经度差 (Z = Y - X)
  4. 在 1653x1012 图像中确定最北纬度 (A)
  5. 确定 1653x1012 图像中最南端的纬度 (B)
  6. 确定纬度差异 (C = A - B) 给定纬度和经度,以确定他们点击了哪个像素:

J = 输入经度 K = 输入纬度

计算 X 像素

XPixel = CInt(((Y - J) / CDbl(Z)) * 1653)

计算 Y 像素

YPixel = CInt(((A - K) / CDbl(C)) * 1012)

这是我使用的代码。

    import java.awt.geom.Point2D;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.util.ArrayList;
    import java.util.List;

    public class LatLongService {
        private static LatLongService latLangService;
        private BufferedReader reader = null;
        private String st;

        private LatLongService() {
            try {
                reader = new BufferedReader(new FileReader(new File(
                        "resources/GPS_lat_long_2.txt")));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public static LatLongService getInstance() {
            if (latLangService == null)
                latLangService = new LatLongService();
            return latLangService;
        }

        public List<Point2D> readLatLongList() {
            List<Point2D> pointList = new ArrayList<Point2D>();
            StringBuffer xStr;
            StringBuffer yStr = new StringBuffer();
            try {
                while ((st = reader.readLine()) != null) {
                    xStr = new StringBuffer(st.substring(0, st.indexOf(',')));
                    yStr = new StringBuffer(st.substring(st.indexOf(',') + 2,
                            st.length()));
                    Point2D pt = new Point2D.Double(
                            new Double(xStr.toString()).doubleValue(), new Double(
                                    yStr.toString()).doubleValue());
                    pointList.add(pt);
                }
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    reader.close();
                } catch (Exception e2) {
                    e.printStackTrace();
                }
            }
            return pointList;
        }


    public List<Point2D> convertLatLongToCoord(List<Point2D> coordinate) {
            List<Point2D> latLong = new ArrayList<Point2D>();
            double westMostLong = -79.974642;
            double eastMostLong = -79.971244;
            double longDiff = eastMostLong - westMostLong; // (rightmost_longitude -
                                                            // leftmost_longitude)

            double northMostLat = 39.647556;
            double southMostLat = 39.644675;
            double latDiff = northMostLat - southMostLat; // (topmost_latitude -
                                                            // bottommost_latitude)
            for (Point2D coord : coordinate) {
                double j = coord.getY();
                double k = coord.getX();

                double XPixel = (((eastMostLong - j) / longDiff) * 1653);
                double YPixel = (((northMostLat - k) / latDiff) * 1012);

                Point2D actualCoord = new Point2D.Double(XPixel, YPixel);
                latLong.add(actualCoord);
            }
            return latLong;
        }
    }

我从 GPS 传感器获得的一些 GPS 纬度/经度

输入纬度 输入经度 (39.64581, -79.97168) (39.64651, -79.97275) (39.646915, -79.97342) (39.646538, -79.97279)

[IMG]http://i59.tinypic.com/nbqkk3.png[/IMG]

图片中的红线表示传感器获取 GPS 坐标时所遵循的路径。

但是,当我使用此公式将纬度/经度坐标转换为像素坐标时。转换后的像素坐标不一致,如下图输出:

图像 X 图像 Y (212.0977045, 613.3120444) (732.6127134, 367.4251996) (1058.542672, 225.1620965) (752.0712184, 357.5897258)

X、Y(像素)坐标的变化太大。因此,当我尝试根据像素坐标移动车辆时,车辆不会跟随红线或至少靠近红线。

车辆在红线上方或下方移动,但不在红线上。

对于基于像素坐标的车辆平稳移动,理想情况下,我希望从纬度/经度到图像坐标的转换是这样的:

所需图像 X 所需图像 Y (1290, 409) (1289, 409) (1288, 409) (1287, 409)

但我得到了这个

图像 X 图像 Y (212.0977045, 613.3120444) (732.6127134, 367.4251996) (1058.542672, 225.1620965) (752.0712184, 357.5897258)

我希望我能够传达我的问题。

【问题讨论】:

  • 你有你的java源代码和一些算法的例子吗?
  • “它会跳”是什么意思?你需要使用动画框架吗?还是您认为坐标完全错误?并且您确定车辆的输入坐标没有跳跃(这是通过 GPS 测量坐标并且车辆或人静止不动的情况)
  • 我已经编辑了我的问题,希望对您有所帮助。
  • 您应该首先尝试使用谷歌地图中的图片,卫星图片不太合适,它不是从上方拍摄的,有时在此类卫星图片中会出现可见的数字“折叠线”。因此,请使用漂亮的平面鸟瞰图对其进行测试。
  • 我用谷歌地图查了一下,车辆还是没有走红线。我认为从纬度/经度到像素坐标的转换有一些问题。连续纬度/经度的差异非常小。值在千位和万位变化。但是转换成图像坐标后,数值的变化还是蛮大的。

标签: java gps google-earth


【解决方案1】:

纬度和经度不是距离。

http://geography.about.com/cs/latitudelongitude/a/latlong.htm

我最近参与了一个使用 GPS 的 Arduino 项目。我采用了 minigeo API 方法,将纬度和经度转换为北距和东距 (UTM)。

使用链接中的库,您可以进行以下转换: http://www.ibm.com/developerworks/library/j-coordconvert/

获得最大东移和北移并计算比例

private synchronized void scale() {
        int w = 800;
        int h = 600;

        this.scale = Math.min(
                w / (maxEasting - minEasting),
                h / (maxNorthing - minNorthing));

        oEasting = minEasting;
        oNorthing = minNorthing;
    }

比转换成X和Y

private int applyScale(double km) {
        return (int) (km * scale);
    }

    private int convertX(double easting) {
        return applyScale(easting - oEasting);
    }

    private int convertY(double northing, int height) {
        return 600/*height*/ - applyScale(northing - oNorthing);
    }

来源:Minigeo

【讨论】:

  • 我使用的是从谷歌地球捕获的静态图像(GE 使用简单的圆柱投影)。为什么我需要再次转换为 UTM 坐标?你能解释一下吗?
  • 查看最佳答案,很好解释:stackoverflow.com/questions/14329691/…
【解决方案2】:

这是一个编译并回答您的问题的代码

[1] (39.64581,-79.97168) -> 102,363
[2] (39.64651,-79.97275) -> 354,217
[3] (39.646915,-79.97342) -> 512,133
[4] (39.646538,-79.97279) -> 363,212
[5] (39.646458,-79.97264) -> 328,228

您可能已经交换了 x-y 坐标。在这种情况下,x == 经度,y == 纬度。

import java.util.*;
import java.awt.geom.*;

public class LatLong {

        private  int  imageW,  imageH;
        private final static   double   west = -79.974642,      north = 39.647556,
                                        east = -79.971244,      south = 39.644675;

        public LatLong (int w, int h) {
                imageW = w;
                imageH = h;
        }

        public List<Point2D> convertLatLongToCoord (List<Point2D> coordinate) {
            List<Point2D> latLong = new ArrayList<Point2D>();
            for (Point2D coord : coordinate) {
                double  x = coord.getY(),       px = imageW * (x-east) / (west-east),
                        y = coord.getX(),       py = imageH * (y-north)/(south-north);
                latLong.add (new Point2D.Double(px,py));
            }
            return latLong;
        }

        public static void main (String[] args) {
                double[] latit = {39.64581, 39.64651, 39.646915, 39.646538, 39.646458},
                        longit = {-79.97168, -79.97275, -79.97342, -79.97279, -79.97264};

                List<Point2D> pointList = new ArrayList<Point2D>();
                for (int i = 0 ; i < latit.length ; i++)
                        pointList.add (new Point2D.Double(latit[i], longit[i]));

                List<Point2D> pixels = new LatLong (800,600).convertLatLongToCoord (pointList);

                for (int i = 0 ; i < latit.length ; i++)
                        System.out.println ("[" + (i+1) + "]\t(" + latit[i] + "," + longit[i] + ") -> " +
                                (int) (pixels.get(i).getX()) + "," + (int) (pixels.get(i).getY()));
}}

【讨论】:

  • 如果我们在谷歌地球中绘制所有的纬度/经度坐标,它几乎会形成一条直线。但是,当我们使用上面的公式将这个纬度/经度转换为像素坐标时,这些都在各处。像素坐标的递增/递减应该是顺序的,目前没有。
  • 该公式假设由经纬度组成的矩形的边界为矩形。对于这么小的部分,我不认为测地线变换是相关的。
  • 我认为转换可能是相关的,因为我尝试了不同的公式进行转换。但我没有得到我需要的图像坐标。
  • 你试过上面的代码了吗?这只是您的中音的重新散列,并且还会产生上面的数字。 - M.
  • 我试过你的代码。我的代码的地图宽度和高度是 1653 X 1012。问题是转换后的连续像素坐标有很大的差异。而连续的经纬度坐标差异很小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
  • 2016-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多