Skip to main content
 首页 » 编程设计

c#之c#中的不安全图像噪声去除(错误: Bitmap region is already locked)

2024年02月03日32lyj

public unsafe Bitmap  MedianFilter(Bitmap Img) 
     { 
        int Size =2; 
 
        List<byte> R = new List<byte>(); 
        List<byte> G = new List<byte>(); 
        List<byte> B = new List<byte>(); 
 
        int ApetureMin = -(Size / 2); 
        int ApetureMax = (Size / 2); 
 
        BitmapData imageData = Img.LockBits(new Rectangle(0, 0, Img.Width, Img.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb); 
 
        byte* start = (byte*)imageData.Scan0.ToPointer (); 
        for (int x = 0; x < imageData.Width; x++) 
        { 
            for (int y = 0; y < imageData.Height; y++) 
            { 
                for (int x1 = ApetureMin; x1 < ApetureMax; x1++) 
                { 
                    int valx = x + x1; 
                    if (valx >= 0 && valx < imageData.Width) 
                    { 
                        for (int y1 = ApetureMin; y1 < ApetureMax; y1++) 
                        { 
                            int valy = y + y1; 
                            if (valy >= 0 && valy < imageData.Height) 
                            { 
                                Color tempColor = Img.GetPixel(valx, valy);// error come from here 
                                R.Add(tempColor.R); 
                                G.Add(tempColor.G); 
                                B.Add(tempColor.B); 
                            } 
                        } 
                    } 
                } 
            } 
        } 
 
        R.Sort(); 
        G.Sort(); 
        B.Sort(); 
 
        Img.UnlockBits(imageData); 
        return Img; 
     } 

我试过这样做。但我收到一个错误消息“位图区域已被锁定”任何人都可以帮助解决这个问题。 (错误位置高亮显示)

请您参考如下方法:

GetPixel 是访问图像的 slooow 方法,如果其他人开始直接弄乱图像缓冲区,它就不再起作用(正如您所注意到的)。为什么要这样做?

检查 Using the LockBits method to access image data以获得对快速图像处理的一些深入了解。

在这种情况下,请改用这样的东西:

int pixelSize = 4 /* Check below or the site I linked to and make sure this is correct */ 
byte* color =(byte *)imageData .Scan0+(y*imageData .Stride) + x * pixelSize; 

请注意,这为您提供了该像素的第一个字节。根据您正在查看的颜色格式(ARGB?RGB?..),您还需要访问以下字节。似乎无论如何都适合您的用例,因为您只关心字节值,而不是 Color 值。


所以,经过一些空闲时间,这就是我想出的(请花点时间理解和检查它,我只是确保它可以编译):

    public void SomeStuff(Bitmap image) 
    { 
        var imageWidth = image.Width; 
        var imageHeight = image.Height; 
        var imageData = image.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb); 
 
        var imageByteCount = imageData.Stride*imageData.Height; 
        var imageBuffer = new byte[imageByteCount]; 
        Marshal.Copy(imageData.Scan0, imageBuffer, 0, imageByteCount); 
 
        for (int x = 0; x < imageWidth; x++) 
        { 
            for (int y = 0; y < imageHeight; y++) 
            { 
                var pixelColor = GetPixel(imageBuffer, imageData.Stride, x, y); 
 
                // Do your stuff 
            } 
        } 
    } 
 
    private static Color GetPixel(byte[] imageBuffer, int imageStride, int x, int y) 
    { 
 
        int pixelBase = y*imageStride + x*3; 
        byte blue = imageBuffer[pixelBase]; 
        byte green = imageBuffer[pixelBase + 1]; 
        byte red = imageBuffer[pixelBase + 2]; 
 
        return Color.FromArgb(red, green, blue); 
    } 

这个

  • 取决于您在示例中使用的 PixelFormat(关于像素大小/每像素字节数和值的顺序)。如果您更改 PixelFormat,这将中断。
  • 不需要不安全关键字。我怀疑这会有很大的不同,但您可以自由使用基于指针的访问,方法是相同的。