代码之家  ›  专栏  ›  技术社区  ›  user366312

锐化操作,输出对比度不正确

  •  2
  • user366312  · 技术社区  · 6 年前

    请看一下这个源代码。具有以下内核的3x3锐化过滤器

    0-1 0
    -15-1
    0-1 0
    

    给出以下输出:

    我试图用我自己的代码来复制结果,这非常直接:

    public分部类filterform:form
    {
    公共筛选窗体()
    {
    初始化组件();
    
    位图图像=(bitmap)bitmap.fromfile(“lena.jpg”);
    inputPictureBox.image=图像;
    
    double[,]dimage=todouble2d(图像);
    双[,]dmask=0,-1,0,,
    -1,5,-1,,
    _0,-1,0,,
    
    double[,]dconv=线性变换空间(dimage,dmask);
    
    bitmap conv=tobitmap2d(dconv,pixelformat.format32bppargb);
    
    outputPictureBox.image=conv;
    }
    
    public double[,]todouble2d(位图输入)
    {
    int width=输入.width;
    int height=输入。height;
    
    double[,]array2d=新double[宽度,高度];
    
    对于(int y=0;y<height;y++)
    {
    对于(int x=0;x<width;x++)
    {
    颜色cl=input.getPixel(x,y);
    
    双灰色=(cl.r*0.3)+(cl.g*0.59)+(cl.b*0.11));
    
    array2d[x,y]=灰色/255.0;
    }
    }
    
    返回阵列2d;
    }
    
    公共位图tobitmap2d(double[,]image,pixelformat pixelformat)
    {
    int width=image.getlength(0);
    int height=image.getlength(1);
    
    位图BMP=新位图(宽度、高度、像素格式);
    
    对于(int y=0;y<height;y++)
    {
    对于(int x=0;x<width;x++)
    {
    int i=(int)(图像[x,y]*255.0);
    
    如果(i>255)i=255;
    如果(i<0)i=0;
    
    颜色clr=颜色。来自argb(i,i,i);
    
    bmp.设置像素(x,y,clr);
    }
    }
    
    返回BMP;
    }
    
    private double[,]linearconvolutionspatial(double[,]paddedimage,double[,]mask)
    {
    int paddedimagewidth=paddedimage.getlength(0);
    int paddedimageheight=paddedimage.getlength(1);
    
    int maskwidth=mask.getlength(0);
    int maskheight=mask.getlength(1);
    
    int imagewidth=paddedimagewidth-maskwidth;
    int imageheight=paddedimageheight-遮罩高度;
    
    double[,]卷积=新的double[图像宽度,图像高度];
    
    对于(int y=0;y<imageheight;y++)
    {
    对于(int x=0;x<imagewidth;x++)
    {
    双和=和(paddedimage,mask,x,y);
    int x x x=x;
    利息y=y;
    卷积[XXX,YYY]=和;
    
    string str=string.empty;
    }
    }
    
    重新缩放(卷积);
    
    返回卷积;
    }
    
    双和(double[,]paddedimage1,double[,]mask1,int startx,int starty)
    {
    双和=0;
    
    int maskwidth=mask1.getlength(0);
    int maskheight=mask1.getlength(1);
    
    对于(int y=starty;y<(starty+maskheight);y++)
    {
    对于(int x=startx;x<(startx+maskwidth);x++)
    {
    双img=paddedimage1[x,y];
    double msk=mask1[遮罩宽度-x+startx-1,遮罩高度-y+starty-1];
    sum=sum+(img*msk);
    }
    }
    
    返还金额;
    }
    
    无效重缩放(双[,]卷积)
    {
    int imagewidth=卷积。获取长度(0);
    int imageheight=卷积。获取长度(1);
    
    双MinAmp=0.0;
    双最大值=0.0;
    
    对于(int j=0;j<imageheight;j++)
    {
    对于(int i=0;i<imagewidth;i++)
    {
    MinAmp=数学最小值(MinAmp,卷积[I,J]);
    最大值=数学最大值(最大值,卷积[I,J]);
    }
    }
    
    双刻度=1/(math.abs(minamp)+maxamp);
    
    对于(int j=0;j<imageheight;j++)
    {
    对于(int i=0;i<imagewidth;i++)
    {
    double d=(卷积[i,j]+math.abs(minamp))*比例;
    卷积[i,j]=d;
    }
    }
    }
    }
    

    但是,我面临的问题是,我的输出具有不同的对比度。

    我应该解决哪些问题?

     0  -1   0 
    -1   5  -1 
     0  -1   0
    

    给出以下输出:

    enter image description here

    我尝试使用自己的代码来复制结果,这非常直接:

    public partial class FilterForm : Form
    {
        public FilterForm()
        {
            InitializeComponent();
    
            Bitmap image = (Bitmap)Bitmap.FromFile("lena.jpg");            
            InputPictureBox.Image = image;
    
            double[,] dImage = ToDouble2d(image);
            double[,] dMask = { { 0,-1, 0, }, 
                                { -1, 5, -1, }, 
                                { 0,-1, 0, }, };
    
            double[,]dConv = LinearConvolutionSpatial(dImage, dMask);
    
            Bitmap conv = ToBitmap2d(dConv, PixelFormat.Format32bppArgb);
    
            OutputPictureBox.Image = conv;
        }
    
        public double[,] ToDouble2d(Bitmap input)
        {
            int width = input.Width;
            int height = input.Height;
    
            double[,] array2d = new double[width, height];
    
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Color cl = input.GetPixel(x, y);
    
                    double gray = ((cl.R * 0.3) + (cl.G * 0.59) + (cl.B * 0.11));
    
                    array2d[x, y] = gray / 255.0;
                }
            }
    
            return array2d;
        }
    
        public Bitmap ToBitmap2d(double[,] image, PixelFormat pixelFormat)
        {
            int Width = image.GetLength(0);
            int Height = image.GetLength(1);
    
            Bitmap bmp = new Bitmap(Width, Height, pixelFormat);
    
            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    int i = (int)(image[x, y] * 255.0);
    
                    if (i > 255) i = 255;
                    if (i < 0) i = 0;
    
                    Color clr = Color.FromArgb(i, i, i);
    
                    bmp.SetPixel(x, y, clr);
                }
            }
    
            return bmp;
        }
    
        private double[,] LinearConvolutionSpatial(double[,] paddedImage, double[,] mask)
        {
            int paddedImageWidth = paddedImage.GetLength(0);
            int paddedImageHeight = paddedImage.GetLength(1);
    
            int maskWidth = mask.GetLength(0);
            int maskHeight = mask.GetLength(1);
    
            int imageWidth = paddedImageWidth - maskWidth;
            int imageHeight = paddedImageHeight - maskHeight;
    
            double[,] convolve = new double[imageWidth, imageHeight];
    
            for (int y = 0; y < imageHeight; y++)
            {
                for (int x = 0; x < imageWidth; x++)
                {
                    double sum = Sum(paddedImage, mask, x, y);
                    int xxx = x;
                    int yyy = y;
                    convolve[xxx, yyy] = sum;
    
                    string str = string.Empty;
                }
            }
    
            Rescale(convolve);
    
            return convolve;
        }
    
        double Sum(double[,] paddedImage1, double[,] mask1, int startX, int startY)
        {
            double sum = 0;
    
            int maskWidth = mask1.GetLength(0);
            int maskHeight = mask1.GetLength(1);
    
            for (int y = startY; y < (startY + maskHeight); y++)
            {
                for (int x = startX; x < (startX + maskWidth); x++)
                {
                    double img = paddedImage1[x, y];
                    double msk = mask1[maskWidth - x + startX - 1, maskHeight - y + startY - 1];
                    sum = sum + (img * msk);
                }
            }
    
            return sum;
        }
    
        void Rescale(double[,] convolve)
        {
            int imageWidth = convolve.GetLength(0);
            int imageHeight = convolve.GetLength(1);
    
            double minAmp = 0.0;
            double maxAmp = 0.0;
    
            for (int j = 0; j < imageHeight; j++)
            {
                for (int i = 0; i < imageWidth; i++)
                {
                    minAmp = Math.Min(minAmp, convolve[i, j]);
                    maxAmp = Math.Max(maxAmp, convolve[i, j]);
                }
            }
    
            double scale = 1 / (Math.Abs(minAmp) + maxAmp);
    
            for (int j = 0; j < imageHeight; j++)
            {
                for (int i = 0; i < imageWidth; i++)
                {
                    double d = (convolve[i, j] + Math.Abs(minAmp)) * scale;
                    convolve[i, j] = d;
                }
            }
        }
    }
    

    但是,我面临的问题是,我的输出有一个不同的对比.

    enter image description here

    enter image description here

    我应该解决哪些问题?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Abstract    6 年前

    上面的一些代码具有最小/最大效果,并平衡柱状图。

    从该行中删除规范化位:

     array2d[x, y] = gray;// / 255.0;
    

    我删除了这篇文章中255的重缩放倍数:

    public Bitmap ToBitmap2d(double[,] image, PixelFormat pixelFormat)
    {
        int Width = image.GetLength(0);
        int Height = image.GetLength(1);
    
        Bitmap bmp = new Bitmap(Width, Height, pixelFormat);
    
        for (int y = 0; y < Height; y++)
        {
            for (int x = 0; x < Width; x++)
            {
                int i = (int)(image[x, y] * 1);
    
                if (i > 255) i = 255;
                if (i < 0) i = 0;
    
                Color clr = Color.FromArgb(i, i, i);
    
                bmp.SetPixel(x, y, clr);
            }
        }
    
        return bmp;
    }
    

    我还从这个函数中去掉了比例因子:

    void Rescale(double[,] convolve)
    {
        int imageWidth = convolve.GetLength(0);
        int imageHeight = convolve.GetLength(1);
    
        double minAmp = 0.0;
        double maxAmp = 255.0;
    
        for (int j = 0; j < imageHeight; j++)
        {
            for (int i = 0; i < imageWidth; i++)
            {
                minAmp = Math.Min(minAmp, convolve[i, j]);
                maxAmp = Math.Max(maxAmp, convolve[i, j]);
             }
         }
    
         double scale = 1 / (Math.Abs(minAmp) + maxAmp);
    
         for (int j = 0; j < imageHeight; j++)
         {
             for (int i = 0; i < imageWidth; i++)
             {
                 double d = (convolve[i, j]);// + Math.Abs(minAmp)) * scale;
                 convolve[i, j] = d;
             }
         }
     }
    

    在这种情况下,在进行这些更改之后,似乎可以按预期工作。

        2
  •  1
  •   user366312    6 年前

    我从中找到了解决方案 this link . 主要线索是介绍 offset 和A factor .

    • 因素 是内核中所有值的总和。
    • 抵消 是用于进一步修复输出的任意值。

    给定链接中提供了以下源代码:

        private void SafeImageConvolution(Bitmap image, ConvMatrix fmat) 
        { 
            //Avoid division by 0 
            if (fmat.Factor == 0) 
                return; 
    
            Bitmap srcImage = (Bitmap)image.Clone(); 
    
            int x, y, filterx, filtery; 
            int s = fmat.Size / 2; 
            int r, g, b; 
            Color tempPix; 
    
            for (y = s; y < srcImage.Height - s; y++) 
            { 
                for (x = s; x < srcImage.Width - s; x++) 
                { 
                    r = g = b = 0; 
    
                    // Convolution 
                    for (filtery = 0; filtery < fmat.Size; filtery++) 
                    { 
                        for (filterx = 0; filterx < fmat.Size; filterx++) 
                        { 
                            tempPix = srcImage.GetPixel(x + filterx - s, y + filtery - s); 
    
                            r += fmat.Matrix[filtery, filterx] * tempPix.R; 
                            g += fmat.Matrix[filtery, filterx] * tempPix.G; 
                            b += fmat.Matrix[filtery, filterx] * tempPix.B; 
                        } 
                    } 
    
                    r = Math.Min(Math.Max((r / fmat.Factor) + fmat.Offset, 0), 255); 
                    g = Math.Min(Math.Max((g / fmat.Factor) + fmat.Offset, 0), 255); 
                    b = Math.Min(Math.Max((b / fmat.Factor) + fmat.Offset, 0), 255); 
    
                    image.SetPixel(x, y, Color.FromArgb(r, g, b)); 
                } 
            } 
        }