Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Rgb图像转换为灰度C#代码时出现性能问题_C#_Tesseract_Grayscale - Fatal编程技术网

将Rgb图像转换为灰度C#代码时出现性能问题

将Rgb图像转换为灰度C#代码时出现性能问题,c#,tesseract,grayscale,C#,Tesseract,Grayscale,我正在为Tesseract Ocr编写一个.Net包装器,如果我使用灰度图像而不是rgb图像作为输入文件,那么结果非常好 所以我在网上搜索C#解决方案,将Rgb图像转换为灰度图像,然后 这将执行3个操作以提高tesseract的精度 调整图像大小 然后转换成灰度图像,去除图像中的噪声 现在,这张转换后的图像给出了几乎90%的准确结果 //Resize public Bitmap Resize(Bitmap bmp, int newWidth, int newHeight) {

我正在为Tesseract Ocr编写一个.Net包装器,如果我使用灰度图像而不是rgb图像作为输入文件,那么结果非常好

所以我在网上搜索C#解决方案,将Rgb图像转换为灰度图像,然后

这将执行3个操作以提高tesseract的精度

  • 调整图像大小
  • 然后转换成灰度图像,去除图像中的噪声
  • 现在,这张转换后的图像给出了几乎90%的准确结果

    //Resize
    
    public Bitmap Resize(Bitmap bmp, int newWidth, int newHeight)
    {    
        Bitmap temp = (Bitmap)bmp;
        Bitmap bmap = new Bitmap(newWidth, newHeight, temp.PixelFormat);
    
        double nWidthFactor = (double)temp.Width / (double)newWidth;
        double nHeightFactor = (double)temp.Height / (double)newHeight;
    
        double fx, fy, nx, ny;
        int cx, cy, fr_x, fr_y;
        Color color1 = new Color();
        Color color2 = new Color();
        Color color3 = new Color();
        Color color4 = new Color();
        byte nRed, nGreen, nBlue;
    
        byte bp1, bp2;
    
        for (int x = 0; x < bmap.Width; ++x)
        {
            for (int y = 0; y < bmap.Height; ++y)
            {
                fr_x = (int)Math.Floor(x * nWidthFactor);
                fr_y = (int)Math.Floor(y * nHeightFactor);
    
                cx = fr_x + 1;
                if (cx >= temp.Width)
                    cx = fr_x;
    
                cy = fr_y + 1;
                if (cy >= temp.Height)
                    cy = fr_y;
    
                fx = x * nWidthFactor - fr_x;
                fy = y * nHeightFactor - fr_y;
                nx = 1.0 - fx;
                ny = 1.0 - fy;
    
                color1 = temp.GetPixel(fr_x, fr_y);
                color2 = temp.GetPixel(cx, fr_y);
                color3 = temp.GetPixel(fr_x, cy);
                color4 = temp.GetPixel(cx, cy);
    
                // Blue
                bp1 = (byte)(nx * color1.B + fx * color2.B); 
                bp2 = (byte)(nx * color3.B + fx * color4.B);
                nBlue = (byte)(ny * (double)(bp1) + fy * (double)(bp2));
    
                // Green
                bp1 = (byte)(nx * color1.G + fx * color2.G);    
                bp2 = (byte)(nx * color3.G + fx * color4.G);    
                nGreen = (byte)(ny * (double)(bp1) + fy * (double)(bp2));
    
                // Red
                bp1 = (byte)(nx * color1.R + fx * color2.R);   
                bp2 = (byte)(nx * color3.R + fx * color4.R);
                nRed = (byte)(ny * (double)(bp1) + fy * (double)(bp2));
    
                bmap.SetPixel(x, y, System.Drawing.Color.FromArgb(255, nRed, nGreen, nBlue));
            }
        }
    
        //here i included the below to functions logic without the for loop to remove repetitive use of for loop but it did not work and taking the same time.
        bmap = SetGrayscale(bmap);
        bmap = RemoveNoise(bmap);
    
        return bmap;
    }
    
    //SetGrayscale
    public Bitmap SetGrayscale(Bitmap img)
    {
        Bitmap temp = (Bitmap)img;
        Bitmap bmap = (Bitmap)temp.Clone();
        Color c;
        for (int i = 0; i < bmap.Width; i++)
        {
            for (int j = 0; j < bmap.Height; j++)
            {
                c = bmap.GetPixel(i, j);
                byte gray = (byte)(.299 * c.R + .587 * c.G + .114 * c.B);
    
                bmap.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
            }
        }
        return (Bitmap)bmap.Clone();
    }
    
    //RemoveNoise
    public Bitmap RemoveNoise(Bitmap bmap)
    {    
        for (var x = 0; x < bmap.Width; x++)
        {
            for (var y = 0; y < bmap.Height; y++)
            {
                var pixel = bmap.GetPixel(x, y);
                if (pixel.R < 162 && pixel.G < 162 && pixel.B < 162)
                    bmap.SetPixel(x, y, Color.Black);
            }
        }
    
        for (var x = 0; x < bmap.Width; x++)
        {
            for (var y = 0; y < bmap.Height; y++)
            {
                var pixel = bmap.GetPixel(x, y);
                if (pixel.R > 162 && pixel.G > 162 && pixel.B > 162)
                    bmap.SetPixel(x, y, Color.White);
            }
        }
        return bmap;
    }
    
    //调整大小
    公共位图调整大小(位图bmp、int newWidth、int newHeight)
    {    
    位图温度=(位图)bmp;
    位图bmap=新位图(新宽度、新高度、临时像素格式);
    双nWidthFactor=(双)临时宽度/(双)新宽度;
    双N权重系数=(双)温度高度/(双)新高度;
    纽约州纽约州财政部双倍外汇;
    int-cx,cy,fr_x,fr_y;
    颜色1=新颜色();
    颜色2=新颜色();
    Color color3=新颜色();
    Color color4=新颜色();
    字节nRed、nGreen、nBlue;
    字节bp1,bp2;
    对于(int x=0;x=温度宽度)
    cx=fr_x;
    cy=fr_y+1;
    如果(cy>=温度高度)
    cy=fr_y;
    fx=x*nWidthFactor-fr_x;
    fy=y*n权重因子-fr_y;
    nx=1.0-fx;
    ny=1.0-fy;
    color1=温度获取像素(fr_x,fr_y);
    color2=温度获取像素(cx,fr_y);
    color3=温度获取像素(fr_x,cy);
    color4=温度获取像素(cx,cy);
    //蓝色的
    bp1=(字节)(nx*color1.B+fx*color2.B);
    bp2=(字节)(nx*color3.B+fx*color4.B);
    nBlue=(字节)(ny*(双字节)(bp1)+fy*(双字节)(bp2));
    //绿色的
    bp1=(字节)(nx*color1.G+fx*color2.G);
    bp2=(字节)(nx*color3.G+fx*color4.G);
    nGreen=(字节)(ny*(双字节)(bp1)+fy*(双字节)(bp2));
    //红色的
    bp1=(字节)(nx*color1.R+fx*color2.R);
    bp2=(字节)(nx*color3.R+fx*color4.R);
    nRed=(字节)(ny*(双字节)(bp1)+fy*(双字节)(bp2));
    bmap.SetPixel(x,y,System.Drawing.Color.FromArgb(255,nRed,nGreen,nBlue));
    }
    }
    //在这里,我在没有for循环的情况下加入了下面的to函数逻辑,以消除for循环的重复使用,但它不起作用,并且占用了相同的时间。
    bmap=设置灰度(bmap);
    bmap=清除噪声(bmap);
    返回bmap;
    }
    //设定灰度
    公共位图设置灰度(位图img)
    {
    位图温度=(位图)img;
    位图bmap=(位图)临时克隆();
    颜色c;
    对于(int i=0;i162&&pixel.G>162&&pixel.B>162)
    bmap.SetPixel(x,y,彩色,白色);
    }
    }
    返回bmap;
    }
    
    但问题是转换它需要很多时间

    所以我加入了
    SetGrayscale(位图bmap)
    RemoveNoise(位图bmap)
    Resize()
    方法中的函数逻辑,以消除for循环的重复使用


    但是它并没有解决我的问题。

    位图类的
    GetPixel()
    SetPixel()
    方法对于多次读取/写入速度非常慢。访问和设置位图中单个像素的更快方法是首先锁定它

    有一个很好的例子说明了如何做到这一点,它使用了一个很好的类
    lockedbimat
    来包装陌生人
    Marshal
    ing代码

    基本上,它所做的是使用
    Bitmap
    类中的
    LockBits()
    方法,为要锁定的位图区域传递一个矩形,然后将这些像素从其非托管内存位置复制到托管内存位置,以便于访问

    下面是一个示例,说明如何将该示例类用于
    SetGrayscale()
    方法:

    public Bitmap SetGrayscale(Bitmap img)
    {
        LockedBitmap lockedBmp = new LockedBitmap(img.Clone());
        lockedBmp.LockBits(); // lock the bits for faster access
        Color c;
        for (int i = 0; i < lockedBmp.Width; i++)
        {
            for (int j = 0; j < lockedBmp.Height; j++)
            {
                c = lockedBmp.GetPixel(i, j);
                byte gray = (byte)(.299 * c.R + .587 * c.G + .114 * c.B);
    
                lockedBmp.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
            }
        }
        lockedBmp.UnlockBits(); // remember to release resources
        return lockedBmp.Bitmap; // return the bitmap (you don't need to clone it again, that's already been done).
    }
    
    公共位图设置灰度(位图img)
    {
    LockedBitmap lockedBmp=新的LockedBitmap(img.Clone());
    lockedBmp.LockBits();//锁定位以加快访问速度
    颜色c;
    对于(int i=0;i
    这个包装类为我节省了大量位图处理时间。一旦您在所有方法中实现了这一点,最好只调用一次
    LockBits()
    ,那么我相信您的应用程序的性能将大大提高


    我还看到你经常克隆图像。这可能不是