微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

实现框模糊 - C# 中的高斯模糊

如何解决实现框模糊 - C# 中的高斯模糊

我想在 C# 中实现基本的 box blur,但在我的版本中改变了图片的颜色,就像一个红绿色过滤器。这有什么问题?为什么要这样做?行的索引和我想的一样好,所以我真的不知道为什么会发生这种情况。我只想要一个简单的框模糊,所以,平滑图像,而不是别的。

这是我的原始图片https://ibb.co/pPsB2gT

private void Boxblur(object sender,EventArgs e)
{
  Bitmap image = new Bitmap(pictureBox.Image);
  BitmapData bitmapData = image.LockBits(new Rectangle(0,image.Width,image.Height),ImageLockMode.ReadWrite,image.PixelFormat); 
  int height = bitmapData.Height;
  int bPP = System.Drawing.Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; 
  int width = bitmapData.Width * bPP;

  Bitmap bitmap2 = image.Clone(new Rectangle(0,image.PixelFormat);
  unsafe 
  {
    byte* firstPixel = (byte*)bitmapData.Scan0; 
    Parallel.For(1,height - 1,j =>
    { 
          byte* line1 = firstPixel + ((j - 1) * bitmapData.Stride); //fst row
          byte* line2 = firstPixel + (j * bitmapData.Stride); //snd row
          byte* line3 = firstPixel + ((j + 1) * bitmapData.Stride); //thrd row
          int idx = 0;
          
          for (int i = 1; i < width-1; i = i + bPP)//one pixel in three elements of a row
          {
            int oldB = line1[i-1] + line1[i+2] + line1[i+5] +
            line2[i-1] + line2[i+2] + line2[i+5] +
            line3[i-1] + line3[i+2] + line3[i+5];

            int oldG = line1[i] + line1[i + 3] + line1[i + 6] +
            line2[i] + line2[i + 3] + line2[i + 6] +
            line3[i] + line3[i + 3] + line3[i + 6];

            int oldR = line1[i+1] + line1[i + 4] + line1[i + 7] +
            line2[i+1] + line2[i + 4] + line2[i + 7] +
            line3[i+1] + line3[i + 4] + line3[i + 7]; ;

            oldB = oldB/9;
            oldG = oldG/9;
            oldR = oldR/9;

            lock (bitmap2)
            {
              bitmap2.SetPixel(idx,j,Color.FromArgb(oldR,oldG,oldB));
            }
            idx++;
          }
          });
    image.UnlockBits(bitmapData);
  }

  pictureBox.Image = bitmap2;           
}

这是经过上面的算法后的样子:https://ibb.co/dmrQB8F

如果我尝试没有并行性,那么它工作正常:

private void Boxblur(object sender,EventArgs e)
{
        Bitmap bitmap = new Bitmap(pictureBox.Image);
        int width = bitmap.Width;
        int height = bitmap.Height;
        Bitmap bitmap2 = bitmap.Clone(new Rectangle(0,bitmap.Width,bitmap.Height),bitmap.PixelFormat);
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                if (i > 1 && j > 1 && i + 1 != width && j + 1 != height)
                {
                    int newRValue = bitmap.GetPixel(i,j + 1).R +
                                    bitmap.GetPixel(i + 1,j + 1).R +
                                    bitmap.GetPixel(i - 1,j).R +
                                    bitmap.GetPixel(i,j).R +
                                    bitmap.GetPixel(i + 1,j).R +
                                    bitmap.GetPixel(i - 1,j - 1).R +
                                    bitmap.GetPixel(i,j - 1).R +
                                    bitmap.GetPixel(i + 1,j - 1).R;
                    newRValue = Convert.ToInt32(newRValue / 9);

                    int newGValue = bitmap.GetPixel(i,j + 1).G +
                                    bitmap.GetPixel(i + 1,j + 1).G +
                                    bitmap.GetPixel(i - 1,j).G +
                                    bitmap.GetPixel(i,j).G +
                                    bitmap.GetPixel(i + 1,j).G +
                                    bitmap.GetPixel(i - 1,j - 1).G +
                                    bitmap.GetPixel(i,j - 1).G +
                                    bitmap.GetPixel(i + 1,j - 1).G;
                    newGValue = Convert.ToInt32(newGValue / 9);

                    int newBValue = bitmap.GetPixel(i,j + 1).B +
                                    bitmap.GetPixel(i + 1,j + 1).B +
                                    bitmap.GetPixel(i - 1,j).B +
                                    bitmap.GetPixel(i,j).B +
                                    bitmap.GetPixel(i + 1,j).B +
                                    bitmap.GetPixel(i - 1,j - 1).B +
                                    bitmap.GetPixel(i,j - 1).B +
                                    bitmap.GetPixel(i + 1,j - 1).B;
                    newBValue = Convert.ToInt32(newBValue / 9);

                    bitmap2.SetPixel(i,Color.FromArgb(newRValue,newGValue,newBValue));
                }
            }
        }
        pictureBox.Image = bitmap2;
}

这是没有并行算法之后的样子:https://ibb.co/dP9xrzT


我尝试执行 Gaussian blur,其工作方式也类似,但我遇到了同样的问题,但现在,使用另一种颜色过滤:

private void gaussianblur(object sender,EventArgs e)
        {
            Bitmap image = new Bitmap(pictureBox.Image);
            BitmapData bitmapData = image.LockBits(new Rectangle(0,image.PixelFormat); 
            int height = bitmapData.Height;
            int bPP = System.Drawing.Bitmap.GetPixelFormatSize(image.PixelFormat) / 8; 
            int width = bitmapData.Width * bPP;

            Bitmap bitmap2 = image.Clone(new Rectangle(0,image.PixelFormat);
            unsafe 
            {
                byte* firstPixel = (byte*)bitmapData.Scan0; 
                Parallel.For(1,j =>
                {
                    byte* line1 = firstPixel + ((j - 1) * bitmapData.Stride); 
                    byte* line2 = firstPixel + (j * bitmapData.Stride); 
                    byte* line3 = firstPixel + ((j + 1) * bitmapData.Stride);
                    int idx = 0;

                    for (int i = 1; i < width - 1; i = i + bPP)
                    {
                        int oldB = line1[i - 1] + line1[i + 2] * 2 + line1[i + 5] +
                                   line2[i - 1] *2 + line2[i + 2] *4 + line2[i + 5] * 2 +
                                   line3[i - 1] + line3[i + 2] *2+ line3[i + 5];

                        int oldG = line1[i] + line1[i + 3] *2 + line1[i + 6] +
                                   line2[i] *2+ line2[i + 3] *4+ line2[i + 6] *2+
                                   line3[i] + line3[i + 3] *2+ line3[i + 6];

                        int oldR = line1[i + 1] + line1[i + 4] *2 + line1[i + 7] +
                                   line2[i + 1] *2 + line2[i + 4] *4 + line2[i + 7] *2+
                                   line3[i + 1] + line3[i + 4] *2+ line3[i + 7];

                        oldB = oldB / 16;
                        oldG = oldG / 16;
                        oldR = oldR / 16;

                        lock (bitmap2)
                        {
                            bitmap2.SetPixel(idx,oldB));
                        }
                        idx++;
                    }
                });
                image.UnlockBits(bitmapData);
            }

            pictureBox.Image = bitmap2;
        }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。