Saya sedang mengerjakan proyek untuk mendeteksi objek dari file GEOTiff dan mengembalikan koordinat objek dan output tersebut akan digunakan untuk drone untuk terbang ke koordinat tersebut

Saya menggunakan tensorflow dengan YOLO v2 (kerangka pendeteksi gambar) dan OpenCV untuk mendeteksi objek yang saya butuhkan di GEOTiff

import cv2
from darkflow.net.build import TFNet
import math
import gdal

# initial stage for YOLO v2 
options = {
    'model': 'cfg/yolo.cfg',
    'load': 'bin/yolov2.weights',
    'threshold': 0.4,
}
tfnet = TFNet(options)

# OpenCV read Image
img = cv2.imread('final.tif', cv2.IMREAD_COLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

#Predict the image
result = tfnet.return_predict(img)

#Calculate the center and radius of each objects
i = 0
while i < len(result):
    tl = (result[i]['topleft']['x'], result[i]['topleft']['y'])
    br = (result[i]['bottomright']['x'], result[i]['bottomright']['y'])
    point = (int((result[i]['topleft']['x']+result[i]['bottomright']['x'])/2), int((result[i]['topleft']['y']+result[i]['bottomright']['y'])/2))
    radius = int(math.hypot(result[i]['topleft']['x'] - point[0], result[i]['topleft']['y'] - point[1]))
    label = result[i]['label']
    result[i]['pointx'] = point[0]
    result[i]['pointy'] = point[1]
    result[i]['radius'] = radius    
    i += 1

print(result)

Jadi hasilnya keluar seperti set JSON

[{'label': 'person', 'confidence': 0.6090355, 'topleft': {'x': 3711, 'y': 1310}, 'bottomright': {'x': 3981, 'y': 1719}, 'pointx': 3846, 'pointy': 1514, 'radius': 244}]

Seperti yang Anda lihat lokasi objek dikembalikan dalam piksel (x,y) dan saya ingin menggunakan x,y ini untuk mengonversi menjadi koordinat dalam lat,lng jadi saya mencoba menggunakan GDAL (perpustakaan digunakan untuk membaca informasi GEO yang berisi di dalam gambar)

Jadi inilah informasi GEO gambar dengan menggunakan gdalinfo di terminal

Driver: GTiff/GeoTIFF
Files: final.tif
Size is 8916, 6888
Coordinate System is:
PROJCS["WGS 84 / UTM zone 47N",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.0174532925199433,
            AUTHORITY["EPSG","9122"]],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",99],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AXIS["Easting",EAST],
    AXIS["Northing",NORTH],
    AUTHORITY["EPSG","32647"]]
Origin = (667759.259870000067167,1546341.352920000208542)
Pixel Size = (0.032920000000000,-0.032920000000000)
Metadata:
  AREA_OR_POINT=Area
  TIFFTAG_SOFTWARE=pix4dmapper
Image Structure Metadata:
  COMPRESSION=LZW
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (  667759.260, 1546341.353) (100d33'11.42"E, 13d58'57.03"N)
Lower Left  (  667759.260, 1546114.600) (100d33'11.37"E, 13d58'49.65"N)
Upper Right (  668052.775, 1546341.353) (100d33'21.20"E, 13d58'56.97"N)
Lower Right (  668052.775, 1546114.600) (100d33'21.15"E, 13d58'49.59"N)
Center      (  667906.017, 1546227.976) (100d33'16.29"E, 13d58'53.31"N)
Band 1 Block=8916x1 Type=Byte, ColorInterp=Red
  NoData Value=-10000
Band 2 Block=8916x1 Type=Byte, ColorInterp=Green
  NoData Value=-10000
Band 3 Block=8916x1 Type=Byte, ColorInterp=Blue
  NoData Value=-10000
Band 4 Block=8916x1 Type=Byte, ColorInterp=Alpha
  NoData Value=-10000

Salah satu?

5
Johnny Ratchapong 5 Mei 2018, 19:29

2 jawaban

Jawaban Terbaik

Anda perlu mengubah koordinat piksel ke ruang geografis menggunakan matriks GeoTransform yang terkait dengan file raster Anda. Menggunakan GDAL Anda dapat melakukan sesuatu seperti berikut:

# open the dataset and get the geo transform matrix
ds = gdal.Open('final.tif') 
xoffset, px_w, rot1, yoffset, px_h, rot2 = ds.GetGeoTransform()

# supposing x and y are your pixel coordinate this 
# is how to get the coordinate in space.
posX = px_w * x + rot1 * y + xoffset
posY = rot2 * x + px_h * y + yoffset

# shift to the center of the pixel
posX += px_w / 2.0
posY += px_h / 2.0

Tentu saja posisi yang Anda dapatkan akan relatif terhadap sistem referensi koordinat yang sama yang digunakan untuk dataset raster Anda. Jadi, jika Anda perlu mengubahnya menjadi lat/long, Anda harus melakukan elaborasi lebih lanjut:

# get CRS from dataset 
crs = osr.SpatialReference()
crs.ImportFromWkt(ds.GetProjectionRef())
# create lat/long crs with WGS84 datum
crsGeo = osr.SpatialReference()
crsGeo.ImportFromEPSG(4326) # 4326 is the EPSG id of lat/long crs 
t = osr.CoordinateTransformation(crs, crsGeo)
(lat, long, z) = t.TransformPoint(posX, posY)

Maaf saya tidak terlalu fasih dengan python, jadi mungkin Anda harus mengadaptasi kode ini. Lihat dokumentasi GeoTransform di sini untuk C++ API untuk mempelajari lebih lanjut tentang elemen matriks.

15
Gabriella Giordano 9 Mei 2018, 12:55

Tanpa kode Python yang sangat baik dan jelas yang diposting oleh Gabriella, saya tidak tahu apakah saya akan pernah menemukan cara untuk melakukan ini di C. Dokumentasi dan contoh untuk gdal sangat jarang.

Berikut adalah versi C dari kode Gabriella:

const char fn[] = "/path/to/geo/file.tif";

GDALDatasetH  hDataset;
GDALAllRegister(); // Register all GDAL formats
hDataset = GDALOpen( fn, GA_ReadOnly ); // Open our geo file (GeoTIFF or other supported format)
if (hDataset == NULL)
{
    printf("Failed to open dataset\n");
    return;
}

// These are the input points to be transformed, in pixel coordinates of the source raster file
double x = 20;
double y = 20;

double        adfGeoTransform[6];
GDALGetGeoTransform( hDataset, adfGeoTransform );

// Put the returned transform values into named vars for readability
double xoffset = adfGeoTransform[0];
double px_w = adfGeoTransform[1];
double rot1 = adfGeoTransform[2];
double yoffset = adfGeoTransform[3];
double rot2 = adfGeoTransform[4];
double px_h = adfGeoTransform[5];

// Apply transform to x,y. Put into posX,posY
double posX = px_w * x + rot1 * y + xoffset;
double posY = rot2 * x + px_h * y + yoffset;

// Transform to center of pixel
posX += px_w / 2.0;
posY += px_h / 2.0;

OGRErr err = 0;

// sr0 is the "from" spatial reference, pulled out of our file
OGRSpatialReferenceH sr0 = OSRNewSpatialReference(GDALGetProjectionRef(hDataset));

// sr1 is the "to" spatial reference, initialized as EPSG 4326 (lat/lon)
OGRSpatialReferenceH sr1 = OSRNewSpatialReference(NULL);
err = OSRImportFromEPSG(sr1, 4326);

double xtrans = posX;
double ytrans = posY;
double ztrans = 0;
int pabSuccess = 0;

// Make our transformation object
OGRCoordinateTransformationH trans = OCTNewCoordinateTransformation(sr0, sr1);

// Transform our point posX,posY, put it into xTrans,yTrans
OCTTransformEx(trans, 1, &xtrans, &ytrans, &ztrans, &pabSuccess);
    
GDALClose(hDataset);

printf("map coordinates (%f, %f)\n", xtrans, ytrans);

1
TyR 30 November 2020, 17:30