如何从位图中获取前10个最高的红色/蓝色值像素?

时间:2019-08-20 23:26:34

标签: c# image image-processing

任何人都可以将我指向正确的方向,我需要从位图中收集包含前10个红色和蓝色像素的点的列表,特别是前10个最高红色值像素和前10个最高蓝色值像素。我知道的问题,但是在有人尝试过相同问题的地方我找不到谷歌搜索。

在这一点上,我只能想像弄出一些极其缓慢的东西,因此我首先在这里。

更新: 我不确定如何使问题更清楚,最高的字面意思是最高的R字节值和最高的B字节值。

public unsafe List<Point> GetHighestRedAndBluePixels(Bitmap b)
{
    List<Point> highestRedAndBlues = new List<Point>();
    List<Point> highest10Reds = new List<Point>();
    List<Point> highest10Blues = new List<Point>();

    BitmapData bData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, b.PixelFormat);

    int bitsPerPixel = 32;
    byte* scan0 = (byte*)bData.Scan0.ToPointer();

    for(int y = 0; y < bData.Height; ++y)
    {
        for(int x = 0; x < bData.Width; ++x)
        {
            byte* data = scan0 + y * bData.Stride + x * bitsPerPixel / 8;
            // looping pixel data fast > need to store highest 10 'R's and 'B's
        }
    }
    b.UnlockBits(bData);

    highestRedAndBlues.AddRange(highest10Reds);
    highestRedAndBlues.AddRange(highest10Blues);
    return highestRedAndBlues;
}

谢谢。

1 个答案:

答案 0 :(得分:1)

这是一种蛮力:

private struct MyPixel
{
    public Point Coord { get; set; }
    public Color Rgb { get; set; }
    public float Rfraction
    {
        get { return Rgb.R / (float)(Rgb.R + Rgb.G + Rgb.B); }
    }
    public float Bfraction
    {
        get { return Rgb.B / (float)(Rgb.R + Rgb.G + Rgb.B); }
    }
}

,您可以像下面这样使用该结构:

using (Bitmap img = new Bitmap("truc.bmp"))
{
    for (int x = 0; x < img.Width; x++)
    {
        for (int y = 0; y < img.Height; y++)
        {
            var m  = new MyPixel();
            m.Coord = new Point(x, y);
            m.Rgb = img.GetPixel(x,y);
            MyPixels.Add(m);
        }
    }

    var maxreds = MyPixels.OrderByDescending(x => x.Rfraction).Take(10);
    var maxblues = MyPixels.OrderByDescending(x => x.Bfraction).Take(10);
}

您可以获得最高的红色/蓝色值或最高的红色/蓝色分数(请参阅我在问题中的评论...)

编辑:使用BitmapData可以更快(但仍然很脏)的方式进行操作。可能会占用大量内存(对于4032x3024的图片,其内存大于500Mo,但要花2秒钟才能完成)。大量基于BitmapData Documentation

List<MyPixel> pixels = new List<MyPixel>();
using (Bitmap img = new Bitmap("t.bmp"))
{
    var bmpData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite,
        PixelFormat.Format24bppRgb);
    IntPtr ptr = bmpData.Scan0;
    int bytes = Math.Abs(bmpData.Stride) * bmpData.Height;
    byte[] rgbValues = new byte[bytes];
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
    img.UnlockBits(bmpData);

    for (int i = 0; i < rgbValues.Length; i += 3)
    {
        int x = i / Math.Abs(bmpData.Stride);
        int y = (i - x * Math.Abs(bmpData.Stride)) / 3;
        var m = new MyPixel();    
        m.Coord = new Point(x, y);
        m.Rgb = Color.FromArgb(rgbValues[i + 2], rgbValues[i + 1], rgbValues[i]);
        pixels.Add(m);
    }

    var maxred = pixels.OrderByDescending(x => x.Rfraction).Take(10);
    var maxblue = pixels.OrderByDescending(x => x.Bfraction).Take(10);
}