我有1000页的图书页面,其文字为这件作品
现在我尝试修复它以便更清楚地阅读,我使用此代码
int age = 0;
由于图像尺寸为1168 x 1807,需要花费大量时间才能完成修复,它完全循环2110576次循环。
有没有其他方法可以解决这个问题?感谢。
答案 0 :(得分:2)
我能想到使用内置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);
}
请注意,我泄漏位图;它只是用于测试; - )
答案 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
只需打包/解包所需像素格式的颜色组件结果如下:
主要思想是找到最小和最大颜色值,然后将此动态范围增强到最大。例如(在灰度颜色上)您的图像具有:
min=181;
max=254;
因此,如果您将每个像素重新调整为最大<0,255>
,则需要执行以下操作:
color=(color-min)*255/(max-min);
对于图像的每个像素而言都是。
<强> [注释] 强>
正如@RosaGronchi所说,由于使用了getpixel,setpixel
代替扫描线,你当前的方法很慢(应该快几千倍)。
您的方法的另一个缺点是您只是将图像二值化,从而丢失所有渲染的文本消除锯齿...