如何修复书页的灰暗图像
我有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.27
和Contrast = +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[]
您的方法的另一个缺点是您只是将图像二值化,从而丢失所有渲染的文本抗锯齿…