--- title: "K.A.R.L" date: 2021-04-01 cover: ./images/Indicatrices_of_Distortion.png license: "CC-BY-SA:4.0" featured: true toc: true icon: /projects/karl/favicon.png links: [ ["live", "https://max-richter.dev/karl"], ["git", "https://git.max-richter.dev/max/karl"], ] --- import Crosswalk from "./images/crosswalk.jpg" import CrosswalkMask from "./images/crosswalk_mask.png" import Image from "@components/Image.astro" import Distorion from "./images/Indicatrices_of_Distortion.png" import ImageGallery from "@components/ImageGallery.svelte" *[Header by Justin Kunimune - Own work, CC BY-SA 4.0](https://commons.wikimedia.org/w/index.php?curid=66467577*)* > K.A.R.L is a web app that helps to divide 360-degree panoramas into sections (sky, ground, trees, etc.) and then determine the proportion of each section in the overall image. # Introduction The project emerged from a collaboration with two friends. One of them is in the conceptual phase of his bachelor's thesis (Geography), which deals with the impact of vegetation on urban climate. To this end, he conducted albedo measurements at various locations in Cologne—essentially measuring "how much light comes from the sky, and how much of it is reflected by the ground." To put these measurements into context, he took 360-degree panoramas at each measurement location, which look something like this: Image of a crosswalk He then needed data on what percentage of the view was occupied by vegetation, sky, and ground. To measure this, he manually created a segmentation map in Gimp, which looks something like this: Segmentation map # Problem Statement If we naively count the pixels of each color and use that to calculate a percentage distribution, we encounter the classic distortion problem that humanity has faced for centuries with maps. Spheres do not like being represented in two dimensions, which always leads to distortions, as visualized in the following image. Indicatrices of Distortion Fortunately, this distortion only occurs in width, so we need a formula that provides a weight for the height of a pixel to compensate for this distortion. After many attempts, we arrived at this formula: ```javascript /* height: height of the image in pixels calibrationFactor: 1.333, somehow this works, don't ask why, we don't either y: y position of the pixel */ const pixelValue = Math.cos( (((360 / height ** 2) * y ** 2 + (-360 / height) * y + 90) / 360) * (2 + calibrationFactor) * Math.PI ) ``` This formula is actually designed to calculate the distance between two longitudes for a given latitude, but it works very well for our purposes. Here are some of the first attempts in Desmos (fantastic tool, by the way):