Получение координат точки с изображения

Я создаю программу, которая может распечатать координаты x и y из определенного пикселя. Есть такая функция, как GetPixel, но она будет получать коды RGB по заданной координате. Я хочу как раз наоборот, поэтому у меня уже есть коды RGB, и теперь я устанавливаю порог с помощью своего изображения, чтобы узнать, содержит ли он цветной пиксель, который я хотел или нет.

Это мой код:

Итак, сначала я загружу изображение:

    public BitmapImage bitmap;

    public void hochladen_Click(object sender, EventArgs e)
    {
        // Create OpenFileDialog 
        Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

        // Set filter for file extension and default file extension 
        dlg.DefaultExt = ".bmp";
        dlg.Filter = "BMP Files (*.bmp)|*.bmp";

        // Get the selected file name and display in a TextBox 
        if (dlg.ShowDialog() == true)
       { 
            // Open document 
            string filename = dlg.FileName;
            bitmap = new BitmapImage();
            bitmap.BeginInit();
            bitmap.UriSource = new Uri(filename);
            bitmap.EndInit();
            image.Source = bitmap;
        }
    }

Затем, когда я нажимаю кнопку в своем приложении, оно должно установить порог из моего изображения, и я собираюсь обнаружить красную точку (R = 255, G = B = 0)

    public Color c;

    private void detektieren_Click(object sender, RoutedEventArgs e)
    {
        double x = bitmap.Width;
        double y = bitmap.Height;
        bl.Content = x + "x" + y;

Итак, с этого момента найти координату не составит труда:

        for (int i = 0; i < x; i++)
        {
            for (int j = 0; i < j; j++)
            {
                if (c.R == 255 && c.G == 0 && c.B == 0)
                {
                    //
                }
            }
        }
    }

У кого-нибудь есть идея? Заранее спасибо.


person user2754279    schedule 04.12.2013    source источник
comment
каков результат вашего кода? Вы хотите, чтобы мы его рассмотрели?   -  person King King    schedule 04.12.2013
comment
Нет, но как это сделать. Я имею в виду, как мне получить координату пикселя, если у меня уже есть код RGB. Мне нужно просто вставить несколько строк в // - ›, но я понятия не имею, какой вид функции я могу использовать.   -  person user2754279    schedule 04.12.2013
comment
Разве координаты не совпадают с координатами i и j, когда пиксель найден?   -  person Håkan Fahlstedt    schedule 04.12.2013
comment
Привет, да, так и должно быть. Я попытался добавить эту строку: xy_coord.Content = i +; + j; Но он ничего не отображал. Что я сделал не так?   -  person user2754279    schedule 04.12.2013
comment
Взгляните на этот вопрос, я думаю, это то, что вы ищете: stackoverflow.com/questions/1176910/   -  person Håkan Fahlstedt    schedule 04.12.2013
comment
Нет, это как раз наоборот. Как я уже сказал: У меня уже есть значение RGB, и я хочу, какой пиксель в моем изображении имеет это значение. Ссылка, которую вы дали, - это как найти значение RGB известного пикселя.   -  person user2754279    schedule 04.12.2013


Ответы (2)


Поиск пикселей, соответствующих значению RGB, конечно, может вернуть много пикселей, попробуйте следующий код, чтобы получить все пиксели, представленные структурой Point:

public Point[] GetPixelsFromRGB(byte[] rgbData, int stride, Color colorToFind){
  int k = stride/4;
  return rgbData.Select((x,i)=>new{x,i})
                .GroupBy(a=>a.i/4,(key,a)=>a.ToArray())
                .Where(g=>g[0].x == colorToFind.Red &&
                          g[1].x == colorToFind.Green &&
                          g[2].x == colorToFind.Blue && g[3].x == 255)
                .Select(g=> new Point(g[0].i%k, g[0].i / k)).ToArray();
}
//Use this method to get the rgbData
int stride = bitmap.PixelWidth * 4;
byte[] rgbData = new byte[stride * bitmap.PixelHeight];
bitmap.CopyPixels(rgbData, stride, 0);
//then call the method above:
var pixels = GetPixelsFromRGB(rgbData, stride, Colors.Red);

Обратите внимание, что приведенный выше код не был протестирован, я просто набрал его прямо в редакторе ответов.

person King King    schedule 04.12.2013

После небольшой модификации все работает. Итак, это мой код:

    public void detektieren_Click(object sender, RoutedEventArgs e)
    {
        for (i = 0; i < bitmap.Height; i++)
        {
            for (j = 0; j < bitmap.Width; j++)
            {
                stride = bitmap.PixelWidth * (bitmap.Format.BitsPerPixel / 8);
                data = new byte[stride * bitmap.PixelHeight];
                bitmap.CopyPixels(data, stride, 0);
                index = i * stride + 4 * j;

                byte A = data[index + 3];
                byte R = data[index + 2];
                byte G = data[index + 1];
                byte B = data[index];

                // Create a writer and open the file:
                StreamWriter Messdaten;
                if (!File.Exists("C:/Users/.../Messdaten.csv"))
                {
                    Messdaten = new StreamWriter("C:/Users/.../Messdaten.csv");
                }
                else
                {
                    Messdaten = File.AppendText("C:/Users/.../Messdaten.csv");
                }

                // Write to the file:
                Messdaten.WriteLine(index + ";" + A + ";" + R + ";" + G + ";" + B);

                // Close the stream:
                Messdaten.Close();

                if (Convert.ToInt32(R) == 0 && Convert.ToInt32(G) == 0 && Convert.ToInt32(B) == 255)
                {
                    // Create a writer and open the file:
                    StreamWriter Messdaten2;
                    if (!File.Exists("C:/Users/.../Messdaten2.csv"))
                    {
                       Messdaten2 = new StreamWriter("C:/Users/.../Messdaten2.csv");
                    }
                    else
                    {
                        Messdaten2 = File.AppendText("C:/Users/.../Messdaten2.csv");
                    }

                    // Write to the file:
                    Messdaten2.WriteLine(index + ";" + i + ";" + j);

                    // Close the stream:
                    Messdaten2.Close();
                }
            }
        }
    }

В первом файле Excel (Messdaten.csv) будут показаны все значения RGB для каждого отдельного пикселя. Во втором (Messdaten2.csv) он покажет все пиксели, которые, например, имеют значение A = 0, R = 0, G = 0, B = 255 (= синий).

Теперь, как мне создать сумму и среднее значение Pixel i и Pixel j (они набор значений)? Пытался это сделать:

                if (Convert.ToInt32(R) == 0 && Convert.ToInt32(G) == 0 && Convert.ToInt32(B) == 255)
                {
                    int x_sum = 0; int y_sum = 0;
                    int x_count = 0; int y_count = 0;
                    int x_mw = 0; int y_mw = 0;

                    x_sum = x_sum + i;
                    x_count++;
                    y_sum = y_sum + j;
                    y_count++;

                    x_mw = x_sum / x_count;
                    y_mw = y_sum / y_count;
                }

Но почему это не сработало? X_sum и y_sum показывают только последнее значение Pixel i и j, а x_count и y_count (как предполагается) показывают только значение 1. Что я не так?

person user2754279    schedule 10.12.2013