Inspired by Alex Onsager and his wacky web app Pokemon Fusion, I was thinking about improving his approaches myself. In his post Pokemon Fusion: Behind the Scenes, he explains how he makes the head-swapping. Basically this can be included in three steps:
- Manually prepare separate parts (a head and a body) of a Pokémon.
- Determine the face size.
- Determine the main palette of a Pokémon.
- Transplant the head to its new owner and unify the torso color.
Introducing the King in the Soil: Dugking!
The resizing part is definitely a highlight. But some weird combinations could be easily noticed due to the “manual separation”, such as this Magikarp head on a Gyarados body:
Nevertheless, it is some brilliant work done by Alex.
Alex mentions he plans only to support the first 151 Pokémons for his site. Understandable, because it’s really hard to automate the head/torso separation. To be honest, I really wish there could be some magical facical recognition algorithm for Pokémons.
The first thing is to scrape the sprites of Pokémons. My target website is Pokémon Database which has a pretty organized gallery of all 809 Pokémons from 7 generations.
rvest is not the hard part. The only thing tricky worth mentioning is the set the sleeping time between batches. How do I know this? Learn from trials.
t0 <- Sys.time() # do things here t1 <- Sys.time() Sys.sleep(0.5*as.numeric(t1-t0))
Sleeping time is proportional to response time.
- Load the images of Pokémon A and Pokémon B.
- Use K-means to find the main palette of the two.
- Simply swap the colors of two palettes. In fact, we are swapping two vectors of clustering assignments.
- Reconstruct the Pokémon A with main palette of Pokémon B. (I forgot to make the other way around, sorry.)
At this point, I’ve realized that facial recognition with data so far is not practical since all images are only of size 30x40 pixels. In other words, the data is too limited.
Anyways, there are still something I want to point out during the four steps above.
- Although the scraped images are in PNG format with transparent background, once loaded with
load.image(), the RGB of these transparent pixels will “turn to the darkside”.
- I am pretty sure in most of the cases, the top two clusterings are the background “Mr Black” and some darkish grey boundary. You can alwasy check their sizes to confirm.
- When swapping the palettes between two Pokémons, we can just ignore these two unnecessary colors.
- Due to the randomness in K-means (
km()), the generated clusterings differ slightly from time to time.
- The number of clusterings
kI pick here is 7. Just do not set it too large.
- The number of clusterings
Are Red Gyarados extremely rare? Maybe.
But ladies and gentlemen, I present you the Elite Four of Blue Magikarps!
And four mediocore red worms. Meh!
As I mentioned above, the head swapping process cannot be fulfilled with this scale of data. The least I can do is to implement the color swapping. You can find my codes on GitHub. Have fun playing with it!