Получить значение RGB изображения и, возможно, переместить файл изображения в C#

#c# #file-io #rgb

#c# #file-io #rgb

Вопрос:

Я рассматриваю возможность создания проекта на C #, который просматривает файл изображения, расширение которого еще не определено, и отмечает значение RGB, и, если оно слишком темное, перемещает его в другую папку, чтобы я мог просмотреть его позже

Итак, вот оно в виде блока

Загрузите несколько изображений из каталога > Проверьте значение RGB для каждого файла > если слишком темный > переместить в другую папку. если нет, игнорировать (оставить в исходной папке)

Я знаю основы, такие как получение файлов из каталога, но проверка значения RGB всего изображения, а затем перемещение его или игнорирование его, я в тупике.

У меня есть этот код:

     private void button1_Click(object sender, EventArgs e)
    {
        CompareImages(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "checked"), 127.0, new string[] {"*.jpg", "*.png"});
    }

    private void CompareImages(string sourceFolder, string disposedImgFolder, double threshold, string[] extensions)
    {
        if (Directory.Exists(sourceFolder))
        {
            DirectoryInfo dir = new DirectoryInfo(sourceFolder);
            List<FileInfo> pictures = new List<FileInfo>();

            foreach (string ext in extensions)
            {
                FileInfo[] fi = dir.GetFiles(ext);
                pictures.AddRange(fi);
            }


            Directory.CreateDirectory(disposedImgFolder);

            int j = 0;

            if (pictures.Count > 0)
            {
                for (int i = 0; i < pictures.Count; i  )
                {
                    Image img = null;
                    Bitmap bmp = null;

                    try
                    {

                        img = Image.FromFile(pictures[i].FullName);
                        bmp = new Bitmap(img);
                        img.Dispose();

                        double avg = GetAveragePixelValue(bmp);

                        bmp.Dispose();


                        if (avg < threshold)
                        {
                            string dest = Path.Combine(disposedImgFolder, pictures[i].Name);

                            if (File.Exists(dest) == false)
                            {
                                pictures[i].MoveTo(dest);
                                j  ;
                            }
                            else
                            {

                            }
                        }
                        else
                        {

                        }
                    }
                    catch
                    {
                        if (img != null)
                            img.Dispose();
                        if (bmp != null)
                            bmp.Dispose();
                    }
                }

                MessageBox.Show("Done, "   j.ToString()   " files moved.");
            }
        }
    }

    private unsafe double GetAveragePixelValue(Bitmap bmp)
    {
        BitmapData bmData = null;

        try
        {
            bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            int stride = bmData.Stride;
            IntPtr scan0 = bmData.Scan0;
            int w = bmData.Width;
            int h = bmData.Height;

            double sum = 0;
            long pixels = bmp.Width * bmp.Height;

            byte* p = (byte*)scan0.ToPointer();

            for (int y = 0; y < h; y  )
            {
                p = (byte*)scan0.ToPointer();
                p  = y * stride;

                for (int x = 0; x < w; x  )
                {

                    double i = ((double)p[0]   p[1]   p[2]) / 3.0;
                    sum  = i;


                    p  = 4;
                }

            }

            bmp.UnlockBits(bmData);

            double result = sum / (double)pixels;

            return resu<
        }
        catch
        {
            try
            {
                bmp.UnlockBits(bmData);
            }
            catch
            {

            }
        }

        return -1;
    }
  

Как мне определить threashold?

Комментарии:

1. Вы должны указать, что означает «слишком темный». Вы хотите сравнить среднее значение яркости всех пикселей с пороговым значением? Это игнорировало бы темные области на высококонтрастных изображениях…

2. под слишком темным я подразумеваю, когда изображение имеет значение RGB черного цвета или что-то подобное

3. Означает, что один черный пиксель сделает изображение слишком темным? Затем используйте решение Фрэнсиса, если производительность не слишком важна для вашего приложения.

4. нет, это означало бы, что все изображения будут удалены

5. Мне нравится концепция этого вопроса, но я думаю, вам нужно немного лучше уточнить свои критерии. Это также будет зависеть от типа изображения, поскольку не все они кодируются одинаково.

Ответ №1:

Если вы хотите прочитать каждый пиксель изображения, его необходимо преобразовать в растровое изображение. Затем вы можете использовать метод GetPixel. Но этот процесс очень медленный и требует много ресурсов процессора. Если вы это сделаете, вам действительно следует предварительно выполнить некоторый тест.

         using (var m = new MemoryStream())
        {
            using (var img = Image.FromFile(args[0]))
            {
                img.Save(m, ImageFormat.Bmp);
            }

            m.Position = 0;

            using (var bitmap = (Bitmap)Bitmap.FromStream(m))
            {
                for (var x = 0; x < bitmap.Width; x  )
                {
                    for (var y = 0; y < bitmap.Height; y  )
                    {
                        var color = bitmap.GetPixel(x, y);

                        // TODO: Do what ever you want
                    }
                }
            }
        }
  

Комментарии:

1. я изучил возможность блокировки bitlock, когда читал, что GetPixel не хватает процессора. но, похоже, я просто не могу разобраться во всем этом, вся программа меня раздражает

2. хорошо, я нашел лучший способ сделать это, как только он прочитает изображение и его в потоковом хранилище, оно переместит его в «папку сохранения», а если нет, то в папку «проверить»

Ответ №2:

Я думаю, вам нужно немного почитать о RGB. С каждым пикселем будет связано значение красного, зеленого и синего цветов, и я предполагаю, что вы ищете способ получить некоторое представление о том, насколько ярким является «средний» пиксель? Если это так, вам нужно выполнить цикл по всем пикселям. При этом вычислите яркость каждого пикселя. «Яркость» каждого пикселя может быть рассчитана несколькими способами, вы могли бы просто выполнить (R G B) / 3, или вы могли бы попытаться имитировать, что человеческий глаз не одинаково чувствителен к R, G и B.

Затем вам нужно будет решить, как использовать вашу «яркость» пикселя. Значение, Медиана, что-то еще? Это зависит от того, что вы хотите сделать..

Обновление: Прочитав больше ваших комментариев, я все еще не совсем уверен, что вы подразумеваете под «ярким» или «темным». Также кажется, что у вас немного запутана терминология, вы продолжаете говорить о значении RGB для всего изображения, но значения RGB в изображении относятся к значениям отдельных пикселей.

Я считаю, что эта страница могла бы помочь вам сделать то, что вы хотите: http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx

Также, немного дополнительного чтения для понимания RGB:

http://en.wikipedia.org/wiki/Luma_ (видео)

http://en.wikipedia.org/wiki/RGB_color_space

Комментарии:

1. да, это то, что я пытаюсь сделать, поскольку расположение источника света на изображении не всегда одинаково

2. я объясню еще раз, извините, мой мозг сегодня плохо функционирует, мы с моим отцом занимаемся астрофотографией, мы собирались оставить камеру включенной на всю ночь, делая снимки, а затем я хотел, чтобы эта программа следила за снимками, чтобы удалить те, на которых написано, что какое-то облако прошло перед телескопом, и убедиться, что она удаляет только те, на которых изображено облако, я думал, что это сработает с «яркостью» как единственным способом определить, хорошее ли изображение, иначе нам придется просматривать их и сделайте это вручную.

3.Если это так, я думаю, вы могли бы просто «сложить upp» все значения пикселей, используя цикл GetPixel, предложенный Фрэнсисом (возможно, разделить на количество пикселей), а затем методом проб и ошибок найти соответствующий порог. Возможно, вы могли бы сначала преобразовать все изображение в оттенки серого. switchonthecode.com/tutorials /… bobpowell.net/lockingbits.htm