initial commit
This commit is contained in:
commit
06af1dbb7c
53
sat.py
Normal file
53
sat.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
from PIL import Image
|
||||||
|
import requests
|
||||||
|
from sat7_pointer import *
|
||||||
|
|
||||||
|
# Load Landsat 7 band 1, 2, 3 TIF images and create a composite image
|
||||||
|
# from the three bands.
|
||||||
|
#
|
||||||
|
# The composite image is a greyscale image with a red, green and blue
|
||||||
|
# channel.
|
||||||
|
#
|
||||||
|
# The red channel is the red channel of band 3, the green channel is the
|
||||||
|
# green channel of band 2 and the blue channel is the blue channel of band 1.
|
||||||
|
#
|
||||||
|
# The composite image is saved as a PNG file.
|
||||||
|
|
||||||
|
band1 = Image.open('LE07_L1TP_177025_20210723_20210818_02_T1_B1.TIF')
|
||||||
|
band2 = Image.open('LE07_L1TP_177025_20210723_20210818_02_T1_B2.TIF')
|
||||||
|
band3 = Image.open('LE07_L1TP_177025_20210723_20210818_02_T1_B3.TIF')
|
||||||
|
|
||||||
|
composite = Image.merge('RGB', (band3, band2, band1))
|
||||||
|
|
||||||
|
# Load corner coordinates of the image.
|
||||||
|
#
|
||||||
|
# The coordinates are stored in a MTL text file.
|
||||||
|
|
||||||
|
mtl_data = load_metadata('LE07_L1TP_177025_20210723_20210818_02_T1_MTL.txt')
|
||||||
|
|
||||||
|
# Fetch coordinates of a city.
|
||||||
|
#
|
||||||
|
# The coordinates of a city are fetched from the OpenStreetMap API.
|
||||||
|
#
|
||||||
|
# The coordinates are used to calculate the corner coordinates of the
|
||||||
|
# composite image.
|
||||||
|
#
|
||||||
|
# # City is Belgorod, Russia.
|
||||||
|
|
||||||
|
url = 'http://nominatim.openstreetmap.org/search?q=Belgorod,+Russia&format=json'
|
||||||
|
response = requests.get(url)
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
# Convert bounding box coordinates to image coordinates.
|
||||||
|
|
||||||
|
x0, y1 = lat_lot_to_pixel(data[0]['boundingbox'][0], data[0]['boundingbox'][2], mtl_data)
|
||||||
|
x1, y0 = lat_lot_to_pixel(data[0]['boundingbox'][1], data[0]['boundingbox'][3], mtl_data)
|
||||||
|
|
||||||
|
print(x0, y0)
|
||||||
|
print(x1, y1)
|
||||||
|
print(composite.size)
|
||||||
|
# Crop the image to the bounding box coordinates.
|
||||||
|
|
||||||
|
cropped = composite.crop((x0, y0, x1, y1))
|
||||||
|
|
||||||
|
cropped.save('cropped.png')
|
81
sat7_pointer/__init__.py
Normal file
81
sat7_pointer/__init__.py
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import csv
|
||||||
|
import pyproj
|
||||||
|
import math
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def load_metadata(mtl_file):
|
||||||
|
mtl_data = {}
|
||||||
|
with open(mtl_file) as f:
|
||||||
|
mtl = csv.reader(f, delimiter='=')
|
||||||
|
try:
|
||||||
|
for row in mtl:
|
||||||
|
mtl_data[row[0].strip()] = row[1]
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
mtl_data['width'] = float(mtl_data['REFLECTIVE_SAMPLES'])
|
||||||
|
mtl_data['height'] = float(mtl_data['REFLECTIVE_LINES'])
|
||||||
|
|
||||||
|
mtl_data['lat_lon_corners'] = np.array([
|
||||||
|
[float(mtl_data['CORNER_UL_LAT_PRODUCT']), float(mtl_data['CORNER_UL_LON_PRODUCT']), 0],
|
||||||
|
[float(mtl_data['CORNER_UR_LAT_PRODUCT']), float(mtl_data['CORNER_UR_LON_PRODUCT']), 0],
|
||||||
|
[float(mtl_data['CORNER_LR_LAT_PRODUCT']), float(mtl_data['CORNER_LR_LON_PRODUCT']), 0],
|
||||||
|
[float(mtl_data['CORNER_LL_LAT_PRODUCT']), float(mtl_data['CORNER_LL_LON_PRODUCT']), 0]
|
||||||
|
])
|
||||||
|
|
||||||
|
mtl_data['ecef'] = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84')
|
||||||
|
mtl_data['lla'] = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84')
|
||||||
|
|
||||||
|
x, y, z = pyproj.transform(mtl_data['lla'], mtl_data['ecef'],
|
||||||
|
mtl_data['lat_lon_corners'][:, 1],
|
||||||
|
mtl_data['lat_lon_corners'][:, 0],
|
||||||
|
mtl_data['lat_lon_corners'][:, 2],
|
||||||
|
radians=False)
|
||||||
|
|
||||||
|
mtl_data['ecef_corners'] = np.array([x, y, z]).T
|
||||||
|
|
||||||
|
vector_a = mtl_data['vector_a'] = mtl_data['ecef_corners'][1, :] - mtl_data['ecef_corners'][0, :]
|
||||||
|
vector_b = mtl_data['vector_b'] = mtl_data['ecef_corners'][2, :] - mtl_data['ecef_corners'][0, :]
|
||||||
|
vector_c = mtl_data['vector_c'] = mtl_data['ecef_corners'][3, :] - mtl_data['ecef_corners'][0, :]
|
||||||
|
|
||||||
|
altitude = mtl_data['altitude'] = 710e3
|
||||||
|
vector_s = mtl_data['vector_s'] = (vector_a + vector_c) / 2 - altitude * np.cross(vector_a, vector_c) / np.linalg.norm(np.cross(vector_a, vector_c))
|
||||||
|
|
||||||
|
b = np.array([vector_b - (vector_a + vector_c)])
|
||||||
|
A = np.array([vector_a - vector_s, vector_c - vector_s, vector_b - vector_s])
|
||||||
|
mnt = np.linalg.solve(A.T, b.T)
|
||||||
|
print(mnt)
|
||||||
|
mtl_data['mu'], mtl_data['nu'] = mnt[0][0], mnt[1][0]
|
||||||
|
|
||||||
|
return mtl_data
|
||||||
|
|
||||||
|
def lat_lot_to_pixel(lat, lon, mtl_data):
|
||||||
|
target_vector = np.array([lat, lon, 0])
|
||||||
|
|
||||||
|
x1, y1, z1 = pyproj.transform(mtl_data['lla'], mtl_data['ecef'],
|
||||||
|
target_vector[1], target_vector[0], target_vector[2], radians=False)
|
||||||
|
x2, y2, z2 = pyproj.transform(mtl_data['lla'], mtl_data['ecef'],
|
||||||
|
mtl_data['lat_lon_corners'][0, 1], mtl_data['lat_lon_corners'][0, 0], mtl_data['lat_lon_corners'][0, 2], radians=False)
|
||||||
|
|
||||||
|
x = np.array([x1-x2, y1-y2, z1-z2])
|
||||||
|
v = np.cross(mtl_data['vector_c'], mtl_data['vector_a'])
|
||||||
|
xh = np.divide(np.dot(v.T, x), np.linalg.norm(v))
|
||||||
|
x1, y1, z1 = pyproj.transform(mtl_data['lla'], mtl_data['ecef'],
|
||||||
|
target_vector[1], target_vector[0], -xh, radians=False)
|
||||||
|
x = np.array([x1-x2, y1-y2, z1-z2])
|
||||||
|
A = np.array([
|
||||||
|
(1+mtl_data['mu'])*mtl_data['vector_a'] - mtl_data['mu']*mtl_data['vector_s'],
|
||||||
|
(1+mtl_data['nu'])*mtl_data['vector_c'] - mtl_data['nu']*mtl_data['vector_s'],
|
||||||
|
x-mtl_data['vector_s']
|
||||||
|
]).T
|
||||||
|
z = np.linalg.solve(A, x.T)
|
||||||
|
|
||||||
|
k = round(z[0], 4)
|
||||||
|
r = round(z[1], 4)
|
||||||
|
|
||||||
|
target_x = min([max([1, round(k*mtl_data['width'] + 0.5)]), mtl_data['width']])
|
||||||
|
target_y = min([max([1, round(r*mtl_data['height'] + 0.5)]), mtl_data['height']])
|
||||||
|
|
||||||
|
return target_x, target_y
|
Loading…
Reference in a new issue