如何修复书页的暗淡图像

时间:2015-12-06 11:07:04

标签: c# image-processing

我有1000页的图书页面,其文字为这件作品 Dimmed Text
现在我尝试修复它以便更清楚地阅读,我使用此代码

int age = 0;

由于图像尺寸为1168 x 1807,需要花费大量时间才能完成修复,它完全循环2110576次循环。
有没有其他方法可以解决这个问题?感谢。

2 个答案:

答案 0 :(得分:2)

我能想到使用内置ColorMatrix类来更改图像的 Gamma 对比度的最佳方式。

以下是Gamma = 6.27Contrast = +1.04的结果:

enter image description here

以下是我使用的代码:

using System.Drawing.Imaging;
..

public static Bitmap ApplyGamma(Bitmap bmp0, float gamma, float contrast)
{

    Bitmap bmp1 = new Bitmap(bmp0.Width, bmp0.Height);
    using (Graphics g = Graphics.FromImage(bmp1))
    {
        ColorMatrix colorMatrix = new ColorMatrix(new float[][] 
                {
                    new float[] {contrast, 0, 0, 0, 0},
                    new float[] {0,contrast, 0, 0, 0},
                    new float[] {0, 0, contrast, 0, 0},
                    new float[] {0, 0, 0, 1, 0},
                    new float[] {0, 0, 0, 0, 1}
                });


        ImageAttributes attributes = new ImageAttributes();
        attributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default,
                                               ColorAdjustType.Bitmap);
        attributes.SetGamma(gamma, ColorAdjustType.Bitmap);
        g.DrawImage(bmp0, new Rectangle(0, 0, bmp0.Width, bmp0.Height),
                    0, 0, bmp0.Width, bmp0.Height, GraphicsUnit.Pixel, attributes);
    }
    return bmp1;
}

该函数使用两个变量和两个TrackBars以及两个Labels

float gamma = 1f ;
float contrast = 1f;

private void trackBar1_Scroll(object sender, EventArgs e)
{
    gamma = 1f * trackBar1.Value / 100f;
    label1.Text = gamma.ToString("#0.00");
    pictureBox1.Image = ApplyGamma(originalImage, gamma, contrast);
}


private void trackBar2_Scroll(object sender, EventArgs e)
{
    contrast = 1f * trackBar2.Value / 1000f;
    label2.Text = contrast.ToString("#0.00");
    pictureBox1.Image = ApplyGamma(originalImage, gamma, contrast);
}

请注意,我泄漏位图;它只是用于测试; - )

答案 1 :(得分:1)

我使用(C ++)代码:

void picture::enhance_range()
    {
    int i,x,y,a0[4],min[4],max,n,c0,c1,q,c;
    if (xs<1) return;
    if (ys<1) return;

    n=0;    // dimensions to interpolate
    if (pf==_pf_s   ) { n=1; c0=0; c1=127*3; }
    if (pf==_pf_u   ) { n=1; c0=0; c1=255*3; }
    if (pf==_pf_ss  ) { n=2; c0=0; c1=32767; }
    if (pf==_pf_uu  ) { n=2; c0=0; c1=65535; }
    if (pf==_pf_rgba) { n=4; c0=0; c1=  255; } // this is your image pixel format so ignore the other pf statements

    // find min,max intensities
    dec_color(a0,p[0][0],pf);
    for (i=0;i<n;i++) min[i]=a0[i]; max=0;
    for (y=0;y<ys;y++)
     for (x=0;x<xs;x++)
        {
        dec_color(a0,p[y][x],pf); // this just unpack pixel color p[][] to a0[4]={r,g,b,a}
        for (q=0,i=0;i<n;i++)
            {
            c=a0[i]; if (c<0) c=-c;
            if (min[i]>c) min[i]=c;
            if (max<c) max=c;
            }
        }
    // change dynamic range to max
    for (y=0;y<ys;y++)
     for (x=0;x<xs;x++)
        {
        dec_color(a0,p[y][x],pf);
        for (i=0;i<n;i++) a0[i]=c0+(((a0[i]-min[i])*(c1-c0))/(max-min[i]+1));
//      for (i=0;i<n;i++) if (a0[i]<c0) a0[i]=c0; // clamp if needed
//      for (i=0;i<n;i++) if (a0[i]>c1) a0[i]=c1; // clamp if needed
        enc_color(a0,p[y][x],pf); // this just pack a0[4]={r,g,b,a} to pixel color p[][]
        }
    }

其中:

  • pf是您的案例pf=_pf_rgba中的当前像素格式,它只是枚举常量
  • xs,ys是图片解析
  • p[y][x]是对图片的直接像素访问
  • enc_color,dec_color只需打包/解包所需像素格式的颜色组件

结果如下:

example

主要思想是找到最小和最大颜色值,然后将此动态范围增强到最大。例如(在灰度颜色上)您的图像具有:

min=181;
max=254;

因此,如果您将每个像素重新调整为最大<0,255>,则需要执行以下操作:

color=(color-min)*255/(max-min);

对于图像的每个像素而言都是。

<强> [注释]

正如@RosaGronchi所说,由于使用了getpixel,setpixel代替扫描线,你当前的方法很慢(应该快几千倍)。

您的方法的另一个缺点是您只是将图像二值化,从而丢失所有渲染的文本消除锯齿...