6 ms·
Show HN: Simple algorithm and color space to generate diverse skin tones
Hello HN!
I found that picking out plausible but diverse skin tones for my digital art and game development projects was kind of difficult, and I got curious about if there was a way to define a color space that made it easy.
I've built a color picker and procedural generation algorithm based on the space as well as a bunch of other fun js features and demos throughout the page that use the equations. If you find it interesting, I have lots of explanations of how I built it and what properties the space has.
The methodology might be a bit shaky, but hopefully the result is as helpful for others as I have found it! There's lots of room for improvements (see the Future Work section), but I'm really happy with how it turned out.
- deleted 2mo ago[deleted]
- m_w_ 2mo agoThis is super cool! I have always loved projects that try to categorize color space. Usually my work has gone in the other direction - isGray, isCloseToWhite, isPastel - but it's the same insofar as it's defining shapes like your matplot visual. Wish I had this on hand like this three or four years ago when I was working on VR avatar software - we had hard-coded skin tone options at the time - would have been a cool addition!
- automatoney 2mo agoIn sharing this around I've found more people than I thought who've done things to semantically chop up the color space - definitely a more interesting area than I first thought of when working on my narrow use case. Feels like it'd be fun to play with something that has a whole bunch of different regions of color space labeled - like "here's where IsPastel overlaps with IsGreen". But absolutely the hope is that this is a tool that stays accessible to people for whatever they're building and everyone can slow down on reinventing the wheel here for every character creator/digital art application.
- tyromaniac 2mo ago[dead]
- moralestapia 2mo ago[flagged]
- Tossrock 2mo ago...Did you read the article, or use the picker? It's a continuous (up to the limits of RGB quantization) space which includes thousands upon thousands of shades of black. The selected tones at the top of the article are random and change continuously.
- 4848489449 2mo ago[flagged]
- andai 2mo agoNice. Most of these colors look right to me, but I'm also seeing green, blue and purple? If you're curating colors from the space manually then it's not a problem. "Only realistic colors" would be a different problem. And I'm not sure if there's a way to solve that problem without excluding some real colors too. (Maybe if the colour selector was a different shape? I don't know much about color spaces.)
- automatoney 2mo agoYes absolutely right on - I mention much deeper in the page that in a picker UI you can use a bigger range, but that in a generation context you might want to be a bit more selective. I go into it a bit more when I explain what R^2 is. "not sure if there's a way to solve that problem without excluding some real colors too" - 100% right on that too. A big part of this work was to define a way to tweak/improve the equations in order to approach a solution to these issues - part of my hope in sharing is to get more eyes and brains thinking about this and proposing improvements!
- compass_copium 2mo agoI would have "show sphere" on by default--this kind of threw me at first, too. This is a really nice project. Great work and a great write-up. Thanks for sharing.
- wongarsu 2mo agoIf you drag the bottom slider all the way to the right you only have plausible skin tones. Drag it all the way to the right and you can match skin tones for orcs, Na'vi and djinn
- richiebful1 2mo agoReducing the R^2 value to ~1.5 excludes skin colors that are extremely blue, green and purple. That seems to be a happy medium between including real outliers and excluding colors like green.
- rsynnott 2mo ago> blue You'd be surprised: https://en.wikipedia.org/wiki/Argyria https://en.wikipedia.org/wiki/Argyria
- Abh1Works 2mo agoCool work!
- 383toast 2mo agoSeems to underrepresent pale skin tone variety
- LocalH 2mo agoTurn off your dark mode reader extension
- BHSPitMonkey 2mo agoUnder-represent relative to what, exactly?
- numpad0 2mo agoyeah, skin tone variations often feels it's about limiting lighter tone options while adding luminosity options for the exact same brown color. There seem to be B channel differences across darker colored people, and I wouldn't be sure if they are better represented either.
- vermarish 2mo agoThis is beautiful work! First, I thought this would involve using PCA to go from 3D to 2D, which would result in an easier selector to use, but at the expense of representing every person. Then, I thought this would stop at using the U-space vectors (the ones that form the basis of the PCA image) and their corresponding ellipse to form our color space, but no, the function fitting is a very slick idea, even if it was executed by hand. Lastly, I love the presentation of sampling from different r values. Whether you sample from a fixed r value or a range of r values, I bet this has great applications in game design or animation. I still don't quite get the manual data labeling process at the beginning? It seems like it would encode some bias, but the consistency of the first point cloud and the results certainly speak for themselves.
- automatoney 2mo agoThank you! I call out the manual labeling bias and also that a future work improvement would be to be scientific about that labeling process (multiple labelers, expert labelers), and then to feed that into the equation generation steps. Part of where the "good enough" naming comes from - I was hoping that using my art brain and keeping a bunch of reference images in mind (shout out to the Humanae project) would maybe offset the bias a bit. But 100% right on the bias being there.
- dr_scully 2mo agoIf you look at my doctoral thesis, in fact skin colour can be parametrised using melanin and haemoglobin concentration; which it means it is indeed (roughly) two dimensional. This allows you to invert the colour of a pixel and identify someone’s chromophore concentration. This is based on previous work of others cited in the thesis. https://discovery.ucl.ac.uk/id/eprint/10093345/ https://discovery.ucl.ac.uk/id/eprint/10093345/
- GolDDranks 2mo agoI've heard that the so-called "yellowish" skin color that non-tanned East Asians tend to have, is due to relative abundance of subcutaneous fat. If that's true, is that captured by the haemoglobin dimension or is it a yet another degree of freedom?
- RIMR 2mo agoFor anyone confused, turn off your dark mode extension. :)
- automatoney 2mo agoOh wow, didn't even think of how that sort of thing might affect the page.
- stephantul 2mo agoLove it. I especially thought the introspective “aside” section on related resources was great, and I wish more people would show this kind of reflection.
- automatoney 2mo agoThanks! I hope to send lots of love those ways, they're basically all things that I found outside of this work that I liked enough to remember (I think Humanae was the one that I found while doing this).
- E-Reverance 2mo agoI definitely don't speak for all non-white people when I say this, but personally I find people obsessing over it disturbing/offensive independent of whether their intentions are racist or anti-racist. I did find modeling/data-driven perspective cool though
- benj111 2mo agoI also agree. Yes, humans need to be reminded that not all humans are just like their immediate group, but that goes for all humans, not just the white ones. And I certainly don't get accusations of racism that come along with it. But then I don't really get the needing to be represented thing either. Was I represented by Mario???
- hluska 2mo agoThis is excellent work! You’ve got a 49 year old and a 10 year old equally into it. That’s impressive - nice work.
- ptsneves 2mo agoOn the movie Dolemite by Eddy Murphy, they go over the fact that black people absorb light and white people reflect, and how that changes the motion picture shooting process totally. Also how one size does not fit all. Cool project! I am not much into the humanities part of the project. For me this is as natural as having a localization framework, just in this case for skin tones.
- PullJosh 2mo agoI love this! Such a beautiful use of some real nerdy math to benefit humans in a way non-nerds would appreciate.
- rrradical 2mo agoVery neat project. Could I use this code to generate skin tones in my own project? Or more meant to just be educational/inspirational? I guess I'm wondering if you've considered adding a license.
- automatoney 2mo agoGood catch, added MIT license - feel free to use it! On top of that, my understanding is that math/equations are not subject to copyright, so the core part of this work (the equations/ideas) I think legally has 0 limitations - even if there were a restrictive license. But IANAL so might have some misconceptions.
- Joel_Mckay 2mo agoProcedural generators are often free if you look around for a bit. https://kuhantilope.gumroad.com/l/ultimate-skin https://kuhantilope.gumroad.com/l/ultimate-skin https://extensions.blender.org/add-ons/mpfb/ https://extensions.blender.org/add-ons/mpfb/ https://github.com/alessandro-zomparelli/tissue https://github.com/alessandro-zomparelli/tissue ymmv, as some paid plugins actually speed up the funky blender workflow (the auto-Bake plugin by the same author is important for procedural generated textures.) https://sanctus.gumroad.com/l/SLibrary?layout=profile https://sanctus.gumroad.com/l/SLibrary?layout=profile Have a great day =3
- bellowsgulch 2mo agoSkin is so interesting as a surface to think about how light passes through and bounces off of. There is at least one article published by a technical artist at Pixar who describes modeling a skull within a human scan so that subsurface lighting is more accurately rendered. I suspect you could combine this with dr_scully’s comment and GolDDranks’ to reach the nuance involved in long tail realism details.
- automatoney 2mo agoThere's a lot of really good research papers that touch on this area from what I saw - would definitely be cool to see if that extra nuance could be added without dramatically increasing the math complexity; in its current state, the code could be used in any programming language without a library.
- dofm 2mo agoInteresting though that the 1.5 setting (at least on my older iPhone) doesn’t really ever seem to cover the range of skin tones of indigenous Australians (“aboriginal” and Torres Strait Islanders), who apparently get their skin tones from a somewhat different expression of genes than other peoples with darker skin. The 2.0 “outliers” cover those skin tones. Masai and some Somali skin tones, similarly, look better represented by the outliers. The full range of possible human skin tones is perhaps a bit of a challenge for technical colour representation, partly because diffuse reflectance seems to vary so much and that is hard to approximate on screen (e.g. as any website designer could attest, the difference between representing silver and grey is the use of highlights), though the representation of skin tones is a lot better than the early colour film era.
- automatoney 2mo agoYes, 2.0 is the value I tuned the equations around - but I think there's definitely room for improvement in terms of squashing the space along the fair/deep axis in order to get better results at lower R^2. The issue I ran into was what happens when the space moves beyond RGB, but I think the fix is to just add clamps to the end R, G, B values.
- efitz 2mo agoNever seen anyone #E6FFF8 (bottom right corner). An albino that consumed too much colloidal silver for years?
- hneqy2wqls 2mo ago[dead]
- xp84 2mo agoThis part ( https://toneyalexander.github.io/inclusive-color-space/#picker-ui https://toneyalexander.github.io/inclusive-color-space/#pick... ) is especially cool. Would love to see this 3-D picker ability in the many character designers out there, instead of the lame 8 swatches or whatever.
- barbecue_sauce 2mo agoI think the ideal would be to use this picker to select a few tones, and then gradient map those across different parts of the body according to a grayscale map. Then you could fine-tune things like palm color, cheeks, facial tone, etc. individually.
- mbo 2mo agoLove it! I was looking at this a little while ago, and used some of The Pudding's data on makeup/foundation shades (https://pudding.cool/2018/06/makeup-shades/ https://pudding.cool/2018/06/makeup-shades/) and plotted it into the Oklab colorspace (https://observablehq.com/@55th/foundation-shades https://observablehq.com/@55th/foundation-shades). The shades form themselves into that same crescent as seen in the article.
- automatoney 2mo agoWoah I LOVE both of these! When I get a chance these are 100% getting linked from the writeup.
- manoDev 2mo agoSkin tones are particularly difficult to pin down, besides the pigmentation there are two effects at play: 1) sub surface scattering (light goes thru and bounces under the skin a bit) and 2) some infra-red emission (the responsible for making some people appear magenta on digital photography) So even when you get the palette right, to paint it like a believable material in a convincing way is still super hard!
- noobahoi 2mo ago[flagged]
- ralusek 2mo agoIf you're ##CCFFFF please go to the hospital
- aaroninsf 2mo agoNot my domain though I followed the data science enough to nod as if I really followed it, but this is just lovely and inspirational work. A unique marriage of hacking in the celebratory sense, thoughtfulness, and meaningful contribution. Outstanding.
- automatoney 2mo agoWow what a touching compliment, thank you so much!!
- drnick1 2mo ago[flagged]
- s1mon 2mo agoIt's always entertaining to try to understand these things from first principles. Color and skin color in particular are very complex things to measure and model. It's not just a physical quantity, it's also a matter of human perception based on lighting and a host of factors. It seems like some work was done to research existing approaches, but I don't see any reference to Pantone Skin Tones [0]. Without intending to, I've worked on 3 different projects which involved measuring skin tones for makeup applications. The Pantone range is not 100% perfect, but it's pretty well done and easy to understand. There are two axes: a light/dark one, and red-yellow one [1]. [0] https://www.pantone.com/na/en-us/skintone https://www.pantone.com/na/en-us/skintone [1] https://cosmeticsbusiness.com/pantone-skintone-guide-80945 https://cosmeticsbusiness.com/pantone-skintone-guide-80945
- ptmkenny 2mo agoThere's also the Monk Skin Tone Scale by Dr. Monk and Google (available under a CC attribution 4.0 international license). It was developed for machine learning, so it's not exactly the same use case, but it provides 10 colors in a variety of formats, including hexadecimal. https://skintone.google/get-started https://skintone.google/get-started
- zild3d 2mo agowell its not a free as in beer color space
- itishappy 2mo agoPantone is not a color space. They are a supplier of physical color samples. Most pigments can be represented in a color space, but that representation differs based on illumination so it not unique. Some Pantone pigments, fluorescent colors in particular, cannot be represented by a color space at all!
- tialaramex 2mo agoYup. This is a rabbit hole like time. Learn a little bit about it, know there's a staggering amount more and then any time you actually need it, check that you've agreed on as much detail as you needed for the task and not less. The person inviting you to a picnic "next week" might need to know about Time Zones if they live some distance away. The requirement to update the CSS on the web site to match a new company logo might need to know about Colour Spaces. But that picnic invite doesn't care about Calendar systems or Leap Seconds, and the logo mandate doesn't care about Sub-surface scattering or a Quantum theory of light.
- richard_chase 2mo ago[flagged]
- dshoemaker 2mo ago> Why do you need diverse skin tones for your art? > It's your art, you can choose whatever skin tones you wish. This is pretty self evident, no?
- richard_chase 2mo ago[flagged]
- DonHopkins 2mo ago[flagged]
- richard_chase 2mo ago[flagged]
- DonHopkins 2mo ago[flagged]
- kentm 2mo agoThey did not present it “as if they don’t have a choice”. I think your personal biases are impacting your reading here.
- richard_chase 2mo ago[flagged]
- DonHopkins 2mo ago
- uhdozo 2mo agoVery interesting, I'll need to read it again lol
- zetanor 2mo agoSetting R² to various large values like 50, 500 and 5000 then moving the slider around seems to give a decent and simple visual representation of what's happening.
- ecesena 2mo agoNice. This is relatively old work (2020) but Pinterest had/has skin tone features, for example if you're searching for cosmetic products. Worth a check if anything might be useful for your work. https://medium.com/pinterest-engineering/powering-inclusive-search-recommendations-with-our-new-visual-skin-tone-model-1d3ba6eeffc7 https://medium.com/pinterest-engineering/powering-inclusive-...
- nahidmahmud555 2mo ago[flagged]
- Sharlin 2mo agoThe U and V axes seem roughly correspond to the tint/temperature (green-magenta/blue-amber) axes that you can find in a white balance tool in photo editors and also as an in-camera setting. Nb. I'd advise against calling the PCA'd space XYZ because that's a well known standard color space: https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_XYZ_color_space https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_XYZ_c...
- dahart 2mo ago> What colors are we? The short answer is maybe something like “brown” and the long answer is very, very long. Pete Shirley (author of Ray Tracing In One Weekend) is also a part time color scientist, and he clued me into the fact that if you crank the saturation to 100% of pictures of people of any race, the skin color comes out orange. I think I heard that some face detectors may work on this principle, but I don’t remember where I heard that.
- madcaptenor 2mo agoand brown is just dark orange.
- dahart 2mo agoYes, true! Though cranking saturation doesn’t brighten colors (much… at least it’s not supposed to), and maybe interestingly, light brown isn’t quite orange. There might some asymmetry in color names. So it might not be that surprising that dark skin people turn orange when sat is cranked, but perhaps slightly surprising that light skin people do. Anyway, I suspect it’s computationally easier to turn everyone orange than brown. Plus, given that brown skin is already a category, orange could be useful terminology/category.
- adamhartenz 2mo agoAnd orange is just a yellow red.
- jagged-chisel 2mo agoOr a red yellow
- mryingster 2mo agoAnd brown is just orange... with context. https://www.youtube.com/watch?v=wh4aWZRtTwU https://www.youtube.com/watch?v=wh4aWZRtTwU
- a3w 2mo ago[flagged]
- stu2b50 2mo agoI think it’s worthwhile to note this is under a light with a color temperature similar to sunlight. When you’re actually painting, skin can really be any color. Blue is a perfectly valid (and fairly common) skin color - just look at someone in the moonlight. It takes two to tango, and the other dancer is the light source.
- JacobAsmuth 2mo agoMe after I spend a day at the beach: #BA3A17
- kaitlinseng 2mo agoSo glad to see Nyma getting recognition! I went to elementary and middle school with her, happy to see her succeeding.
- xdennis 2mo ago[flagged]
- BHSPitMonkey 2mo agoI just think it's highly amusing (in the absurd sense) that you consider a visual artist to be a political ideologue simply for applying color theory to render realistic characters in their art.
- mkesper 2mo agoRelated, pencils for more accurately drawing skin tones: https://hautfarben.org/en/products/skin-tones-pencils https://hautfarben.org/en/products/skin-tones-pencils
- peepsick 2mo agoI really like the idea of treating a color space as a task-specific optimization rather than something universal. It makes me wonder if we're underusing domain-specific color spaces in procedural generation in general.
- rebuilder 2mo agoI read the “limitations” section’s list of things that affect perceived skin tone and it didn’t mention lighting! This is pretty important as the available light determines the shades that can be perceived.
- 1-6 2mo agoI'm using an iPhone Safari plugin called Noir to force darkmode and your tool is making white the absence of color. In other words, I think white is just an alpha channel.
- juleiie 2mo ago[flagged]
- szvsw 2mo agoYou mention a bit about the latent social forces embedded within technological development and how that has related to skin tones and the technologies of color reproduction, so I figured I would share some references: https://canopycanopycanopy.com/contents/color-goes-electric https://canopycanopycanopy.com/contents/color-goes-electric The Kodak “Shirley cards” and test shots are of course famous in the media theory world for how they baked notions of race and “standard” or “normal” conditions into the medium of photography. Not dissimilar from the various discussions around facial recognition from approximately 10 yr ago.
- analog31 2mo agoIn the past we had to use multicultural crayons. https://econocrafts.com/products/crayola-colors-of-the-world-crayons-8-colors https://econocrafts.com/products/crayola-colors-of-the-world...
- kazinator 2mo agoFeature request: drop-down list of ethnicities, where the selection turns on specific guard rails in the parameter space (or retains full movement of the controls, but scales the values). Or is that too racist for 2026?
- nullsanity 2mo ago[dead]
- Roselol 2mo ago[dead]
- fenestella 2mo ago[flagged]
- zestyping 2mo agoCould you explain the first step, "Manually Labeling Colors ? What did you manually label? I didn't quite follow. From the way the article is written, it sounds like you presented yourself with a bunch of faces of completely random colours and then manually sorted them into two categories, "plausible skin colour" and "implausible skin colour". But I feel like I must be misunderstanding, because I don't see why you would do that. Why wouldn't you gather photographs of actual faces and sample colours directly from the photos?
- herf 2mo agoThis seems to do XYZ->RGB without any gamma correction. XYZ is linear, as is the transform to RGB, so we usually convert linear RGB to (gamma-encoded) sRGB at the end. The JS code seems to output linear RGB directly to the webpage (missing gamma). I guess the difficulty with "adding gamma" to it is this: if the training data were also gamma encoded, then it might need to be refit with linear values.
- jademcd 2mo ago[flagged]
- BLACKCRAB 2mo ago[dead]
- mediumdeviation 2mo ago[dead]
- alexpriyad 2mo agoThis is really cool
- wayknow 2mo ago[flagged]