从PictureBox获取指定颜色的所有像素

3
我希望能够在C#中获取特定颜色的所有像素(无论是来自ARGB还是任何Color类中的颜色)。我的第一个想法是将picturebox内容绘制到Bitmap中,然后使用for循环迭代每个像素,使用b.GetPixel(x,y);。然而,我使用的PictureBox非常巨大,需要进行数百万/数千万次迭代来检查,这样会严重影响性能。是否有比此更好的解决方案?谢谢。

2
你正在寻找 Bitmap.Lockbits - Alexei Levenkov
我几乎看不出你如何在不检查每个像素的情况下验证并选择所需的像素。除非使用降低精度的启发式方法(例如预测周围像素),否则似乎只能使用O(n)。这就像尝试计算数组而不遍历每个元素一样,你受到O(n)的限制,这是不可能的。而你可能会找到的替代方案最终都会回到内部逐个查看每个像素的方式。 - Pierre-Luc Pineault
您想处理的图像有多大?也许使用早期评论中提到的 Lockbits() 并将其与不安全的图像处理代码结合使用,尽管需要检查每个像素,但会给您带来可接受的性能。 - Lukasz M
使用LockBits非常快,但我希望你不要在实时中这样做..! - TaW
我刚写了一个示例代码,使用Lockbits()unsafe像素数据访问来逐像素检查颜色,并计算匹配像素的数量。在我的机器上,处理一张1920x1080的图像(2073600个像素)大约需要90毫秒。您可以在这里找到一些不安全的像素数据访问示例:http://ithoughthecamewithyou.com/post/fastest-image-merge-%28alpha-blend%29-in-gdi2b。如果您在实现过程中需要帮助,请告诉我。 - Lukasz M
1个回答

0
我编写了针对System.Drawing.Image的扩展方法,它可以迭代图像中的每个像素,并返回一个包含每个x/y坐标的System.Drawing.Point的列表。
您可以搜索rgb值或rgba值。
我的方法使用指针,因此您需要为项目启用不安全代码。
与GetPixel(...)相比,使用指针迭代位图速度快得多。
在这篇博客文章中,GetPixel(...)被认为比基于指针的解决方案慢1000多倍。 http://davidthomasbernal.com/blog/2008/03/14/c-image-processing-performance-unsafe-vs-safe-code-part-ii/
在使用此代码之前,您应该适当地测试它,但即使出现问题,本文所示的技术也应该能让您入门!
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;

public static class Pixelcounter
{
    private struct PixeldataARGB
    {
        public byte b;
        public byte g;
        public byte r;
        public byte a;
    }

    private struct PixeldataRGB
    {
        public byte b;
        public byte g;
        public byte r;
    }

    public static IEnumerable<Point> CountOccurences(this Image @this, int r, int g, int b)
    {
        if (r < 0 || g < 0 || b < 0)
            throw new ArgumentException("color values must not be negative");
        if (r > 255 || g > 255 || b > 255)
            throw new ArgumentException("color values must be below 256");

        return CountOccurences(@this, (byte)r, (byte)g, (byte)b);
    }

    public static unsafe IEnumerable<Point> CountOccurences(this Image @this, byte r, byte g, byte b)
    {
        Bitmap bitmap = new Bitmap(@this);
        BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        PixeldataRGB* pointer = (PixeldataRGB*)bitmapData.Scan0;

        List<Point> pointList = new List<Point>();

        for (int y = 0; y < bitmap.Height; y++)
        {
            for (int x = 0; x < bitmap.Width; x++)
            {
                PixeldataRGB current = *pointer;
                if (current.r == r && current.g == g && current.b == b)
                    pointList.Add(new Point(x, y));
                pointer++;
            }
        }

        bitmap.Dispose();

        return pointList;
    }

    public static IEnumerable<Point> CountOccurences(this Image @this, int r, int g, int b, int a)
    {
        if (r < 0 || g < 0 || b < 0 || a < 0)
            throw new ArgumentException("color and alpha values must not be negative");
        if (r > 255 || g > 255 || b > 255 || a > 255)
            throw new ArgumentException("color and alpha values must be below 256");

        return CountOccurences(@this, (byte)r, (byte)g, (byte)b, (byte)a);
    }

    public static unsafe IEnumerable<Point> CountOccurences(this Image @this, byte r, byte g, byte b, byte a)
    {
        Bitmap bitmap = new Bitmap(@this);
        BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
        PixeldataARGB* pointer = (PixeldataARGB*)bitmapData.Scan0;

        List<Point> pointList = new List<Point>();

        for (int y = 0; y < bitmap.Height; y++)
        {
            for (int x = 0; x < bitmap.Width; x++)
            {
                PixeldataARGB current = *pointer;
                if (current.r == r && current.g == g && current.b == b && current.a == a)
                    pointList.Add(new Point(x, y));
                pointer++;
            }
        }

        bitmap.Dispose();

        return pointList;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接