代码很搓,就是实验,Delphi我也不是很熟。 (一) 去干扰线 首先,验证码图片是这样子的,28像素高。100像素宽,有干扰线(还与文字同色的),干扰点。随机颜色,随机旋转角度 首先,我尝试去干扰线,通过函数的形式计算破坏红色数字的完整性,我采用遍历单列,如果列里有只有2个红色像素点的话,就变成白色去除红色 判断颜色我使用的是RGB中R的值大于153,就是包括暗红 procedure TForm1.GRedLineBMP(BMP:TBITMAP); var i,j,x,y,co,n:integer; p: PByteArray; begin Bmp.PixelFormat := pf24Bit; randomize; for i := 0 to BMP.Width - 1 do begin for j := 0 to BMP.Height - 1 do begin p := Bmp.scanline[j]; if p[i * 3+2]>=153 then //如果红色值大于153 begin co:=0; for n := 0 to BMP.Height - 1 do begin if Colorflag(BMP.Canvas.Pixels[i, n]) =1 then begin co:=co+1; end; end; if(co<=2) then BMP.Canvas.Pixels[i, j] := clwhite else begin end; end; end; end; end; 效果是这样的 因为我发现随机噪点颜色是固定的,我就提前把噪点颜色给clwhite了 后面这个是因为随机干扰线在文字上方,就不处理了,应该不会有太大影响吧。
(二)图像二色化处理 就是把彩色的图片变成黑白的图片,好识别 采用的那个标准的灰度计算公式 procedure TForm1.BWBMP(BMP:TBITMAP); var x,y,gray:Integer; p: PByteArray; begin Bmp.PixelFormat := pf24Bit; randomize; for y := 0 to BMP.Height - 1 do begin p := Bmp.scanline[y]; for x := 0 to BMP.Width - 1 do begin // Gray := Round((p[x * 3 + 2] + p[x * 3 + 1]+ p[x * 3])/3); Gray := Round(p[x * 3 + 2] * 0.3 + p[x * 3 + 1] * 0.59 + p[x * 3] * 0.11); if gray > 150 then //全局阀值128 begin p[x * 3] := 255; p[x * 3 + 1] := 255; p[x * 3 + 2] := 255; end else begin p[x * 3] := 0; p[x * 3 + 1] := 0; p[x * 3 + 2] := 0; end; end; end; end; 注释部分是RGB平均值分法,我也不知道哪个好一些 变成黑白后,又补洞修复了一下 //补洞 procedure TForm1.BDBMP(BMP1:TBITMAP); var i,j:Integer; begin //补洞 for i := 0 to BMP1.Width - 1 do begin for j := 0 to BMP1.Height - 1 do begin if BMP1.Canvas.Pixels[i, j]=$ffffff then begin if ColorBlackflag(BMP1.Canvas.Pixels[i+1, j])+ ColorBlackflag(BMP1.Canvas.Pixels[i-1, j]) +ColorBlackflag(BMP1.Canvas.Pixels[i, j-1])+ColorBlackflag(BMP1.Canvas.Pixels[i, j+1])=4 then begin BMP1.Canvas.Pixels[i, j]:= clblack; end; end; end; end;end; 就是判断当前白像素点的上下左右是不是全是黑色的,如果是黑的,那就把当前的变成黑的 效果如下
(四)图片旋转,这个我查了一些别人写的经验,好像用X轴投影法,就是把所有有黑色像素点的X轴标记出来,投影到下面成为一条线,计算线长度。然后对图片进行旋转。最短的线就是正立的,当然有些也不是正立的 //计算投影长度 function TForm1.LENGBMP(BMP: TBITMAP):Integer; var x,y,i,len:Integer; xarray:array[0..14] of Integer; begin len:=0; for i := 0 to BMP.Width-1 do xarray[i] := 0; for y := 0 to BMP.Height - 1 do begin for x := 0 to BMP.Width-1 do begin if BMP.Canvas.Pixels[x, y]= clblack then xarray[x]:=xarray[x]+1; end; end; for i := 0 to BMP.Width-1 do if xarray[i] >0 then begin len :=len+1; end; result:=len; end;
(一) 去干扰线
首先,验证码图片是这样子的,28像素高。100像素宽,有干扰线(还与文字同色的),干扰点。随机颜色,随机旋转角度
首先,我尝试去干扰线,通过函数的形式计算破坏红色数字的完整性,我采用遍历单列,如果列里有只有2个红色像素点的话,就变成白色去除红色 判断颜色我使用的是RGB中R的值大于153,就是包括暗红
procedure TForm1.GRedLineBMP(BMP:TBITMAP);
var
i,j,x,y,co,n:integer;
p: PByteArray;
begin
Bmp.PixelFormat := pf24Bit;
randomize;
for i := 0 to BMP.Width - 1 do
begin
for j := 0 to BMP.Height - 1 do
begin
p := Bmp.scanline[j];
if p[i * 3+2]>=153 then //如果红色值大于153
begin
co:=0;
for n := 0 to BMP.Height - 1 do
begin
if Colorflag(BMP.Canvas.Pixels[i, n]) =1 then
begin
co:=co+1;
end;
end;
if(co<=2) then
BMP.Canvas.Pixels[i, j] := clwhite
else
begin
end;
end;
end;
end;
end;
效果是这样的
因为我发现随机噪点颜色是固定的,我就提前把噪点颜色给clwhite了
后面这个是因为随机干扰线在文字上方,就不处理了,应该不会有太大影响吧。
就是把彩色的图片变成黑白的图片,好识别
采用的那个标准的灰度计算公式
procedure TForm1.BWBMP(BMP:TBITMAP);
var
x,y,gray:Integer;
p: PByteArray;
begin
Bmp.PixelFormat := pf24Bit;
randomize;
for y := 0 to BMP.Height - 1 do
begin
p := Bmp.scanline[y];
for x := 0 to BMP.Width - 1 do
begin
// Gray := Round((p[x * 3 + 2] + p[x * 3 + 1]+ p[x * 3])/3);
Gray := Round(p[x * 3 + 2] * 0.3 + p[x * 3 + 1] * 0.59 + p[x
* 3] * 0.11);
if gray > 150 then //全局阀值128
begin
p[x * 3] := 255;
p[x * 3 + 1] := 255;
p[x * 3 + 2] := 255;
end
else
begin
p[x * 3] := 0;
p[x * 3 + 1] := 0;
p[x * 3 + 2] := 0;
end;
end;
end;
end;
注释部分是RGB平均值分法,我也不知道哪个好一些
变成黑白后,又补洞修复了一下
//补洞
procedure TForm1.BDBMP(BMP1:TBITMAP);
var
i,j:Integer;
begin
//补洞
for i := 0 to BMP1.Width - 1 do
begin
for j := 0 to BMP1.Height - 1 do
begin
if BMP1.Canvas.Pixels[i, j]=$ffffff then
begin
if ColorBlackflag(BMP1.Canvas.Pixels[i+1, j])+ ColorBlackflag(BMP1.Canvas.Pixels[i-1, j])
+ColorBlackflag(BMP1.Canvas.Pixels[i, j-1])+ColorBlackflag(BMP1.Canvas.Pixels[i, j+1])=4 then
begin
BMP1.Canvas.Pixels[i, j]:= clblack;
end;
end;
end;
end;end;
就是判断当前白像素点的上下左右是不是全是黑色的,如果是黑的,那就把当前的变成黑的
效果如下
BitBlt(bits[i].Canvas.Handle, 0, 0, 15, 28, BMP.Canvas.Handle, 5+i*15, 0, SRCCOPY);
具体代码不上了,我写的太烂,我都不知道会不会内存泄露,就不误导了。
//计算投影长度
function TForm1.LENGBMP(BMP: TBITMAP):Integer;
var
x,y,i,len:Integer;
xarray:array[0..14] of Integer;
begin
len:=0;
for i := 0 to BMP.Width-1 do
xarray[i] := 0;
for y := 0 to BMP.Height - 1 do
begin
for x := 0 to BMP.Width-1 do
begin
if BMP.Canvas.Pixels[x, y]= clblack then
xarray[x]:=xarray[x]+1;
end;
end;
for i := 0 to BMP.Width-1 do
if xarray[i] >0 then
begin
len :=len+1;
end;
result:=len;
end;
//获得旋转角度的BMP
// x,y:质心坐标数组
//angle 旋转角度
//x2,y2 新坐标点
// x2=(x - x1) * Cos(angle * 3.14 / 180) - (y - y1) * Sin(angle * 3.14 / 180) + x1
// y2=(y - y1) * Cos(angle * 3.14 / 180) + (x - x1) * Sin(angle * 3.14 / 180) + y1
通过正负30度旋转,就变成了这个挫样