The DefaultPunks project contains a token for every possible unique CryptoPunk silhouette. Rendering Punk silhouettes is straightforward: iterate through all the Punk's pixels and make all the non-transparent pixels the same color. Do this for all 10k Punks, remove duplicates, and you're left with 954 unique silhouettes.
Two Punks have the same silhouette when the attributes that make them distinct do not affect their silhouettes. E.g., if the only difference between two Punks is a Clown Nose, their silhouettes will be identical.
This begs the question: which traits affect Punk silhouettes? To answer this, we computed silhouette-affecting traits on a per-Punk basis by removing each of the Punk's traits, recalculating the Punk's silhouette, and storing the trait if the silhouette changed. Then, to find the traits that define a given silhouette, take the unique silhouette-affecting traits of the Punks that define the silhouette.