我想在.NET中检索背景图像中的大部分颜色。有可能吗?
答案 0 :(得分:6)
您可以遍历图像中的所有像素,并使用getPixel方法确定RGB值。然后,您可以使用字典存储ARGB值以及计数。然后,您可以查看图像中最常出现的ARGB值。
var list = new Dictionary<int, int>();
Bitmap myImage = (Bitmap)Bitmap.FromFile("C:/test.jpeg");
for (int x = 0; x < myImage.Width; x++)
{
for (int y = 0; y < myImage.Height; y++)
{
int rgb = myImage.GetPixel(x, y).ToArgb();
if (!list.ContainsKey(rgb))
list.Add(rgb, 1);
else
list[rgb]++;
}
}
正如所指出的,这并没有对类似的颜色表示同情。如果你想要一个更“普通”的多数颜色,你可以在相似性上有一个阈值。例如而不是:
if (!list.ContainsKey(rgb))
list.Add(rgb, 1);
else
list[rgb]++;
你可以这样做:
var added = false;
for (int i = 0; i < 10; i++)
{
if (list.ContainsKey(rgb+i))
{
list[rgb+i]++;
added = true;
break;
}
if (list.ContainsKey(rgb-i))
{
list[rgb-i]++;
added = true;
break;
}
}
if(!added)
list.Add(rgb, 1);
你可以将10的门槛提高到你需要的任何值。
答案 1 :(得分:5)
你也可以在Stack Overflow上找到这个算法挑战:
Algorithm challenge: Generate color scheme from an image
还要考虑创建图像的直方图 - 并将最高值的颜色作为“多数颜色”:http://www.phpclasses.org/browse/file/15953.html
答案 2 :(得分:5)
这将返回图像的平均颜色。
static Color AverageColor(string fileName)
{
using (var bmp = new Bitmap(fileName))
{
int width = bmp.Width;
int height = bmp.Height;
int red = 0;
int green = 0;
int blue = 0;
int alpha = 0;
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
var pixel = bmp.GetPixel(x, y);
red += pixel.R;
green += pixel.G;
blue += pixel.B;
alpha += pixel.A;
}
Func<int, int> avg = c => c / (width * height);
red = avg(red);
green = avg(green);
blue = avg(blue);
alpha = avg(alpha);
var color = Color.FromArgb(alpha, red, green, blue);
return color;
}
}
答案 3 :(得分:4)
这将使用不安全的指针访问返回图像的平均颜色。注意:代码仅适用于24bppRgb,可以适用于其他像素格式。
unsafe static Color GetColor(string filename)
{
using (var image = (Bitmap)Bitmap.FromFile(filename))
{
if (image.PixelFormat != PixelFormat.Format24bppRgb) throw new NotSupportedException(String.Format("Unsupported pixel format: {0}", image.PixelFormat));
var pixelSize = 3;
var bounds = new Rectangle(0, 0, image.Width, image.Height);
var data = image.LockBits(bounds, ImageLockMode.ReadOnly, image.PixelFormat);
long r = 0;
long g = 0;
long b = 0;
for (int y = 0; y < data.Height; ++y)
{
byte* row = (byte*)data.Scan0 + (y * data.Stride);
for (int x = 0; x < data.Width; ++x)
{
var pos = x * pixelSize;
b += row[pos];
g += row[pos + 1];
r += row[pos + 2];
}
}
r = r / (data.Width * data.Height);
g = g / (data.Width * data.Height);
b = b / (data.Width * data.Height);
image.UnlockBits(data);
return Color.FromArgb((int)r, (int)g, (int)b);
}
}
答案 4 :(得分:3)
假设您使用RGB(相对于CMYK)来表征每个像素的颜色,您可以构建一个3d数组(R,G和B各一个)。然后决定你想要在每个维度中拥有的箱子数量 - 箱子越多,你在相似色调之间的差异就越大。
完成后,只需迭代图像的位图表示,即对落入3d数组中每个单元格的#像素求和。具有最高总和的单元格将是主要颜色。
您可能希望使您的算法可以轻松配置为每个维度中的#bins,以便您可以调整它在相似颜色之间的区别。
image = new Bitmap("C:\\test.bmp", true);
int x, y;
// Loop through the images pixels to product 3d histogram
for(x=0; x<image.Width; x++)
{
for(y=0; y<image.Height; y++)
{
Color pixelColor = image.GetPixel(x, y);
// Increment color count in appropriate cell of your 3d histogram here
...
}
}