如何修复书页的灰暗图像

我有1000页的图书页面,它的文字像这一块一样暗淡 灰暗的文字
现在我尝试修复它以便更清楚地阅读,我使用此代码

private Bitmap repairImage(Bitmap bmp) { Color cc=Color.FromArgb(255, 251, 251, 251); for (int x = 0; x < bmp.Width; x++) { for (int y = 0; y 238) { bmp.SetPixel(x, y, Color.White); } else { bmp.SetPixel(x, y, Color.Black); } } } return bmp; } 

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

我可以想到使用内置的ColorMatrix类来改变图像的Gamma对比度的最好方法。

这是Gamma = 6.27Contrast = +1.04

在此处输入图像描述

这是我使用的代码:

 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); } 

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

我用这个(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;ic) min[i]=c; if (maxc1) 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只需打包/解包所需像素格式的颜色分量

这是结果:

例

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

 min=181; max=254; 

因此,如果你拍摄每个像素并重新缩放到最大<0,255>你需要做类似的事情:

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

对于图像的每个像素,这就是全部。

[笔记]

正如@RosaGronchi所提到的,由于使用了getpixel,你当前的方法很慢,而getpixel,setpixel使用的是scanlines(应该快几千倍)。

  • 看GDI Bitmap和ScanLine[]

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