获取图像的RGB值,并可能在c#中移动图像文件

本文关键字:图像 移动 文件 RGB 获取 | 更新日期: 2023-09-27 18:14:41

我正在考虑在c#中做一个项目,该项目查看图像文件,不确定扩展名,并注意RGB值,如果它太暗,将其移动到另一个文件夹,供我稍后查看

这里是block形式的

从目录加载多个图像>检查每个文件的RGB值>如果太暗>移动到不同的文件夹。如果没有忽略(留在原始文件夹)

我知道基本的,比如从dir获取文件,但检查整个图片的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 result;
        }
        catch
        {
            try
            {
                bmp.UnlockBits(bmData);
            }
            catch
            {
            }
        }
        return -1;
    }

如何定义阈值?

获取图像的RGB值,并可能在c#中移动图像文件

如果要读取图像的每个像素,则必须将其转换为位图。然后你可以使用GetPixel方法。但是,这个过程非常缓慢,并且需要大量的CPU。如果您这样做,您真的应该在此之前运行一些测试。

        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
                    }
                }
            }
        }

我认为你需要读一点关于RGB。每个像素都有一个与之相关的红、绿、蓝值,我猜你正在寻找一种方法来测量"平均"像素的亮度?如果是这样,你需要循环遍历所有像素。同时计算每个像素的亮度。每个像素的"亮度"可以用几种方法计算,你可以简单地做(R + G + B)/3,或者你可以尝试模拟人眼对R, G和B的敏感度不一样。

然后你必须决定如何使用像素的"亮度"。Mean, Median,还有什么?这取决于你想做什么。

更新:在阅读了更多你的评论后,我仍然不确定你所说的"明亮"或"黑暗"是什么意思。似乎你的术语有点混乱,你一直在谈论整个图像的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