Click here to Skip to main content
Licence CPOL
First Posted 6 Jan 2007
Views 34,605
Downloads 438
Bookmarked 19 times

Find the Nearest Color with C# - Using the Euclidean Distance between Two Colors

By V. Thieme | 6 Jan 2007
A short method to find the nearest color
1 vote, 20.0%
1
1 vote, 20.0%
2

3
2 votes, 40.0%
4
1 vote, 20.0%
5
3.00/5 - 5 votes
μ 3.00, σa 2.88 [?]
Sample Image - NearestColorFinder.png

Description

This small method provides an algorithm to find the nearest (or "most similar") color in a given "colorspace" compared to a given single color. This is done by searching for the least Euclidean distance between the two colors. The Euclidean distance can be computed in an arbitrary n-dimensional space. In this implementation, the value for the alpha-component of the given color to "approximate" is NOT used. In the sample, I have used a little bit of code written by Julijan Sribar (http://www.codeproject.com/cs/miscctrl/MultiTabColorPicker.asp) to receive the "web colors" as the sample color space. The webcolor-space is actually a subspace of the RGB-space.

The Algorithm

It is quite simple to compute the Euclidean distance between two points. First, convert the three color-components to double-values:

double dbl_input_red = Convert.ToDouble(input_color.R);
double dbl_input_green = Convert.ToDouble(input_color.G);
double dbl_input_blue = Convert.ToDouble(input_color.B);

Further define a "similarity measure" (actually this is THE distance). This measure has to be initialized by an arbitrary value which must be greater than the greatest possible distance (basically this is the distance between white and black).

double distance = 500.0;

The algorithm to find the least distance is quite simple:

Color nearest_color = Color.Empty;
foreach (object o in WebColors)
{
	// compute the Euclidean distance between the two colors
	// note, that the alpha-component is not used in this example
	dbl_test_red = Math.Pow(Convert.ToDouble(((Color)o).R) - dbl_input_red, 2.0);
	dbl_test_green = Math.Pow(Convert.ToDouble
		(((Color)o).G) - dbl_input_green, 2.0);
	dbl_test_blue = Math.Pow(Convert.ToDouble
		(((Color)o).B) - dbl_input_blue, 2.0);
	// it is not necessary to compute the square root
	// it should be sufficient to use:
	// temp = dbl_test_blue + dbl_test_green + dbl_test_red;
	// if you plan to do so, the distance should be initialized by 250000.0
	temp = Math.Sqrt(dbl_test_blue + dbl_test_green + dbl_test_red);
	// explore the result and store the nearest color
	if(temp == 0.0)
	{
		// the lowest possible distance is - of course - zero
		// so I can break the loop (thanks to Willie Deutschmann)
		// here I could return the input_color itself
		// but in this example I am using a list with named colors
		// and I want to return the Name-property too
		nearest_color = (Color)o;
		break;
	}
	else if (temp < distance)
	{
		distance = temp;
		nearest_color = (Color)o;
	}
}

Use

To use the code, simply copy and paste the method GetNearestWebColor(Color input_color) into your project. Alternatively you can place a reference to SampleLibrary.dll.

History

  • 6th January, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

V. Thieme

Web Developer

Germany Germany

Member
Anesthesiologist from Germany
- first contact: 1985 - ATARI 800 XE (there was a great assembler: ATMAS II)
- special interests: my son, number theory, statistics, linear algebra, medicine (of course)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralBetter results with HSL Pinmemberandre_dart1:48 3 Mar '09  
GeneralHope it solves a problem Pinmembercoleydog23:00 6 May '08  
GeneralTwo small suggestions. PinmemberWilli Deutschmann5:13 8 Jan '07  
AnswerRe: Two small suggestions. Pinmember_vt_7:28 8 Jan '07  
GeneralRe: Two small suggestions. PinmemberTheo Lagendijk1:44 19 Apr '09  
GeneralRe: Two small suggestions. PinmemberWilli Deutschmann5:35 20 Apr '09  
GeneralRe: Two small suggestions. PinmemberTheo Lagendijk5:51 20 Apr '09  
GeneralRe: Two small suggestions. PinmemberWilli Deutschmann7:30 20 Apr '09  
Colors are a very complicated field and I may know a bit (as much as required for my profession), but I'm no expert.
Short answer to your question is no, I don't know the value before humans start noticing differences.
 
However, if you look at color and the way its stored, there are many ways to describe a color. Here, we have RGB, which is actually not very intuitive to the human, but it comes in handy for computers and monitors and such, because they happen to have light sources for each, red, green and blue.
A better way for humans might be the HSL color space (hue, saturation, luminance). We know this from advanced color pickers for example in photo shop. The hue is represented by a circle, starting at red, changing to yellow, green, cyan, blue, magenta and then red again. The radius of the circle then either represents the saturation (strong color, or rather grey'ish, or it represents the lightness.
Here, the human perception is escpecially sensitive to the lightness part (probably that's why gray images are still attractive and kind of "real".) The less important components are saturation and hue.
JPG for example takes advantage of that, splitting an image into those three parts and then compressing the hue and saturation part with information loss and the grey part more carefully. You can try it yourself, take an image, save it as JPG with medium quality. It should still look ok overall. But now extract the hue channel and look at that one separately. Looks terrible! Aerial images (e.g. seen in Google Maps/Earth) also take advantage of this by taking low resolution color images, blowing them up and then combining them with high resolution gray images - known as pan-sharpening.
 
And to make matters more complicated, it also depends on the image that you are looking at. If the image is busy/noisy to begin with you will be able to get away with a larger threshold than if you had smooth color ramps (cloudless blue sky) where even small changes are more prominent.
 
Back to your question, in RGB space, I would be surprised if there was a globally valid threshold value. If you go into HSL space, then it depends on the channel, H, S or L.
I don't have an example right now, but I am very confident that you will find a color which is "further away" than another in RGB space, but has a greater resemblance in human perception.
 
Seven days without coffee makes one weak.

GeneralNo one uses euclidian distance PinmemberGilad Kapelushnik0:28 7 Jan '07  
GeneralRe: No one uses euclidian distance Pinmember_vt_1:51 7 Jan '07  
GeneralRe: No one uses euclidian distance PinmemberJohnnyLocust10:55 20 Sep '07  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120210.1 | Last Updated 6 Jan 2007
Article Copyright 2007 by V. Thieme
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid