Skip to content

Instantly share code, notes, and snippets.

@jdbcode
Last active March 23, 2023 17:59
Show Gist options
  • Save jdbcode/f3ebf33bfdf74a257b734a1ff61bc83b to your computer and use it in GitHub Desktop.
Save jdbcode/f3ebf33bfdf74a257b734a1ff61bc83b to your computer and use it in GitHub Desktop.
Create image chips that have consistent dimensions despite varying aspect ratios of input image region using Earth Engine and PIL
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/jdbcode/f3ebf33bfdf74a257b734a1ff61bc83b/ee_image_chips.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "cwxd0NG5Nk_7"
},
"outputs": [],
"source": [
"import ee\n",
"ee.Authenticate()\n",
"ee.Initialize()"
]
},
{
"cell_type": "markdown",
"source": [
"FeatureCollection of cities"
],
"metadata": {
"id": "GOYgn3aSYS6E"
}
},
{
"cell_type": "code",
"source": [
"cities_fc = ee.FeatureCollection(\n",
" [ee.Feature(\n",
" ee.Geometry.Polygon(\n",
" [[[-86.30931396484377, 40.08385948719423],\n",
" [-86.52080078125002, 39.87550140515563],\n",
" [-86.53453369140627, 39.72145688768831],\n",
" [-86.22966308593752, 39.44839825753037],\n",
" [-85.81767578125002, 39.63901776816407],\n",
" [-85.78197021484377, 39.88603977106767],\n",
" [-85.89732666015627, 40.111172435524274]]]),\n",
" {\n",
" \"city_name\": \"city_0\"\n",
" }),\n",
" ee.Feature(\n",
" ee.Geometry.Polygon(\n",
" [[[-86.99870605468752, 40.51119785354961],\n",
" [-87.00145263671877, 40.385790713738075],\n",
" [-86.86961669921877, 40.29367679615214],\n",
" [-86.66636962890627, 40.43598164994896]]]),\n",
" {\n",
" \"city_name\": \"city_1\"\n",
" }),\n",
" ee.Feature(\n",
" ee.Geometry.Polygon(\n",
" [[[-86.23515625000002, 40.52998873829066],\n",
" [-86.19670410156252, 40.392066627828704],\n",
" [-86.05113525390627, 40.35858832843792],\n",
" [-86.03740234375002, 40.477778831614565],\n",
" [-86.10881347656252, 40.55294822166985]]]),\n",
" {\n",
" \"city_name\": \"city_2\"\n",
" })]);"
],
"metadata": {
"id": "0EIiL4ipYB1v"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"An impervious surface image visualized as RGB"
],
"metadata": {
"id": "jBf6CD82YYtt"
}
},
{
"cell_type": "code",
"source": [
"img = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019').select('impervious')\n",
"vis_img = img.visualize(min=0, max=100, palette=['white', 'yellow', 'brown', 'black'])"
],
"metadata": {
"id": "OK0lf8N4Ntok"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Get bounds and add buffer to each city"
],
"metadata": {
"id": "iXN41HiRYfuz"
}
},
{
"cell_type": "code",
"source": [
"city_names = cities_fc.aggregate_array('city_name').distinct()\n",
"\n",
"def city_box(city_name):\n",
" city_box = (cities_fc.filter(ee.Filter.eq('city_name', city_name))\n",
" .geometry().bounds().buffer(1000, 1)) # 1 km buffer\n",
" return ee.Feature(city_box).set('city_name', city_name)\n",
"\n",
"city_boxes_fc = ee.FeatureCollection(city_names.map(city_box))"
],
"metadata": {
"id": "1Uvu1ufNYe1a"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Loop to download images"
],
"metadata": {
"id": "bal2V8KDaidh"
}
},
{
"cell_type": "code",
"source": [
"import urllib.request\n",
"from PIL import Image, ImageOps\n",
"\n",
"city_names_client = city_names.getInfo()\n",
"\n",
"def overlay_boundary(city_name):\n",
" city_features = cities_fc.filter(ee.Filter.eq('city_name', city_name))\n",
" return vis_img.clipToCollection(city_features).unmask(0)\n",
"\n",
"def add_padding(img_file, target_size):\n",
" img = Image.open(img_file)\n",
" width, height = img.size\n",
"\n",
" delta_w = target_size - width\n",
" delta_h = target_size - height\n",
"\n",
" pad_left = delta_w // 2\n",
" pad_right = delta_w - pad_left\n",
" pad_top = delta_h // 2\n",
" pad_bottom = delta_h - pad_top\n",
"\n",
" padded_img = ImageOps.expand(img, (pad_left, pad_top, pad_right, pad_bottom), fill=(0, 0, 0))\n",
"\n",
" padded_img.save(f'{img_file[:-4]}_padded.png')\n",
"\n",
"for city_name in city_names_client:\n",
" print(f'Downloading: {city_name}')\n",
" image_to_download = overlay_boundary(city_name)\n",
" img_url = image_to_download.getThumbURL({\n",
" 'dimensions': 1280,\n",
" 'region': city_boxes_fc.filter(ee.Filter.eq('city_name', city_name)).geometry(),\n",
" 'crs': 'EPSG:4326'\n",
" })\n",
"\n",
" filename = f'{city_name}.png'\n",
" urllib.request.urlretrieve(img_url, filename)\n",
"\n",
" add_padding(filename, 1280)"
],
"metadata": {
"id": "XBQ2JYGCamCV"
},
"execution_count": null,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment