Spaces:
Runtime error
Runtime error
| # based on https://huggingface.co/spaces/NimaBoscarino/climategan/blob/main/app.py # noqa: E501 | |
| # thank you @NimaBoscarino | |
| import os | |
| from datetime import datetime | |
| from textwrap import dedent | |
| from urllib import parse | |
| import googlemaps | |
| import gradio as gr | |
| import numpy as np | |
| from gradio.components import ( | |
| HTML, | |
| Button, | |
| Column, | |
| Dropdown, | |
| Image, | |
| Markdown, | |
| Radio, | |
| Row, | |
| Textbox, | |
| ) | |
| from requests import get | |
| from skimage import io | |
| from climategan_wrapper import ClimateGAN | |
| TEXTS = [ | |
| dedent( | |
| """ | |
| <p> | |
| Climate change does not impact everyone equally. | |
| This Space shows the effects of the climate emergency, | |
| "one address at a time". | |
| Visit the original experience at | |
| <a href="https://thisclimatedoesnotexist.com/"> | |
| ThisClimateDoesNotExist.com | |
| </a> | |
| </p> | |
| <br> | |
| <p> | |
| Enter an address or upload a Street View image, and ClimateGAN | |
| will generate images showing how the location could be impacted | |
| by flooding, wildfires, or smog if it happened there. | |
| </p> | |
| <br> | |
| <p> | |
| This is <strong>NOT</strong> an exercise in climate prediction, | |
| rather an exercise of empathy, to put yourself in others' shoes, | |
| as if Climate Change came crushing on your doorstep. | |
| </p> | |
| <br> | |
| <p> | |
| After you have selected an image and started the inference you | |
| will see all the outputs of ClimateGAN, including intermediate | |
| outputs such as the flood mask, the segmentation map and the | |
| depth maps used to produce the 3 events. | |
| </p> | |
| <br> | |
| <p> | |
| This Space makes use of recent Stable Diffusion in-painting | |
| pipelines to replace ClimateGAN's original Painter. If you | |
| select 'Both' painters, you will see a comparison | |
| </p> | |
| <br> | |
| <p style='text-align: center'> | |
| Visit | |
| <a href='https://thisclimatedoesnotexist.com/'> | |
| ThisClimateDoesNotExist.com</a> | |
| for more information | |
| | | |
| Original | |
| <a href='https://github.com/cc-ai/climategan'> | |
| ClimateGAN GitHub Repo | |
| </a> | |
| | | |
| Read the original | |
| <a | |
| href='https://arxiv.org/abs/2110.02871' | |
| target='_blank'> | |
| ICLR 2022 ClimateGAN paper | |
| </a> | |
| </p> | |
| """ | |
| ), | |
| dedent( | |
| """ | |
| ## How to use this Space | |
| 1. Enter an address or upload a Street View image (at least 640x640) | |
| 2. Select the type of Painter you'd like to use for the flood renderings | |
| 3. Click on the "See for yourself!" button | |
| 4. Wait for the inference to complete, typically around 30 seconds | |
| (plus queue time) | |
| 5. Enjoy the results! | |
| 1. The prompt for Stable Diffusion is `An HD picture of a street with | |
| dirty water after a heavy flood` | |
| 2. Pay attention to potential "inventions" by Stable Diffusion's in-painting | |
| 3. The "restricted to masked area" SD output is the result of: | |
| `y = mask * flooded + (1-mask) * input` | |
| """ | |
| ), | |
| ] | |
| CSS = dedent( | |
| """ | |
| a { | |
| color: #0088ff; | |
| text-decoration: underline; | |
| } | |
| strong { | |
| color: #c34318; | |
| font-weight: bolder; | |
| } | |
| #how-to-use-md li { | |
| margin: 0.1em; | |
| } | |
| #how-to-use-md li p { | |
| margin: 0.1em; | |
| } | |
| """ | |
| ) | |
| def toggle(radio): | |
| if "address" in radio.lower(): | |
| return [ | |
| gr.update(visible=True), | |
| gr.update(visible=False), | |
| gr.update(visible=True), | |
| ] | |
| else: | |
| return [ | |
| gr.update(visible=False), | |
| gr.update(visible=True), | |
| gr.update(visible=True), | |
| ] | |
| def predict(cg: ClimateGAN, api_key): | |
| def _predict(*args): | |
| print(f"Starting inference ({str(datetime.now())})") | |
| image = place = painter = radio = None | |
| if api_key: | |
| radio, image, place, painter = args | |
| else: | |
| image, painter = args | |
| if api_key and place and "address" in radio.lower(): | |
| geocode_result = gmaps.geocode(place) | |
| address = geocode_result[0]["formatted_address"] | |
| static_map_url = f"https://maps.googleapis.com/maps/api/streetview?size=640x640&location={parse.quote(address)}&source=outdoor&key={api_key}" | |
| img_np = io.imread(static_map_url) | |
| print("Using GSV image") | |
| else: | |
| print("Using user image") | |
| img_np = image | |
| painters = { | |
| "ClimateGAN Painter": "climategan", | |
| "Stable Diffusion Painter": "stable_diffusion", | |
| "Both": "both", | |
| } | |
| print("Using painter", painters[painter]) | |
| output_dict = cg.infer_single( | |
| img_np, | |
| painters[painter], | |
| concats=[ | |
| "input", | |
| "masked_input", | |
| "climategan_flood", | |
| "stable_copy_flood", | |
| ], | |
| as_pil_image=True, | |
| ) | |
| input_image = output_dict["input"] | |
| masked_input = output_dict["masked_input"] | |
| wildfire = output_dict["wildfire"] | |
| smog = output_dict["smog"] | |
| depth = np.repeat(output_dict["depth"], 3, axis=-1) | |
| segmentation = output_dict["segmentation"] | |
| climategan_flood = output_dict.get( | |
| "climategan_flood", | |
| np.ones(input_image.shape, dtype=np.uint8) * 255, | |
| ) | |
| stable_flood = output_dict.get( | |
| "stable_flood", | |
| np.ones(input_image.shape, dtype=np.uint8) * 255, | |
| ) | |
| stable_copy_flood = output_dict.get( | |
| "stable_copy_flood", | |
| np.ones(input_image.shape, dtype=np.uint8) * 255, | |
| ) | |
| concat = output_dict.get( | |
| "concat", | |
| np.ones(input_image.shape, dtype=np.uint8) * 255, | |
| ) | |
| return ( | |
| input_image, | |
| masked_input, | |
| segmentation, | |
| depth, | |
| climategan_flood, | |
| stable_flood, | |
| stable_copy_flood, | |
| concat, | |
| wildfire, | |
| smog, | |
| ) | |
| return _predict | |
| if __name__ == "__main__": | |
| ip = get("https://api.ipify.org").content.decode("utf8") | |
| print("My public IP address is: {}".format(ip)) | |
| api_key = os.environ.get("GMAPS_API_KEY") | |
| gmaps = None | |
| if api_key is not None: | |
| gmaps = googlemaps.Client(key=api_key) | |
| cg = ClimateGAN( | |
| model_path="config/model/masker", | |
| dev_mode=os.environ.get("CG_DEV_MODE", "").lower() == "true", | |
| ) | |
| cg._setup_stable_diffusion() | |
| radio = address = None | |
| pred_ins = [] | |
| pred_outs = [] | |
| with gr.Blocks(css=CSS) as app: | |
| with Row(): | |
| with Column(): | |
| Markdown("# ClimateGAN: Visualize Climate Change") | |
| HTML(TEXTS[0]) | |
| with Column(): | |
| Markdown(TEXTS[1], elem_id="how-to-use-md") | |
| with Row(): | |
| HTML("<hr><br><h2 style='font-size: 1.5rem;'>Choose Inputs</h2>") | |
| with Row(): | |
| with Column(): | |
| if api_key: | |
| radio = Radio(["From Address", "From Image"], label="Input Type") | |
| pred_ins += [radio] | |
| im_inp = Image(label="Input Image", visible=not api_key) | |
| pred_ins += [im_inp] | |
| if api_key: | |
| address = Textbox(label="Address or place name", visible=False) | |
| pred_ins += [address] | |
| with Column(): | |
| pred_ins += [ | |
| Dropdown( | |
| choices=[ | |
| "ClimateGAN Painter", | |
| "Stable Diffusion Painter", | |
| "Both", | |
| ], | |
| label="Choose Flood Painter", | |
| value="Both", | |
| ) | |
| ] | |
| btn = Button( | |
| "See for yourself!", | |
| label="Run", | |
| variant="primary", | |
| visible=not api_key, | |
| ) | |
| with Row(): | |
| Markdown("## Outputs") | |
| with Row(): | |
| pred_outs += [Image(type="numpy", label="Original image")] | |
| pred_outs += [Image(type="numpy", label="Masked input image")] | |
| pred_outs += [Image(type="numpy", label="Segmentation map")] | |
| pred_outs += [Image(type="numpy", label="Depth map")] | |
| with Row(): | |
| pred_outs += [Image(type="numpy", label="ClimateGAN-Flooded image")] | |
| pred_outs += [Image(type="numpy", label="Stable Diffusion-Flooded image")] | |
| pred_outs += [ | |
| Image( | |
| type="numpy", | |
| label="Stable Diffusion-Flooded image (restricted to masked area)", | |
| ) | |
| ] | |
| with Row(): | |
| pred_outs += [Image(type="numpy", label="Comparison of flood images")] | |
| with Row(): | |
| pred_outs += [Image(type="numpy", label="Wildfire")] | |
| pred_outs += [Image(type="numpy", label="Smog")] | |
| Image(type="numpy", label="Empty on purpose", interactive=False) | |
| btn.click(predict(cg, api_key), inputs=pred_ins, outputs=pred_outs) | |
| if api_key: | |
| radio.change(toggle, inputs=[radio], outputs=[address, im_inp, btn]) | |
| app.launch(show_api=False) | |