- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试找到图像的主色。我正在使用 ColorMine做颜色比较。基本上我有一个颜色模板,我将每个像素与之进行比较。
从模板中选择距离最小的颜色作为该像素的代表。
public class ColorItem
{
public enum Colors
{
White ,
Black ,
Gray ,
Red ,
Orange ,
Yellow ,
Green ,
Cyan ,
Blue ,
Magenta,
Pink ,
Brown ,
None,
}
public ColorItem(Color color, Colors colorType)
{
this.color = color;
this.colorType = colorType;
}
public Colors colorType;
public Color color;
}
//The color template that I am comparing against, which I cannot help but to
//Think that this is the issue
public class ColorTemplate
{
public static Color white = Color.FromArgb(255,255,255);
public static Color black = Color.FromArgb(0, 0, 0);
public static Color gray = Color.FromArgb(150, 150, 150);
public static Color red = Color.FromArgb(255, 0, 0);
public static Color orange = Color.FromArgb(255, 150, 0);
public static Color yellow = Color.FromArgb(255, 255, 0);
public static Color green = Color.FromArgb(0, 255, 0);
public static Color cyan = Color.FromArgb(0, 255, 255);
public static Color blue = Color.FromArgb(0, 0, 255);
public static Color magenta = Color.FromArgb(255, 0, 255);
public static Color pink = Color.FromArgb(255, 150, 255);
public static Color brown = Color.FromArgb(150, 90, 25);
}
private static List<ColorItem> _template = new List<ColorItem>
{
new ColorItem(ColorTemplate.black, ColorItem.Colors.Black),
new ColorItem(ColorTemplate.blue, ColorItem.Colors.Blue),
new ColorItem(ColorTemplate.brown, ColorItem.Colors.Brown),
new ColorItem(ColorTemplate.cyan, ColorItem.Colors.Cyan),
new ColorItem(ColorTemplate.gray, ColorItem.Colors.Gray),
new ColorItem(ColorTemplate.green, ColorItem.Colors.Green),
new ColorItem(ColorTemplate.magenta, ColorItem.Colors.Magenta),
new ColorItem(ColorTemplate.orange, ColorItem.Colors.Orange),
new ColorItem(ColorTemplate.pink, ColorItem.Colors.Pink),
new ColorItem(ColorTemplate.red, ColorItem.Colors.Red),
new ColorItem(ColorTemplate.white, ColorItem.Colors.White),
new ColorItem(ColorTemplate.yellow, ColorItem.Colors.Yellow)
};
public bool GetDominantColor(string filePath, out List<ColorPercentages> domColor)
{
domColor = new List<ColorPercentages>();
Bitmap bmp = null;
try
{
bmp = new Bitmap(filePath);
}
catch (Exception)
{
}
if (bmp == null)
return false;
//Used for tally
var total = 0;
var countWhite = 0;
var countBlack = 0;
var countGray = 0;
var countRed = 0;
var countOrange = 0;
var countYellow = 0;
var countGreen = 0;
var countCyan = 0;
var countBlue = 0;
var countMagenta = 0;
var countPink = 0;
var countBrown = 0;
for (var x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
total++;
var clr = bmp.GetPixel(x, y);
var near = FindNearestColor(clr);
switch (near)
{
case ColorItem.Colors.Black:
countBlack++;
break;
case ColorItem.Colors.Blue:
countBlue++;
break;
case ColorItem.Colors.Brown:
countBrown++;
break;
case ColorItem.Colors.Cyan:
countCyan++;
break;
case ColorItem.Colors.Gray:
countGray++;
break;
case ColorItem.Colors.Green:
countGreen++;
break;
case ColorItem.Colors.Magenta:
countMagenta++;
break;
case ColorItem.Colors.Orange:
countOrange++;
break;
case ColorItem.Colors.Pink:
countPink++;
break;
case ColorItem.Colors.Red:
countRed++;
break;
case ColorItem.Colors.White:
countWhite++;
break;
case ColorItem.Colors.Yellow:
countYellow++;
break;
}
}
}
domColor.Add(new ColorPercentages((int)(((double)countWhite / (double)total) * 100), ColorItem.Colors.White));
domColor.Add(new ColorPercentages((int)(((double)countBlack / (double)total) * 100), ColorItem.Colors.Black));
domColor.Add(new ColorPercentages((int)(((double)countGray / (double)total) * 100), ColorItem.Colors.Gray));
domColor.Add(new ColorPercentages((int)(((double)countRed / (double)total) * 100), ColorItem.Colors.Red));
domColor.Add(new ColorPercentages((int)(((double)countOrange / (double)total) * 100), ColorItem.Colors.Orange));
domColor.Add(new ColorPercentages((int)(((double)countYellow / (double)total) * 100), ColorItem.Colors.Yellow));
domColor.Add(new ColorPercentages((int)(((double)countGreen / (double)total) * 100), ColorItem.Colors.Green));
domColor.Add(new ColorPercentages((int)(((double)countCyan / (double)total) * 100), ColorItem.Colors.Cyan));
domColor.Add(new ColorPercentages((int)(((double)countBlue / (double)total) * 100), ColorItem.Colors.Blue));
domColor.Add(new ColorPercentages((int)(((double)countMagenta / (double)total) * 100), ColorItem.Colors.Magenta));
domColor.Add(new ColorPercentages((int)(((double)countPink / (double)total) * 100), ColorItem.Colors.Pink));
domColor.Add(new ColorPercentages((int)(((double)countBrown / (double)total) * 100), ColorItem.Colors.Brown));
domColor.Sort(new SortColorPercentagesDescending());
return true;
}
private ColorItem.Colors FindNearestColor(Color input)
{
ColorItem.Colors nearest_color = ColorItem.Colors.None;
var distance = 255.0;
Rgb inColoRgb = new Rgb {R = input.R, G = input.G, B = input.B};
Lab inColorLab = inColoRgb.To<Lab>();
foreach (var colorItem in _template)
{
Rgb templateColorRgb = new Rgb {R = colorItem.color.R, G = colorItem.color.G, B = colorItem.color.B};
Lab templateColorLab = templateColorRgb.To<Lab>();
var target = new CieDe2000Comparison();
var tempRes = inColoRgb.Compare(templateColorRgb, target);
if (tempRes == 0.0)
{
nearest_color = colorItem.colorType;
break;
}
else if (tempRes < distance)
{
distance = tempRes;
nearest_color = colorItem.colorType;
}
}
return nearest_color;
}
public class SortColorPercentagesDescending : Comparer<ColorPercentages>
{
public override int Compare(ColorPercentages x, ColorPercentages y)
{
if (x == null || y == null)
return -1;
if (x.Percentage > y.Percentage)
return -1;
if (x.Percentage < y.Percentage)
return 1;
return 0;
}
}
public class ColorPercentages
{
public int Percentage;
public ColorItem.Colors Color;
public ColorPercentages(int percentage, ColorItem.Colors color)
{
Percentage = percentage;
Color = color;
}
}
这里的两个主要函数是GetDominantColor
和FindNearestColor
。第一个加载位图中的图像文件并遍历每个像素,找到最接近的颜色并增加该颜色的计数。一旦遍历所有像素,它就会计算每种颜色的出现百分比,并将它们返回到按颜色百分比排序的列表中的调用方。
FindNearestColor
函数使用 ColorMine 的 CieDe2000Comparison 实现将每个像素与硬编码模板进行比较,并返回最接近的模板颜色作为像素的颜色。
现在,我不禁想到问题出在我使用的颜色模板上。我不确定如何调整这些以给出准确的结果。我尝试将 RGB 值减半,结果有所好转,但还没有达到准确的程度。例如,黄色图像将主色返回为白色。深绿色图像将主色返回为黑色等。
我怎样才能让它工作
编辑:我不想找到图像的平均颜色。我正在寻找一种方法,将每个像素的颜色分类/映射到特定的预定义颜色,然后找到重复次数最多的颜色。
最佳答案
我不得不做类似的事情。作为输入颜色,我使用了 System.Drawing.KnownColor 中的所有值,但您可以很容易地更改该部分。
下面的代码获取图像中最常用的颜色,然后尝试将其与已知颜色匹配。
class Program
{
static void Main(string[] args)
{
var image = (Bitmap)Image.FromFile(@"C:\temp\colorimage3.bmp");
var mostUsedColor = GetMostUsedColor(image);
var color = GetNearestColor(mostUsedColor);
Console.WriteLine(color.Name);
Console.ReadKey();
}
private static Color GetNearestColor(Color inputColor)
{
var inputRed = Convert.ToDouble(inputColor.R);
var inputGreen = Convert.ToDouble(inputColor.G);
var inputBlue = Convert.ToDouble(inputColor.B);
var colors = new List<Color>();
foreach (var knownColor in Enum.GetValues(typeof(KnownColor)))
{
var color = Color.FromKnownColor((KnownColor) knownColor);
if (!color.IsSystemColor)
colors.Add(color);
}
var nearestColor = Color.Empty;
var distance = 500.0;
foreach (var color in colors)
{
// Compute Euclidean distance between the two colors
var testRed = Math.Pow(Convert.ToDouble(color.R) - inputRed, 2.0);
var testGreen = Math.Pow(Convert.ToDouble(color.G) - inputGreen, 2.0);
var testBlue = Math.Pow(Convert.ToDouble(color.B) - inputBlue, 2.0);
var tempDistance = Math.Sqrt(testBlue + testGreen + testRed);
if (tempDistance == 0.0)
return color;
if (tempDistance < distance)
{
distance = tempDistance;
nearestColor = color;
}
}
return nearestColor;
}
public static Color GetMostUsedColor(Bitmap bitMap)
{
var colorIncidence = new Dictionary<int, int>();
for (var x = 0; x < bitMap.Size.Width; x++)
for (var y = 0; y < bitMap.Size.Height; y++)
{
var pixelColor = bitMap.GetPixel(x, y).ToArgb();
if (colorIncidence.Keys.Contains(pixelColor))
colorIncidence[pixelColor]++;
else
colorIncidence.Add(pixelColor, 1);
}
return Color.FromArgb(colorIncidence.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value).First().Key);
}
}
关于c# - 查找图像中的主色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30103425/
我是 node.js 新手。 我读过有关 Node.js 图像库的帖子,似乎 GM似乎是最 高级。我正在尝试使用 nodejs 找出图像中最主要的颜色。 然后我找到了这个脚本color-thief ,
我是一名优秀的程序员,十分优秀!