Skip to content

Instantly share code, notes, and snippets.

@KMarkert
Last active September 4, 2020 23:00
Show Gist options
  • Save KMarkert/055a9334d64ad8e2d9e1d6b146f5e5a0 to your computer and use it in GitHub Desktop.
Save KMarkert/055a9334d64ad8e2d9e1d6b146f5e5a0 to your computer and use it in GitHub Desktop.
using PyCall, JSON, Images, Plots
# import gcloud authentication packages for interacting with the EE REST API
service_account = pyimport("google.oauth2.service_account");
gauth = pyimport("google.auth.transport.requests");
# path to service account secret key
# see the folowing link for details to key:
# https://developers.google.com/earth-engine/reference/Quickstart#obtain-a-private-key-file-for-your-service-account
SECRET_KEY = "<PATH_TO_SECRET_KEY>"
# define the credentials to authorize
credentials = service_account.Credentials.from_service_account_file(SECRET_KEY)
scoped_credentials = credentials.with_scopes(
["https://www.googleapis.com/auth/cloud-platform"])
# authorize a session to start sending requests
session = gauth.AuthorizedSession(scoped_credentials)
# define the project and asset we want to access
project = "projects/earthengine-public"
asset_id = "COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG"
# create an endpoint url to access the data from asset
name = "$project/assets/$asset_id"
url = "https://earthengine.googleapis.com/v1alpha/$name:getPixels"
# define some parameters to control what data, how much, and where we request data
w,h = 1000,1000 # x and y dimensions to request
res = 50 # pixel resolutions in meters
bands = ["B2","B3","B4","B8"] # array of desired bands to request
nbands = size(bands,1) # number of bands
dtype = UInt16 # output data type of pixels, this is important and will change depending on dataset!!!
# define the parameter content for the http POST request
# see the following link for more details on accepted paramters:
# https://developers.google.com/earth-engine/reference/rest/v1alpha/projects.assets/getPixels
params = Dict(
"fileFormat" => "NPY",
"bandIds" => bands,
"grid" => Dict(
"affineTransform" => Dict(
"scaleX" => res,
"scaleY" => -res,
"translateX" => 530000,
"translateY" => 4200000
),
"dimensions" => Dict("width" => w,"height" => h)
)
)
# dump dict values to json string
body = JSON.json(params)
# post the http request
pixel_response = session.post(url,body)
# should be 200 response...
# need to add in control to make sure it is
# now we take the response and read the data as a Julia array
# this is a hacky way of reading NPY data from the reponse as an array in Julia...
img = begin
# create a mem buffer to read response contents to
buffer = IOBuffer()
write(buffer,pixel_response.content)
# acutally get the data and interpret is as the dtype specified earlier
foo = reinterpret(dtype,take!(buffer))
close(buffer) # close the io buffer for clean memory management
# find the number of pixels we expect based on img
data_size = w*h*nbands
# find the offset of what was returned vs what is expected
offset = size(foo,1)-data_size + 1
# read byte values as intergers and trim the unneeded bytes from npy header
arr = Int.(foo)[offset:end]
# reshape array from 1-d to correct 3-d dimensions
arr3d = reshape(arr,(nbands,h,w))
# reorder the dimensions for row-major to column-major
permutedims(arr3d,(1,3,2))
end
# the result is an 3-d array with (4, 1000, 1000) dimensions
# now that we have the data, we can start doing fun stuff within Julia!
maxv = 3300 # maximum value for display purposes
gamma = 1.3 # gamma correction value for display purposes
# get the rgb channels, scale by max value and apply gamma correction
rgb_img = (Float64.(img[1:3,:,:][end:-1:1,:,:])./maxv).^gamma;
# convert to an `Image` for display purposes
display = colorview(RGB, rgb_img);
# display the image
plot(display, ticks=nothing, border=:none,dpi=300)
savefig("julia_ee_rest_example.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment