首页 > 解决方案 > 如何从位图中获取前 10 个最高红/蓝值像素?

问题描述

谁能指出我正确的方向,我需要从位图中收集包含前 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;
}

提前致谢。

标签: c#imageimage-processing

解决方案


这是一种蛮力的方法:

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

推荐阅读