Custom Tattoo

Every summer at home, the setting sun casts long shadows across the valleys and an endless procession of crows make their way to wherever crows go on lovely warm nights. It’s pretty idyllic, and it’s one of my favorite things about where I grew up.

About a year ago (summer 2022) I got my first tattoo, and I liked it a lot. Since then I’ve gotten a few more and have still a few more I’d like to get. For a long while though, I’ve wanted a tattoo that reminds me of home. Something I could always keep with me no matter how far I find myself from our little valley.

I like a minimalistic tattoo style, just some linework really - but packed with a bunch of meaning and nuance. For this tattoo, I wanted the ridgeline of the valley I see when I look out past my yard with crows flying through the valley.

Realistically, I could have a tattoo artist draw any nondescript squiggle and call it the ridgeline, but I wanted something a little more personal than that. I decided I would try to use some sort of programmatic analysis to recreate a high fidelity representation of the ridgeline as viewed from my house.

This presents a few problems... What kind of data is going to allow me to recreate the ridgeline? How precise does that data need to be? And what kind of algorithm or analysis will I need to employ to actually extract a ridgeline? How can I be sure it is satisfactory…?

Using RasTer data…

The USGS keeps a great database of maps of different kinds you can download for various projects - I made great use of this both personally and professionally when I interned for the National Parks Service as a GIS Intern. Specifically, Digital Elevation Models (or DEMs, for short) are extremely useful raster datasets that encode elevation profiles with various levels of resolution for an area. Downloading the raster, I was able to generate this depth map for my valley, where my vantage point is the red dot.

Here’s a version more closely zoomed in on my region of interest.

Using a pretty crude homemade algorithm, I did a viewshed analysis to create a binary image of all the regions that are visible or not from my home. Visibility is only based on the 30m resolution elevation data and does not account for trees or structures. Generally speaking, 30m is fairly coarse but good enough when we just care about the rougher general topographic features.

Since I live on the north side of the valley I want to compute the southernmost pixels I can see, this represents the ridgeline of the valley!

Taking a step back, what the heck do I have here? This is no tattoo I would want on my body. What we see here is the white line trying to represent an aerial view of what constitutes the southern rim of the valley as viewed from my house.

If you’re looking at those discontinuities thinking we may be running into some trouble, you’re exactly right. When we try and translate this into a vertical elevation profile, we get a line that suffers immensely from those discontinuities.

I tried a few different techniques to smooth out the discontinuities we see here (check those out in the source code linked at the end) but ultimately, my data and approach just weren’t good enough to create a profile that looked even remotely representative of the ridgeline.

Back to the Drawing Board…

A couple of months later I was back home for the summer and I took this photo, seen at the top of this post.

And as I marveled at how lovely my home is, I realized that what I had here was exactly the data I was looking for. A clear representation of the ridgeline as seen from my back yard.

I’d also dabbled with some edge detection algorithms a few months prior in another project. What would it look like if I applied that here?

Well, there are a number of edge detection algorithms in existence today. Some are neural and other are algorithmic. I tried both to see what I liked better.

Neural Edge Detection

As you can see, the neural edge detection outputs an image that looks pretty cool. One downside (in my opinion) is that the probabilistic nature of the neural approach gives us a bit of fuzziness at times in our rendering.

Canny Edge Detection Algorithm

On the other hand, the Canny algorithm gives us extremely crisp lines! However, depending on how many details there are in the image, we can get some pretty noisy looking outputs like we see here.

I tried running the output of the neural network into the Canny algorithm to see if I could get the best of both worlds…

Neural Edge Detection Output Passed Through Canny Edge Detection Algorithm

It worked! The neural network is really great at ignoring small details that aren’t that important for picking out the most significant edges. By reducing the amount of detail in the image like this, it makes for great inputs to the Canny algorithm that come out crisp and simple.

But our work isn’t done. As much as I like tattoos, I don’t want one this sprawling and complex. Just a nice simple ridgeline. I cleaned it up in MS Paint. Maybe I could have written a quick script to clean this up, but that felt like an “over engineered solution”.

The final tattoo template.

And here it is! I decided to leave the rising moon in it simply because it looked cool. With this, I was able to give this to a tattoo artist as a stencil and get it tattooed on me.

I’ll admit, it’s a little ironic that my tattoo symbolizing home was done by a Polish guy in Amsterdam. But I like to put a poetic spin on it. I’ve always got a little bit of home with me, wherever I go.

Check the code for the raster analysis here and the edge detection algorithm here.

Thanks for reading!

Previous
Previous

Image Perturbation (pt 1)

Next
Next

Sightless Navigation using Absolute Monocular Depth Estimation