首页
社区
课程
招聘
[原创]游戏中的图片识别,OCR一般性方法。
发表于: 2013-9-20 15:52 28241

[原创]游戏中的图片识别,OCR一般性方法。

2013-9-20 15:52
28241

除了汉字,需要制作太多的模版,字母和数字,都是可以的。

OCR的,一般性方法。

灰度处理---中值滤波---细化---平滑---然后模版比对覆盖率




灰度处理
//计算数量
  m:=0;
  for y:=0 to FHeight -1 do
    for x:=0 to FHeight -1 do
    begin
      r :=((Buf[y*FHeight+x] and $F800) shr 11) * 256   div   32;
      g :=((Buf[y*FHeight+x] and $07E0) shr 5)  * 256   div   64;
      b :=( Buf[y*FHeight+x] and $001F) * 256   div   32;
      //灰度算法一
      n:=0.212671*R   +   0.715160*G   +   0.072169*B ;
      //灰度算法二  随便哪个算法结果似乎都一样。
      //n:=0.114*R   +   0.587*G   +   0.299*B ;
      if n>k  then m:=m+1;
    end;

平滑
procedure TPictureTools.SmothPixel(X,Y:integer);
var
A:Array[0..2,0..2] of Integer;
Z:integer;
i,J:integer;
N:integer;
begin
   A[0,0] := 1; A[0,1] := 2; A[0,2] := 1;
   A[1,0] := 2; A[1,1] := 4; A[1,2] := 2;
   A[2,0] := 1; A[2,1] := 2; A[2,2] := 1;
   z := 16;
   N:=0;
   For I:=-1 to 1 do
   begin
        For J:=-1 to 1 do
        if Self.GetPixel(X+J,Y+I)=ForeGroundPoint then
        begin
           N:=N+A[I+1,J+1];
        end;
   end;
   if N<8 then Self.setPixel(X,Y);
end;

细化
procedure TPicturetools.InterThin;
var
   X, Y: integer;
   nb: array[1..3, 1..3] of byte;
   c1, c2, c3, c4: boolean;
   ncount: integer;
begin
   for X:= 1 to FWidth - 2 do
   begin
      for Y := 1 to FHeight - 2 do
      begin
         if Self.GetPixel(X,Y)=BackGroundPoint then Continue;
         c1 := false;
         c2 := false;
         c3 := false;
         c4 := false;
         // 设立四个条件的初始值
         nb[1, 1] := self.GetPixel(X-1,Y-1);
         nb[1, 2] := self.GetPixel(X-1,Y);
         nb[1, 3] := self.GetPixel(X-1,Y+1);
         nb[2, 1] := self.GetPixel(X,Y-1);
         nb[2, 2] := self.GetPixel(X,Y);
         nb[2, 3] := self.GetPixel(X,Y+1);
         nb[3, 1] := self.GetPixel(X+1,Y-1);
         nb[3, 2] := self.GetPixel(X+1,Y);
         nb[3, 3] := self.GetPixel(X+1,Y+1);
         //将[x,y]周围的八个象素点和它自己0-1化
         nCount := nb[1, 1] + nb[1, 2] + nb[1, 3]
            + nb[2, 1] + nb[2, 3]
            + nb[3, 1] + nb[3, 2] + nb[3, 3];
         // 获得ncount的值
         if (ncount >= 2) and (ncount <= 6) then
            c1 := True;
         //condition1
         ncount := 0;
         if (nb[1, 1] = 0) and (nb[1, 2] = 1) then
            inc(ncount);
         if (nb[1, 2] = 0) and (nb[1, 3] = 1) then
            inc(ncount);
         if (nb[1, 3] = 0) and (nb[2, 3] = 1) then
            inc(ncount);
         if (nb[2, 3] = 0) and (nb[3, 3] = 1) then
            inc(ncount);
         if (nb[3, 3] = 0) and (nb[3, 2] = 1) then
            inc(ncount);
         if (nb[3, 2] = 0) and (nb[3, 1] = 1) then
            inc(ncount);
         if (nb[3, 1] = 0) and (nb[2, 1] = 1) then
            inc(ncount);
         if (nb[2, 1] = 0) and (nb[1, 1] = 1) then
            inc(ncount);
         if ncount = 1 then
            c2 := true;
         //condition2
         if (nb[1, 2] * nb[3, 2] * nb[2, 3] = 0) then
            c3 := true;
         // condition3
         if (nb[2, 1] * nb[2, 3] * nb[3, 2] = 0) then
            c4 := true;
         //condition4
         if (c1 and c2 and c3 and c4) then
         begin
            self.SetPixel(X,y)
            //设置O[X]为白色
         end;
      end;
   end;
end;

procedure TPictureTools.RotateByAngle(Angle:integer);
var
C1x,C1Y,P1x,P1y:integer;
C2x,C2y,P2x,P2y:integer;
N:integer;
Bx,BY:integer;
NewPic:Array of Array of Byte;
R,alpha,Beta:real;
V1,V2,V3,V4:byte;
begin
    N:=Max(FWidth,Fheight);
    setlength(NewPic,N,N);
    for P2x:=0 to N-1 do
    for P2y:=0 to N-1 do
    Newpic[p2x,p2y]:=BackGRoundPoint;
//    FillMemory(Newpic[0],N*N,1);
    Beta:=Angle * PI / 180;
    C1x:=Fwidth div 2;
    C1y:=FHeight div 2;
    C2x:=N div 2;
    C2y:=N div 2;
    N:=Max(C2x,C2y);
    dec(N);
    for P2x:=0 to N do
    begin
        for P2y:=0 to N do
        begin
            if p2x = 0 then alpha := pi / 2
            else  alpha := arctan2(p2y,p2x);
            R := sqrt(sqr(p2x) + sqr(p2y));
            p1x := round(R * cos(Beta + alpha));
            p1y := round(R * sin(Beta + alpha));
            V1 := self.GetPixel(c1x + p1x, c1y + p1y);
            V2 := self.GetPixel(c1x - p1x, c1y - p1y);
            V3 := self.GetPixel(c1x + p1y, c1y - p1x);
            V4 := self.GetPixel(c1x - p1y, c1y + p1x);

            Newpic[c2x + p2x, c2y + p2y]:= V1;
            NewPic[c2x - p2x, c2y - p2y]:= V2;
            NewPic[c2x + p2y, c2y - p2x]:= V3;
            Newpic[c2x - p2y, c2y + p2x]:= V4;

        end;
    end;
    Bx:=C2x-(FWidth div 2);
    By:=C2Y-(Fheight div 2);
    for P1x:=1 to Fwidth-2 do
    begin
        for P1y:=1 to Fheight-2 do
        begin
            setvalue(P1x,P1y,Newpic[Bx+P1x,By+P1y]);
        end;
    end;
end;

中值滤波
procedure TPictureTools.FilterPixel(x,y,Num:integer;T:integer=2);
var
N,i,j:integer;
begin
    if (Y<=1) or (X<=1) or(X>=FWidth-2) or (Y>=Fheight-2) then
    begin
        SetPixel(X,Y);
        exit;
    end;
    N:=0;
    for I:=X-NUM to X+NUM do
    begin
        for J:=Y-NUM to Y+NUM do
        begin
            if Self.GetPixel(I,J)=ForeGroundPoint then inc(N);
        end;
    end;
    if N<(sqr(2*NUM+1) div (T*Num)) then SetPixel(X,Y)
//    else setPixel(x,Y);
end;

//矫正
procedure TpictureTools.Rectifer;
var
Bak:PByte;
V1,V2:integer;
D1,D2,D3:integer;
begin
    //保存原图象的副本
    GetMem(Bak,FMemSize);
    copyMemory(bak,FPoints,FMemSize);

    GetDataV(V1,V2);
    D1:=V2-V1;
    if D1>DataWidthKey then
    begin
         CopyMemory(Fpoints,Bak,FMemSize);
         RotateByAngle(MinAngle);
         GetDataV(V1,V2);
         D2:=V2-V1;
         if (D2>D1) then
         begin
                CopyMemory(Fpoints,Bak,FMemSize);
                RotateByAngle(-1*MinAngle);
                GetDataV(V1,V2);
                D3:=V2-V1;
                if D3<=DataWidthKey then
                begin
                    FreeMem(Bak);
                    exit;
                end;
         end
         else   begin
                    FreeMem(Bak);
                    exit;
                end;
    end;
    FreeMem(Bak);
end;

最后,根据覆盖率,识别。
function COCR.GetFuGaiLv (x,y,ModeIdx,N:integer):single;
var
  i,j,k,M : integer;
begin
  result :=0; k:=0; M:=0;
  for i:=0 to MinLetterHeight -1 do
    for j:=0 to MinLetterWidth -1 do
    begin
      if (x+j)>=MinLetterWidth*(N+1) then continue;
      if (y+i)>=MinLetterHeight  then continue;
      m:=M+1;
      if (PicMode[ModeIdx].buf[i*MinLetterWidth+j]=SrcPicBuf[(y+i)*FWidth+(x+j)]) then
        //and (SrcPicBuf[(y+i)*FWidth+(x+j)]=ForeGroundPoint) then
        k:=k+1;
    end;
  //result :=k / PicMode[ModeIdx].ForePointNum ;
  result :=k / m ;
end;

//识别算法
function COCR.GetLetter(N : integer;Memo: TMemo;Edit:TEdit) :string;
var
  k :integer ;
  Flv,MaxFlv : single;
begin
  result :='9' ;
  MaxFlv :=0;
  Memo.Lines.Add('====='+inttostr(N)+'=====');
  Edit.Color :=clRed;
      for k:=0 to nPicMode -1 do
      begin
        Flv :=GetFuGaiLv(N*MinLetterWidth,0,k,N);
        if (Flv>MaxFlv) and (FLV>0.8) then
        begin
          MaxFlv :=Flv ;

          result :=PicMode[k].Letter ;
          Memo.Lines.Add(format('L=%s,Flv=%.2f,K=%d',[result,Flv,k]));
          if Flv>0.995 then
            Edit.Color :=clWindow ;
        end;
      end;

end;


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 5
支持
分享
最新回复 (53)
雪    币: 49
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
呵呵,第一次坐沙发,庆贺一下

也感激一下楼主能发出这么好的文章!!
2013-9-20 15:59
0
雪    币: 257
活跃值: (67)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
谢谢分享,来看看
2013-9-20 16:10
0
雪    币: 6
活跃值: (1156)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2013-9-20 16:14
0
雪    币: 219
活跃值: (793)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
5
顶这个是必须的
2013-9-20 16:54
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
谢谢分享,来看看
2013-9-20 17:06
0
雪    币: 114
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
这个不错,支持。
2013-9-20 17:09
0
雪    币: 212
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
果断MARK支持楼主!
2013-9-20 21:35
0
雪    币: 231
活跃值: (2631)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
9
这个值得顶
2013-9-20 22:46
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
10
这个不错,顶楼主
2013-9-20 23:22
0
雪    币: 47147
活跃值: (20485)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
11
fosom答应晚上写些理论上的东西上来,太期待了~
2013-9-22 09:48
0
雪    币: 1839
活跃值: (295)
能力值: ( LV9,RANK:370 )
在线值:
发帖
回帖
粉丝
12
语言组织能力比较差,不过,晚上会详细写的过程的。

今天加班,没时间,郁闷。
2013-9-22 09:55
0
雪    币: 1711
活跃值: (516)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
13
所以现在验证码都做得人也识别不出来~
2013-9-22 10:18
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
学习且关注,感谢楼主。
2013-9-22 10:47
0
雪    币: 351
活跃值: (80)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
15
《数字图像处理》参考
2013-9-22 11:06
0
雪    币: 1906
活跃值: (712)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
源码是否可以分享,谢谢
2013-9-22 12:13
0
雪    币: 193
活跃值: (26)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
17
标志一下
2013-9-22 16:28
0
雪    币: 19
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
mark 验证识别码 thx.
2013-9-22 16:32
0
雪    币: 43
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
不错不错,一些基本操作可以用opencv实现,更成熟强大。opencv处理好了直接用tesseract,设置一下识别范围,效果也还可以。不过要达到一个精度还是需要下点功夫的。
2013-9-22 16:57
0
雪    币: 143
活跃值: (263)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
20
楼主是ps高手,原来也熟悉图像算法
2013-9-22 19:43
0
雪    币: 141
活跃值: (162)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
mark
2013-9-22 21:10
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
22
期待............数字图象处理   验证码 OCR
2013-9-22 21:14
0
雪    币: 56
活跃值: (242)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
支持一下~~
2013-9-22 21:19
0
雪    币: 225
活跃值: (195)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
这个不错。值 得学习
2013-9-22 21:47
0
雪    币: 245
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
谢谢楼主分享
2013-9-22 22:04
0
游客
登录 | 注册 方可回帖
返回
//