C# 如何修复书页的暗显图像
我有1000张书页的图片,它的文字和这张一样暗淡C# 如何修复书页的暗显图像,c#,image-processing,C#,Image Processing,我有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 < bmp.Heig
现在我试图修复它,以便更清晰地阅读,我使用此代码
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 < bmp.Height; y++)
{
if (bmp.GetPixel(x, y).R>238)
{
bmp.SetPixel(x, y, Color.White);
}
else
{
bmp.SetPixel(x, y, Color.Black);
}
}
}
return bmp;
}
私有位图图像(位图bmp)
{
Color cc=Color.FromArgb(255,251,251,251);
对于(int x=0;x238)
{
bmp.SetPixel(x,y,Color.White);
}
其他的
{
bmp.SetPixel(x,y,Color.Black);
}
}
}
返回bmp;
}
由于图像尺寸为1168 x 1807,因此需要花费大量时间来完成修复,它正好循环2110576个循环。还有别的办法解决这个问题吗?谢谢。我使用这个(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[][]
}
}
因此,如果您选取每个像素并重新缩放到最大值,则需要执行以下操作:
color=(color-min)*255/(max-min);
对于图像的每个像素,仅此而已
[Notes]
正如@RosaGronchi提到的,由于使用了getpixel,您当前的方法速度很慢,setpixel
使用扫描线(应该快几千倍)
- 看
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[][]
}
}
因此,如果您选取每个像素并重新缩放到最大值,则需要执行以下操作:
color=(color-min)*255/(max-min);
对于图像的每个像素,仅此而已
[Notes]
正如@RosaGronchi提到的,由于使用了getpixel,您当前的方法速度很慢,setpixel
使用扫描线(应该快几千倍)
- 看
您的方法的另一个缺点是,您只需对图像进行二值化,从而使所有渲染的文本消除混叠…我所能想到的最好方法是使用内置类来更改图像的Gamma和对比度 以下是
Gamma=6.27
和对比度=+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;
}
该函数使用两个变量和两个轨迹栏
,以及两个标签
:
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);
}
请注意,我正在泄漏位图;只是为了测试;-) 我能想到的最好方法是使用内置类来更改图像的Gamma和对比度 以下是
Gamma=6.27
和对比度=+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;
}
该函数使用两个变量和两个轨迹栏
,以及两个标签
:
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);
}
请注意,我正在泄漏位图;只是为了测试;-) 看这里:(避免对每个像素使用GetPixel()和SetPixel())查找gamma和ColorMatrix!请参见,特别是指南的链接!看这里:(避免对每个像素使用GetPixel()和SetPixel())查找gamma和ColorMatrix!请参见,特别是指南的链接!对我来说,这应该快几千倍,听起来相当乐观。@TaW如果编码正确,一点也不。。。每个
setpixel
或getpixel
都会调用许多GDI调用,检查边界、像素格式、覆盖以及更多。。。ScanLine
属性也会执行此操作,但每行仅执行一次,如果记住,则每幅图像每行仅执行一次/resize,并且可以在。。。在重像素访问上,通常的速度提升约为10000x
次(例如在SW 3D渲染或填充算法上)。。。但必须正确编码…上次我压缩锁位和get/setPixel的速度快了20倍。很多,但决不是几千。。但这和你的代码不一样,我想。@Taw这取决于你实际使用了多少getpiel
,setpixel
而不是直接像素访问。。。与其他GDI呼叫的数量相反。如果你所指的getpixel
,setpixel
不是GDI,那就完全是另一个话题了。我比较了使用C#angainst LockBits的GDI+Get/setpixel。这应该快几千倍,这对我来说听起来相当乐观。@TaW如果编码正确,一点也不。。。每个setpixel
或getpixel
都会调用许多GDI调用,检查边界、像素格式、覆盖以及更多。。。ScanLine
属性也会执行此操作,但每行仅执行一次,如果记住,则每幅图像每行仅执行一次/resize,并且可以在。。。在重像素访问上,通常的速度提升约为10000x
次(例如在SW 3D渲染或填充算法上)。。。但必须正确编码…上次我压缩锁位和get/setPixel的速度快了20倍。很多,但决不是几千。。但这和你的代码不一样,我想。@Taw这取决于你实际使用了多少getpiel
,setpixel
而不是直接像素访问。。。与其他GDI呼叫的数量相反。如果您所指的getpixel
,setpixel
不是GDI,那么这完全是另一个话题。我比较了使用GDI+Get/setpixel from C#angainst LockBits。