2016-11-30 5 views
-1

Так кто помог мне сделать этот код, который сообщит мне самый используемый цвет в фото:показывают наиболее часто используемые цвета в изображении

class PictureAnalysis 
{ 
    public static List<Color> TenMostUsedColors { get; private set; } 
    public static List<int> TenMostUsedColorIncidences { get; private set; } 

    public static Color MostUsedColor { get; private set; } 
    public static int MostUsedColorIncidence { get; private set; } 

    private static int pixelColor; 

    private static Dictionary<int, int> dctColorIncidence; 

    public static void GetMostUsedColor(Bitmap theBitMap) 
    { 
     TenMostUsedColors = new List<Color>(); 
     TenMostUsedColorIncidences = new List<int>(); 

     MostUsedColor = Color.Empty; 
     MostUsedColorIncidence = 0; 

     // does using Dictionary<int,int> here 
     // really pay-off compared to using 
     // Dictionary<Color, int> ? 

     // would using a SortedDictionary be much slower, or ? 

     dctColorIncidence = new Dictionary<int, int>(); 

     // this is what you want to speed up with unmanaged code 
     for (int row = 0; row < theBitMap.Size.Width; row++) 
     { 
      for (int col = 0; col < theBitMap.Size.Height; col++) 
      { 
       pixelColor = theBitMap.GetPixel(row, col).ToArgb(); 

       if (dctColorIncidence.Keys.Contains(pixelColor)) 
       { 
        dctColorIncidence[pixelColor]++; 
       } 
       else 
       { 
        dctColorIncidence.Add(pixelColor, 1); 
       } 
      } 
     } 

     // note that there are those who argue that a 
     // .NET Generic Dictionary is never guaranteed 
     // to be sorted by methods like this 
     var dctSortedByValueHighToLow = dctColorIncidence.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value); 

     // this should be replaced with some elegant Linq ? 
     foreach (KeyValuePair<int, int> kvp in dctSortedByValueHighToLow.Take(10)) 
     { 
      TenMostUsedColors.Add(Color.FromArgb(kvp.Key)); 
      TenMostUsedColorIncidences.Add(kvp.Value); 
     } 

     MostUsedColor = Color.FromArgb(dctSortedByValueHighToLow.First().Key); 
     MostUsedColorIncidence = dctSortedByValueHighToLow.First().Value; 
    } 

} 

и я пытаюсь реализовать, как это, но я не действительно знаю, что я должен сделать, чтобы показать мне наиболее часто используемый цвет?

string filep = @"C:\Users\User\Desktop\Gallery\image" + NumberOfClick.ToString() + "cropped.png"; 

       Bitmap bMap = Bitmap.FromFile(filep) as Bitmap; 

       PictureAnalysis.GetMostUsedColor(bMap); 

Я хочу, чтобы определить наиболее часто используемые цвета из «реальной» фото, как это: I am cropping her "jacket" from the photo and I want a program that determines it as it is black

+1

Как вы хотите это показать? –

+3

как строка, как в ящике сообщений –

+3

'MessageBox.Show (« Самый используемый цвет »+ PictureAnalysis.MostUsedColor.ToString());' ... но серьезно. Как вы хотите отображать этот цвет? Показывая новый диалог, поместите это где-нибудь в пользовательский интерфейс (например, прямоугольник, заполненный этим цветом)? –

ответ

0

Есть два способа:

Первый изменить тип возвращаемого значения метода GetMostUsedColor от void до int

public static int GetMostUsedColor(Bitmap theBitMap) 
{ 
    TenMostUsedColors = new List<Color>(); 
    /*unchangeable code here*/ 
    return dctSortedByValueHighToLow.First().Value; 
} 

После этого этот метод вернет m ost б/у цвет.

Если запустить программу в консоли

Вы можете заменить последнюю строку PictureAnalysis.GetMostUsedColor(bMap) с Console.WriteLine(PictureAnalysis.GetMostUsedColor(bMap)), чтобы получить наиболее часто используемые цвета

Второй способ (если вы используете консоль) просто замените одну строку

public static void GetMostUsedColor(Bitmap theBitMap) 
{ 
    /*unchangeable code here*/ 
    Console.WriteLine(dctSortedByValueHighToLow.First().Value); 
} 
+2

ОК, я использовал первый, и он показывает мне гексагонный цвет, и я хочу превратить его в синее, красное и т. Д. –

+0

Итак, ищите 'C#, чтобы получить цвет из hex' в вашей любимой поисковой системе, прочитайте первый результат, прибыль. – Equalsk

0

Этот класс статический вызов метода является статическим, и результаты тоже ...

Так, чтобы использовать это:

string filep = @"C:\Users\User\Desktop\Gallery\image" + NumberOfClick.ToString() + "cropped.png"; 
Bitmap bMap = Bitmap.FromFile(filep) as Bitmap; 
PictureAnalysis.GetMostUsedColor(bMap); 

//Here you get the most used color 
var Color MostUsed = PictureAnalysis.MostUsedColor; 
//Here you get the ten most used colors 
var List<Color> TenMostUsed = PictureAnalysis.TenMostUsedColor; 

дисплей цвет в виде строки

В пространстве имен System.Drawing , Microsoft определила множество цветов в структуре Color. Таким образом, есть возможность создать цвет от known color name.

Однако вы должны понимать, что у всех цветов нет имени. Потому что их много. Поэтому не всегда можно поместить имя в цвет.

Вы можете попробовать написать метод, который будет принимать цвет и вернуть имя цвета ... Но помните, существует более 16 миллионов возможностей ...

Вид раствора

Что Я бы сделал, помещен цвет внутри ColorDialog. Затем вы устанавливаете свой цвет в свой наиболее используемый цвет.

Таким образом, пользователь, по крайней мере, иметь возможность просматривать цветовой

Другой вариант для его просмотра внутри PropertyGrid, потому что их ColorPicker тоже приятно.

0

Существует несколько способов сделать это.

Вот два решения:

1.

Возьмите список всех цветов, которые вы хотите сравнить против. Я бы взял список всех цветов в цвете. *

Затем прокрутите все пиксели и сравните каждый цвет с этим списком, чтобы взять ближайший, а затем сохраните этот цвет со значением 1 вхождения, затем возьмите затем и так далее, и, наконец, у вас есть список наиболее доминирующего цвета в списке. Тогда просто возьмите этот цвет и получите имя, так как это настоящий цвет. как:

string nameOfColorRed = Color.Red.Name; 

Для перебора всех пикселей в изображении можно использовать GetPixel(), но это немного медленно, так что вы должны использовать более быстрые методы, как вы можете найти здесь: Travel through pixels in BMP

2.

Другим простым решением, которое должно работать, является обмануть и изменить размер изображения до размера 1x1 пикселя, а затем вы получите самый доминирующий цвет на этом одиночном пикселе. Это проработало несколько простых тестов, которые я сделал, и это может быть достаточно хорошо? В противном случае используйте 1-е решение.

Затем просто сравните этот цвет с списком.

Вот пример для последнего решения:

 var listOfColors = GetAllColors(); 

     var filename = @"D:\Nature-View.jpg"; 
     var image = Image.FromFile(filename); 

     var smallImage = ResizeImage(image, 1, 1); 

     var index = ClosestColor2(listOfColors, smallImage.GetPixel(0, 0)); 

     var closestColorName = listOfColors[index].Name; 

методы обнаружения ClosestColor берется здесь: How to compare Color object and get closest Color in an Color[]?

Вот остальные методы:

private List<Color> GetAllColors() { 
     var list = new List<Color>(); 
     var colorType = typeof(Color); 
     var propInfos = colorType.GetProperties(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public); 
     foreach (var propInfo in propInfos) { 
      var color = Color.FromName(propInfo.Name); 
      list.Add(color); 
     } 
     return list; 
    } 

    // closed match in RGB space 
    private int ClosestColor2(List<Color> colors, Color target) { 
     var colorDiffs = colors.Select(n => ColorDiff(n, target)).Min(n => n); 
     return colors.FindIndex(n => ColorDiff(n, target) == colorDiffs); 
    } 

    // distance in RGB space 
    private static int ColorDiff(Color c1, Color c2) { 
     return (int) Math.Sqrt((c1.R - c2.R)*(c1.R - c2.R) 
           + (c1.G - c2.G)*(c1.G - c2.G) 
           + (c1.B - c2.B)*(c1.B - c2.B)); 
    } 

    public static Bitmap ResizeImage(Image image, int width, int height) { 
     var destRect = new Rectangle(0, 0, width, height); 
     var destImage = new Bitmap(width, height); 

     destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); 

     using (var graphics = Graphics.FromImage(destImage)) { 
      graphics.CompositingMode = CompositingMode.SourceCopy; 
      graphics.CompositingQuality = CompositingQuality.HighQuality; 
      graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 
      graphics.SmoothingMode = SmoothingMode.HighQuality; 
      graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; 

      using (var wrapMode = new ImageAttributes()) { 
       wrapMode.SetWrapMode(WrapMode.TileFlipXY); 
       graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode); 
      } 
     } 

     return destImage; 
    } 
Смежные вопросы