Topic: Clarification on cool_colors

Posted under General

Pup

Privileged

Hopefully a quick one.

The testing of my tagging bot for cool_colors seems to be going well, but I'd like some input these that are more on the edge:
post #1871441 post #1873199 post #1872289

The first is mostly cool_colors, and the horizon would be seen more as pink/purple than red, and apparently pink is considered more of a cool colour, though that's debatable. Is the strip of pink/purple enough to say it shouldn't be tagged?

The second, being purple, probably should be tagged, yet for some reason I feel it shouldn't be.

The third, most of the shading/colours in the image are blue, except for the nipples and penis tip, which are pink, and like the second one, I'm undecided on if it should actually be tagged.

A quick edit to say a bit about the code, for the people who are interested:

At the moment, it counts the colour of all the pixels, then gets a percentage with:
(cold colour pixel count - warm colour pixel count) / (total pixels - white/black/grey pixels)

Then anything at 0.98 or above would get tagged. It's pretty simple, but seems to work well.

Updated

Coming from someone with just a bit of a traditional background in color theory, but much more from an image processing standpoint I think I can offer some help

Considering we're mostly just looking at a color's hue here (even though value and saturation also play a big role), it's clear that much of the confusion is arriving from the bits of the color wheel that represent transitions between cool and warm colors (your purples and greens, which are sorta halfway inbetween your oranges and blues)

If I were to try to come up a better algorithm for classifying an image as a whole as warm/cool what I'd personally do would probably involve getting the "warmness" of each pixel and using that instead of a simple count of warm/cool pixels to avoid running into problems with those "transitional" hues

I'd probably assign two separate angles of the hue wheel as being my "most cool" and "most warm" angles (ideally separated by 180º) and assign a "warmness" value to each pixel based on it's hue angle (with, let's say, 1 being the same as the warmest angle, 0 being exactly between both previous angles and -1 being the same as the coldest angle). What you can then do is add all values together and see if it's absolute value passes a certain threshold calculated using the total number of pixels in the image

Of course that's still only using hue, but it should be good enough for what you're trying to do. The main thing is that classifying an entire pic as warm/cold runs into the same problems as classifying the weather as warm/cold: aside from very specific edge cases that are easy to point as examples, the entire classification is relative and ends up not being too useful for most cases

Updated by anonymous

Pup

Privileged

mabit said:
Coming from someone with just a bit of a traditional background in color theory, but much more from an image processing standpoint I think I can offer some help

Well, I've got no experience at all in colour theory. So the advice is welcome :)

mabit said:
If I were to try to come up a better algorithm for classifying an image as a whole as warm/cool what I'd personally do would probably involve getting the "warmness" of each pixel and using that instead of a simple count of warm/cool pixels to avoid running into problems with those "transitional" hues
[..]

Looking at a colour wheel, what degrees would you say for warmest and coldest?

On most scales, red is warmest and blue is coldest, and I'd agree with that, but that'd make it really awkward to code, and put pink/purple in an odd grey area. The E6 wiki mentioned blue/purple as cold, and post #1582238 has lots of pink in it, and is tagged with cool_colors.

How would you feel about, instead of a circle, split it at hue 340, and have your algorithm along a line. The problem with that is it'd make 339 the coldest, when it's not, I feel the coldest should really be blue.

Then separate from the hues, and preferably with the HSL model as that's what I'm using, how would you handle black, grey and white? And/or saturation and lightness?

For example, post #1686707 is definitely correctly tagged with cool_colors, yet the moon is considered yellow. Would you just ignore the lighter shades? With your algorithm I suppose you could add weight to the intensity of the colour as well, which would be even better.

Currently, it ignores black/grey/white, as they're more neutral, which seems to work ok, but I'd like to hear what you think about that.

As a side note, I ended up adding an extra rule to say if the hue was pink, but the lightness was low, to count it as purple. As far as I'm aware, the only colours that need an extra rule like that, are purple and brown.

mabit said:
[..] The main thing is that classifying an entire pic as warm/cold runs into the same problems as classifying the weather as warm/cold: aside from very specific edge cases that are easy to point as examples, the entire classification is relative and ends up not being too useful for most cases

You kinda hit the nail on the head with that one. And it's one reason I'm so hesitant to put this into practice, and why I wanted to ask people if those edge cases were would still be considered as "cold."

Thanks again for your input, I really appreciate it! And I really like the sound of that algorithm, it's just working out what to have as warm and cold.

Also, I just noticed it's nearly 7am here and I've been coding/testing this tagbot all night.. I really should set a "stop coding" alarm..

Updated by anonymous

Those examples look good to me.

I'm interested in your code. What tolerance are you using for white, grey and black colors? How much can they differ from a perfect black or perfect white and still be considered black or white?

Updated by anonymous

Pup

Privileged

Jamie_Pi said:
Those examples look good to me.

I'm interested in your code. What tolerance are you using for white, grey and black colors? How much can they differ from a perfect black or perfect white and still be considered black or white?

Ah, good to hear. Though I'm kinda questioning whether it's best to stick with the current algorithm or change it. Though I think I'll just try both and test them, as that'll be easier.

Just giving a quick answer from my phone, if you want I can give a more detailed answer later. I think it's, with HSL, a lightness of <=5 and >=95. I can't remember grey off the top of my head, but it was probably the opposite of those for lightness and about <=15 for saturation.

Though for the cool/warm colours, black/white/grey aren't counted. So it's only on the colour content of the image. If 98% of the pixels are considered to be a cold color, then it's cold. I'm still wondering where pink should be, as it's a bit of a middle ground. I might try counting it as both and see how that goes, along with a lot more testing of course.

Updated by anonymous

Hmmm, very cool. I like how it looks now, but I'm be interested in seeing how it would change if you considered pink a cool color.
I feel like if there's more red than blue, it should be considered warm, and if there's more blue than red, it should be considered cool. That's just me though.

Updated by anonymous

Pupslut said:
Looking at a colour wheel, what degrees would you say for warmest and coldest?

As far as I know there's no solid definition, so really any orange/blue pair would do. My personal pick would be 30º/210°

Pupslut said:
On most scales, red is warmest and blue is coldest, and I'd agree with that, but that'd make it really awkward to code, and put pink/purple in an odd grey area. The E6 wiki mentioned blue/purple as cold, and post #1582238 has lots of pink in it, and is tagged with cool_colors.

Eeeeh, that's one of the examples where a classification like this runs into problems. Specially since it's human-tagged, we run into a lot of noise caused by how subjective it can be when there's no concrete rules. (Btw most of the peeps consider orange to be the warmest color instead of red, but that's really not that big of a difference)

Pupslut said:
How would you feel about, instead of a circle, split it at hue 340, and have your algorithm along a line. The problem with that is it'd make 339 the coldest, when it's not, I feel the coldest should really be blue.

Some simple equations take care of it quite easily. Given Hw and Hc as our chosen hues for the warmest and coldest points of reference respectively (considering that Hw < 180 and Hc = Hw + 180) and Hp as the hue for the pixel we're analyzing:

  • If Hw <= Hp <= Hc: Map Hp from 1 to -1 using Hw and Hc as the edges
  • If Hp > Hc: Map Hp-180 to -1 to 1 using Hw and Hc as the edges
  • If Hp < Hw: Do as above, but assigning Hp = 360 - Hp beforehand

(Note that everything above is a huge bodge that I wrote in a couple of minutes from the top of my head, there are certainly more elegant ways of doing it)

Pupslut said:
Then separate from the hues, and preferably with the HSL model as that's what I'm using, how would you handle black, grey and white? And/or saturation and lightness?

Grays are literally a bit of a gray area when it comes to color theory. I've personally been taught that in traditional mediums painters generally consider black to be the warmest possible color and white as the coldest possible color, so that might give us a few hints on how to deal with them.

You should also consider that the less saturated a color is, the more it slowly changes to the other side of the wheel (as it indeed does if you plot the wheel as a circle with grays in the center). So cool colors warm up as they get less saturated, and warm colors cool up when they do the same.

From the two previous paragraphs, if I were to code it I'd probably make it so the "warmness" value is calculated like:

def calculateWarmness(H, S, L):
	Hw = 30
	Hc = Hw + 180
	warmnessByHue = calculateWarmnessByHue(H, Hw, Hc)
	saturationEffect = S / 100

	if L <= 50: # closer to black means it gets warmer
		blackEffect = (50 - Min(50,L)) / 50
		warmness = (1 * blackEffect) + (warmnessByHue * saturationEffect * (1-blackEffect))
	else: # closer to white means it gets colder
		whiteEffect = (50 - Max(50,L)) / 50
		warmness = (-1 * whiteEffect ) + (warmnessByHue * saturationEffect * (1-whiteEffect ))

	return warmness

Again, complete bodge and probably very wrong in many ways. But I think it might be a nice start. I tried to accommodate for the idea that the L values of 0 and 100 make the pixel as warm or cold as possible, while a L value of 50 would make it depend solely on the H and S information (where S would then multiply the H value from 0 to 1, representing that gray is completely neutral while the more vibrant colors are defined only by their hue)

Pupslut said:
You kinda hit the nail on the head with that one. And it's one reason I'm so hesitant to put this into practice, and why I wanted to ask people if those edge cases were would still be considered as "cold."

Yeah I hear ya, not having concrete definitions makes it kinda hard to work with because it's so subjective. Fun image processing exercise though

Pupslut said:
Thanks again for your input, I really appreciate it! And I really like the sound of that algorithm, it's just working out what to have as warm and cold.

No prob. If you need more help with it just give me a poke, I usually give the forums here a peek every once in a while.
If it's anything more immediate feel free to contact me via discord, link to my server on my twitter profile

Updated by anonymous

Pup

Privileged

mabit said:
As far as I know there's no solid definition, so really any orange/blue pair would do. My personal pick would be 30º/210°
[..]
(Btw most of the peeps consider orange to be the warmest color instead of red, but that's really not that big of a difference)

Looking again, I could probably say 0 and 180, as that'd make red warmest, and cyan, which is already a pretty light colour, the coldest. Though I think I'll stick with your suggestion, I didn't realise most thought of orange as being warmer than red.

mabit said:
Eeeeh, that's one of the examples where a classification like this runs into problems. Specially since it's human-tagged, we run into a lot of noise caused by how subjective it can be when there's no concrete rules.

Yeah, the subjective nature can be awkward. The plan is to tag images I'm sure only use warm/cold colours, and never untag them, at least it'll help with getting more images tagged with it that should be.

mabit said:
Some simple equations take care of it quite easily.
[..]
(Note that everything above is a huge bodge that I wrote in a couple of minutes from the top of my head, there are certainly more elegant ways of doing it)

Thanks for that. And I do love a good bodge, especially if the bodge works.

mabit said:
You should also consider that the less saturated a color is, the more it slowly changes to the other side of the wheel (as it indeed does if you plot the wheel as a circle with grays in the center). So cool colors warm up as they get less saturated, and warm colors cool up when they do the same.

I did think about that earlier, when first creating the algorithm then thought, "well it's still a cold colour so it doesn't matter too much," but that's definitely a better way to do it.

mabit said:
From the two previous paragraphs, if I were to code it I'd probably make it so the "warmness" value is calculated like:

[..]

Massive thanks for this. It really helps, and I'll definitely be trying it.

*a bit later*

In testing, I feel the values need tweaking a bit, and there's a few concerns.
So very light cyan (hsl 180, 100, 98) should probably be cooler than if the lightness was 51. Then also, with this algorithm, if the lightness is 20, it then counts as a warm colour, when it's certainly still a blue hue.

The other concern is that an entirely white background, with a small orange/red character in the middle, should probably be tagged with warm_colors, however if we count white as the coolest colour, it'd get the cool_colors tag. So it might be best to discount bright whites and dark blacks, and focus more on the shades.

I really want to use an algorithm like this, as I think it would be more accurate than the simple count if done/tweaked right. At the same time, it's almost annoying that the simple/lazy method I used earlier seems to work better.

Here's the code I used to get the hue's temperature, from -1 to +1, in case you want it:

float hueMaxWarm  = 30;
float hueMaxCold = 210;
float hue = 200;
float hueTemp = 0;

if (hue >= hueMaxWarm && hue <= hueMaxCold)
{ hueTemp = -1 * ((hue - hueMaxWarm - 90) / 90f); }

if (hue < hueMaxWarm)
{ hueTemp = (hue + 90 - hueMaxWarm ) / 90f; }

if (hue > hueMaxCold)
{ hueTemp = (hue - 270 - hueMaxWarm) / 90f; }

Again, complete bodge and probably very wrong in many ways. But I think it might be a nice start.

It's definitely a great start. And it really helps to have something to work with.

I tried to accommodate for the idea that the L values of 0 and 100 make the pixel as warm or cold as possible, while a L value of 50 would make it depend solely on the H and S information (where S would then multiply the H value from 0 to 1, representing that gray is completely neutral while the more vibrant colors are defined only by their hue)

I like that, but it definitely needs some tweaking, maybe so that the deeper blacks and lighter whites have more weight than the shades in between, though that'd make the white background thing worse.

Then, for example, purple is colder than pink but then pink with a low lightness is purple, and with the algorithm as it is, the lower lightness combined with the hue being pink, would make it a much warmer colour than it should be.

Thinking about it, it's probably why the simple algorithm, at least for now, is more accurate, it's much easier to code in "dark pink is actually purple" when you're only using a simple hue count. Whereas I feel this more sliding scale could be much more accurate when it's been tweaked, but will also be a bit more awkward to code. I'd say to discount lightness entirely if it wasn't for the dark pink/purple thing.

Have you got any ideas on how best to change it?

Fun image processing exercise though

It definitely is, hence why I've been up till stupid o'clock coding the past few days :)

Plus I'm a lot more passionate than I thought I'd be about getting a really good tagbot working.

No prob. If you need more help with it just give me a poke, I usually give the forums here a peek every once in a while.
If it's anything more immediate feel free to contact me via discord, link to my server on my twitter profile

Thanks for that, I'll keep it in mind.

I'm gunna try and get an early night, then continue testing/programming this in the morning. Any further ideas would definitely be welcome! And thanks again for that previous code!

Updated by anonymous

  • 1