分享

Delphi识别读取验证码 转

 quasiceo 2015-07-15
 http://bbs.csdn.net/topics/390099267?list=lz
小弟水平低,代码写的很乱,请谅解
需用到calcexprress,pngimage和gifimage,这里不再提供!

unit OCR;

interface

uses Windows, SysUtils, Graphics, Classes, PNGImage, GIFImage, JPEG, Math, AsphyreZlib;

type
  TOCRLibSetting = record  //验证码库设置
    SaveBMP: Boolean; //存储转换后的Bmp文件
    BmpPath: String; //Bmp存储路径
    BmpPrefix: String; //Bmp文件前缀
    BmpSuffix: String; //Bmp文件后缀
  end;

type
  //图像大小类
  TOCRSz = record
    W,H: Byte;   //宽,高
  end;
  //特征码模板库类
  TOCRTemplates = record
    Count: Byte;    //数量
    Names: array of String; //名称
    OCRFiles: array of String; //文件名/路径
    OCRSz: array of TOCRSz; //图像大小
    YaoqiuSS: array of Byte;  //是否为算式
  end;

//初始化验证码库
function InitOCRLib: Boolean;
//取消使用Dll
procedure CancelUseDLL;
//加载验证码模板库
function LoadOCRLib(const AFileName: String = ''): Boolean;
//图像转换为BMP
function ALL2BMP(const Filename : String; const Bmp: TBitmap): Boolean;
//加载资源dll
function LoadOCRResourceDLL(const ADllName: String): Boolean;
//识别验证码
function RecogOCR(var Success: Boolean; const ImageFile: String): String;
//更改特征码模板
function LoadOCRTemplate(const TmplID: Integer): Boolean;
//加载特征码文件
function LoadOCRFile(const ocrFile: String; const IsAutoSS: Boolean = False): Boolean;
//查找验证码特征文件
function FetchOCR(const StartIndex: Integer; const Width,Height: Integer; const AOCRName: String = ''): Integer;
//验证码库设置
function SetOCRLib(const ASetting: TOCRLibSetting): Boolean;
//获得验证码库设置
function GetOCRLibSetting: TOCRLibSetting;
//获得验证码模板库
function GetOCRTemplates: TOCRTemplates;
//获取最后识别时间(毫秒)
function GetLastRecogTime: DWORD;
//调用AspriseOcr
//function RecogOCRByOCRLib(const FileName: String): String;
//释放验证码库/清除特征码文件
function FreeOcr: Boolean;

//procedure SetPicFormat(Format: Byte);

const
  FMT_AUTO = 4; //自动
  FMT_PNG = 2; //png
  FMT_BMP = 1; //bmp
  FMT_GIF = 3; //gif
  FMT_JPEG = 0; //jpg/jpeg

implementation

uses IniFiles, SSUtils;

type
  RSpeicalEffects = record  //特殊效果
    To1Line: Boolean;   //字符归位
    RemoveZD: Boolean;  //消除噪点
    Y0: Byte;           //Y轴偏移
    XcZD: Byte;         //噪点阀值
  end;

type //字符特征码
  RChar = record
    MyChar: char;          //字符
    used: Boolean;         //已使用
    MyCharInfo: array[0..49, 0..49] of byte;  //字符图像
  end;

type //字符特征文件
  RCharInfo = record
    charwidth: byte; //字符宽度
    charheight: byte; //字符高度
    X0: byte; //第一个字符开始x偏移
    TotalChars: byte; //图象字符总数
    CusDiv : boolean;  //自定义二值化运算
    DivCmp : Byte; //  0:>  1:=  2:<
    DivColr : TColor;  //二值化阀值
    _CmpChr,_CmpBg: Boolean;  //比较字符(黑色),比较背景(白色)
    _ClrRect: Boolean;   //清除矩形
    _RectLen: Byte;     //矩形长度

    allcharinfo: array[0..42] of RChar; //字符特征码列表
  end;

type
  TOcrVersionSng = array [0..1] of Byte;
  TOcrVersion = record    //版本号
    First,Minjor: Byte;   //版本
    Author: String[10];   //作者
    Name: String[20];     //特征码名称
  end;

  ROcrLibFile = record
    Sng: TOcrVersionSng;  //版本标识
    Ver: TOcrVersion;     //版本
    W,H: Byte;            //图像宽,高
    Effect: RSpeicalEffects;  //特殊效果
    CharInfo: RCharInfo;     //特征码
    EffectBLW: Boolean;     //通用二值化
  end;

  TOcrLibDllInfo = record
    DllFile: String;
    MDLRPrefix: String;
    MDLRType: String;
  end;

var
  _BITMAP: TBitmap;  //识别图像
  MycharInfo: RCharInfo; //特征码
  _Effect: RSpeicalEffects;  //特效
  _EffBLW: Boolean;  //通用二值化
  SSCode: Byte;   //是否为算式

var
  BmW,BmH: Integer;  //特征码图像宽,高
  OcrName: String;  //特征码名称
  _PicFormat: Byte; //图像格式
  _PicWidth,_PicHeight: Byte; //实际图像宽,高
  Templates: TOCRTemplates; //模板列表
  Setting: TOCRLibSetting;
  LastRecogTime: DWORD;

var
  UseDll: Boolean;
  DllInfo: TOcrLibDllInfo;

const
  SP = '@';

procedure CancelUseDLL;
begin
  UseDll := False;
end;

function GetLastRecogTime: DWORD;
begin
  Result := LastRecogTime;
end;

function GetOCRLibSetting: TOCRLibSetting;
begin
  Result := Setting;
end;

function GetOCRTemplates: TOCRTemplates;
begin
  Result := Templates;
end;

function LoadOCRResourceDLL(const ADllName: String): Boolean;
var
  strm: TResourceStream;
  hDll: THandle;
  S: String;
  function GetTempPathFileName: String;
  var
    SPath, SFile : PChar;
  begin
    SPath := AllocMem(MAX_PATH);
    SFile := AllocMem(MAX_PATH);
    GetTempPath(MAX_PATH, SPath);
    GetTempFileName(SPath, '~OC', 0, SFile);
    Result := String(SFile);
    FreeMem(SPath, MAX_PATH);
    FreeMem(SFile, MAX_PATH);
    DeleteFile(Result);
  end;
begin
  Result := False;
  try
    hDll := LoadLibrary(PChar(ADllName));
    if hDll <> 0 then
    begin
      try
        strm := TResourceStream.Create(hDll,
          'SDSOFT_OCR',
          PChar('OCR'));

        S := GetTempPathFileName;
        strm.SaveToFile(S);
        try
          UseDll := True;
          Result := LoadOCRLib(S);
        except
          UseDll := False;
        end;
        if Result = False then UseDll := False;
        if UseDll = True then DllInfo.DllFile := ADllName;

        DeleteFile(S);
      finally
        FreeLibrary(hDll);
      end;
    end;
    Result := True;
  except
  end;
end;

function SetOCRLib(const ASetting: TOCRLibSetting): Boolean;
begin
  Result := False;
  try
    Setting := ASetting;
    Result := True;
  except
  end;
end;

function InitOCRLib: Boolean;
begin
  Result := False;
  try
    UseDll := False;
    DllInfo.DllFile := '';
    DllInfo.MDLRPrefix := '';
    DllInfo.MDLRType := '';

    _BITMAP := nil;
    FillChar(MycharInfo,SizeOf(RCharInfo),#0);
    MycharInfo.DivCmp := 3;
    MycharInfo.DivColr := $7FFFFF;
    MycharInfo._CmpChr := True;
    MycharInfo._CmpBg := False;
    MycharInfo.X0 := 0;
    MycharInfo.charwidth := 0;
    MycharInfo.CusDiv := False;
    MycharInfo.charheight := 0;
    FillChar(_Effect,SizeOf(RSpeicalEffects),#0);
    _Effect.To1Line := False;
    _Effect.RemoveZD := False;
    Setting.SaveBMP := False;
    Setting.BmpPrefix := 'OCR';
    Setting.BmpSuffix := '';
    LastRecogTime := 0;
  except
  end;
end;

function FetchOCR(const StartIndex: Integer; const Width,Height: Integer; const AOCRName: String = ''): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := StartIndex to Integer(Templates.Count) - 1 do
  begin
    if (Templates.Names[I] = AOCRName) or
         ((Templates.OCRSz[I].W = Width) and (Templates.OCRSz[I].H = Height))
           then
    begin
      Result := I;
      Break;
    end;
  end;
end;

function LoadOCRLib(const AFileName: String = ''): Boolean;
var
  Ini: TIniFile;
  S,S2: String;
  I,J: Integer;

  FileName: String;
begin
  Result := False;
  FileName := AFileName;
  if FileName = '' then
    FileName := ExtractFilePath(ParamStr(0))+'OCR.INI';
  try
    Templates.Count := 0;
    SetLength(Templates.Names,0);
    SetLength(Templates.OCRFiles,0);
    Ini := TIniFile.Create(FileName);
    Templates.Count := Byte(Ini.ReadInteger('OCRLIB','TCNT',0));
    SetLength(Templates.Names,Templates.Count*SizeOf(String));
    SetLength(Templates.OCRFiles,Templates.Count*SizeOf(String));
    SetLength(Templates.OCRSz,Templates.Count*SizeOf(TOCRSz));
    SetLength(Templates.YaoqiuSS,Templates.Count*SizeOf(Byte));
    for I := 0 to Templates.Count - 1 do
    begin
      S := Ini.ReadString('OCRLIB','T'+IntToStr(I),'');
      if S <> '' then
      begin
        J := Pos(';',S);
        S2 := Copy(S,1,J-1);
        S := Copy(S,J+1,Length(S)-J+1);
        if UseDll then Templates.OCRFiles[I] := S2
        else Templates.OCRFiles[I] := ExtractFilePath(ParamStr(0))+S2;
        J := Pos(';',S);
        S2 := Copy(S,1,J-1);
        S := Copy(S,J+1,Length(S)-J+1);
        Templates.OCRSz[I].W := Byte(StrToInt(S2));
        J := Pos(';',S);
        S2 := Copy(S,1,J-1);
        S := Copy(S,J+1,Length(S)-J+1);
        Templates.OCRSz[I].H := Byte(StrToInt(S2));
        Templates.YaoqiuSS[I] := Byte(StrToInt(S));
        Templates.Names[I] := Ini.ReadString('OCRNAME','T'+IntToStr(I),'');
      end;
    end;
    if UseDll = True then
    begin
      DllInfo.MDLRPrefix := Ini.ReadString('DLLSETTING','Prefix','');
      DllInfo.MDLRType := Ini.ReadString('DLLSETTING','ResourceType','OCR');
    end;
    Ini.Free;
    Result := True;
  except
  end;
end;

function LoadOCRFile(const ocrFile: String; const IsAutoSS: Boolean = False): Boolean;
var
  Fstrm: TFileStream;
  strm: TMemoryStream;
  dat: ROcrLibFile;
  function VersVerify: Boolean;
  begin
    Result := (dat.Sng[0] = Byte('O')) and (dat.Sng[1] = Byte('C'));
  end;
begin
  Result := False;
  try
    Fstrm := TFileStream.Create(ocrFile,fmOpenRead);
    strm := TMemoryStream.Create;
    try
      Fstrm.Position := 0;
      ZDecompressStream(FStrm,strm);
      Fstrm.Free;

      strm.Position := 0;
      strm.Read(dat,SizeOf(ROcrLibFile));
      if VersVerify = True then
      begin
        MycharInfo := dat.CharInfo;
        _Effect := dat.Effect;
        BmW := dat.W;
        BmH := dat.H;
        OcrName := dat.Ver.Name;
        _EffBLW := dat.EffectBLW;
        Result := True;
      end;
    finally
      strm.Free;
    end;
    if IsAutoSS = True then SSCode := 1
    else SSCode := 0;
  except
  end;
end;
//////////////

procedure To1Line(const Bmp: TBitmap; Y0,X0,Chw,CharL: Byte);
type
  xByteArray = array of Byte;
var
  X,Y: Integer;
  Ch: TBitmap;
  MinJL: xByteArray;
  function MinArr(const Data: xByteArray; const Count: Integer): Byte;
  var
    I: Integer;
  begin
    if Count = 0 then Exit;
    Result := Data[0];
    for I := 0 to Count - 1 do
    begin
      if Data[I] < Result then Result := Data[I];
    end;
  end;
  procedure GetMinJL(const nChar: Byte);
  var
    K,L,M: Byte;
    c: TColor;
    MinJLS: xByteArray;
  begin
    K := X0 + nChar * Chw;
    SetLength(MinJLS,Chw);
    for L := 0 to Chw - 1 do
    begin
      M := 0;
      c := Bmp.Canvas.Pixels[K+L,M+Y0];
      while (c <> clBlack) and (M <= Bmp.Height) do
      begin
        inc(M);
        c := Bmp.Canvas.Pixels[K+L,M+Y0];
      end;
      MinJLS[L] := M;
    end;
    MinJL[nChar] := MinArr(MinJLS,Chw);
    SetLength(MinJLS,0);
  end;
begin
  SetLength(MinJL,CharL);
  Ch := TBitmap.Create;
  for X := 0 to CharL - 1 do
  begin
    GetMinJL(X);
    Y := X0 + X * Chw;

    Ch.Width := Chw;
    Ch.Height := Bmp.Height - MinJL[X];
    Ch.Canvas.Brush.Color := clWhite;
    Ch.Canvas.Brush.Style := bsSolid;
    Ch.Canvas.Pen.Color := clWhite;
    Ch.Canvas.Pen.Style := psSolid;
    Ch.Canvas.Rectangle(0,0,Ch.Width,Ch.Height);
    Ch.Canvas.CopyRect(Rect(0,0,Ch.Width,Ch.Height),Bmp.Canvas,Rect(Y,MinJL[X],Y+Chw,Bmp.Height));

    Bmp.Canvas.Brush.Color := clWhite;
    Bmp.Canvas.Brush.Style := bsSolid;
    Bmp.Canvas.Pen.Color := clWhite;
    Bmp.Canvas.Pen.Style := psSolid;
    Bmp.Canvas.Rectangle(Y,MinJL[X],Y+Chw,Bmp.Height);
    Bmp.Canvas.CopyRect(Rect(Y,Y0,Y+Chw,Bmp.Height-MinJL[X]),Ch.Canvas,Rect(0,0,Ch.Width,Ch.Height));
  end;
  Ch.Free;
  SetLength(MinJL,0);
end;

function GetTail(str,sp : String): Integer;
var
  Temp : String;
begin
  Temp := Str;
  Delete(Temp,1,Pos(sp,str)+length(sp)-1);
  Result := StrToInt(Temp);
end;

procedure SlQuickSort(Sl : TStringList; iLo, iHi: Integer);
var
  Lo, Hi, Mid : Integer;
  T : String;
begin
  Lo := iLo;
  Hi := iHi;
  Mid := GetTail(Sl[(Lo + Hi) div 2],Sp);
  repeat
    while GetTail(Sl[Lo],Sp) < Mid do Inc(Lo);
    while GetTail(Sl[Hi],Sp) > Mid do Dec(Hi);
    if Lo <= Hi then
    begin
      T := sl[Lo];
      sl[Lo] := sl[Hi];
      sl[Hi] := T;
      Inc(Lo);
      Dec(Hi);
    end;
  until Lo > Hi;
  if Hi > iLo then SlQuickSort(Sl, iLo, Hi);
  if Lo < iHi then SlQuickSort(Sl, Lo, iHi);
end;

Function HexToInt(Hex :String):Int64;
Var Sum : Int64;
    I,L : Integer;
Begin
  L := Length(Hex);
  Sum := 0;
  For I := 1 to L Do
   Begin
   Sum := Sum * 16;
   If ( Ord(Hex[I]) >= Ord('0')) and (Ord(Hex[I]) <= Ord('9')) then
      Sum := Sum + Ord(Hex[I]) - Ord('0')
   else If ( Ord(Hex[I]) >= Ord('A') ) and (Ord(Hex[I]) <= Ord('F')) then
      Sum := Sum + Ord(Hex[I]) - Ord('A') + 10
   else If ( Ord(Hex[I]) >= Ord('a') ) and ( Ord(Hex[I]) <= Ord('f')) then
      Sum := Sum + Ord(Hex[I]) - Ord('a') + 10
   else
      Begin
      Sum := -1;
      break;
      End;
   End;
  Result := Sum;
End;

function GetHead(str,sp : String):string;
begin
  Result:=copy(str,1,pos(sp,str)-1);
end;

procedure WhiteBlackImgEx(const bmp: TBitmap);
type
  xByteArray = array of Byte;
var
  p: PByteArray;
  J,Y,W: Integer;
  arr: xByteArray;
  function AverageArr(const Data: xByteArray; const Count: Integer): Int64;
  var
    I: Integer;
  begin
    Result := 0;
    if Count = 0 then Exit;
    for I := 0 to Count - 1 do
    begin
      Result := Result + Data[I];
    end;
    Result := Round(Result/Count);
  end;
begin
  bmp.PixelFormat := pf24bit;
  SetLength(arr,bmp.Height*bmp.Width);
  for Y := 0 to bmp.Height - 1 do
  begin
    p := bmp.ScanLine[Y];
    J := 0;
    while J < bmp.Width*3 do
    begin
      arr[(Y*bmp.Width)+J div 3] := Round((p[J]+p[J+1]+p[J+2])/3);
      Inc(J,3);
    end;
  end;
  W := Byte(AverageArr(Arr,bmp.Height*bmp.Width));
  for Y := 0 to bmp.Height - 1 do
  begin
    p := bmp.ScanLine[Y];
    J := 0;
    while J < bmp.Width*3 do
    begin
      if Round((p[J]+p[J+1]+p[J+2])/3) >= W then
      begin
        p[J] := 0;
        p[J+1] := 0;
        p[J+2] := 0;
      end else
      begin
        p[J] := MaxByte;
        p[J+1] := MaxByte;
        p[J+2] := MaxByte;
      end;
      Inc(J,3);
    end;
  end;
  SetLength(Arr,0);
end;

procedure Ranse(const bmp: TBitmap; const Color: TColor);
var
  c: TColor;
  X,Y: Integer;
  r1,g1,b1: Byte;
  r2,g2,b2: Byte;
begin
  r1 := GetRValue(Color);
  g1 := GetGValue(Color);
  b1 := GetBValue(Color);
  for X := 0 to bmp.Width - 1 do
  begin
    for Y := 0 to bmp.Height - 1 do
    begin
      c := Bmp.Canvas.Pixels[X,Y];
      r2 := GetRValue(c);
      g2 := GetGValue(c);
      b2 := GetBValue(c);
     // if (c <> clWhite) and (c <> clBlack) then
     // begin
        r2 := Round(r1*Min(Abs(r2-MaxByte),MaxByte-r2)/MaxByte);
        g2 := Round(g1*Min(Abs(g2-MaxByte),MaxByte-g2)/MaxByte);
        b2 := Round(b1*Min(Abs(b2-MaxByte),MaxByte-b2)/MaxByte);
        c := RGB(r2,g2,b2);
        Bmp.Canvas.Pixels[X,Y] := c;
    //  end;
    end;
  end;
end;

procedure Grayscale(const bmp: TBitmap);
var
  p: PByteArray;
  J,Y,W: Integer;
begin
  bmp.PixelFormat := pf24bit;
  for Y := 0 to bmp.Height - 1 do
  begin
    p := bmp.ScanLine[Y];
    J := 0;
    while J < bmp.Width*3 do
    begin
      W := (P[J] * 28 + P[J+1] *151 + P[J+2] * 77);
      W := W shr 8;
      P[J] := Byte(W);
      P[J+1] := Byte(W);
      P[J+2] := Byte(W);
      Inc(J,3);
    end;
  end;
  //bmp.PixelFormat := pf1bit;
  //bmp.PixelFormat := pf24bit;
end;

function ALL2BMP(const Filename : String; const Bmp: TBitmap): Boolean;
var
  GIF: TGIFImage;
  jpg: TJPEGImage;
  PNG: TPNGobject;
  FileEx: String;
begin
  Result := False;
  try
    FileEx := UpperCase(ExtractFileExt(filename));
    if FileEx = '.PNG' then
    begin
      PNG := TPNGobject.Create;
      try
        PNG.LoadFromFile(filename);
        _PicFormat := 2;
        BMP.Assign(PNG);
      except
        //not png image
      end;
      PNG.Free;
    end else if FileEx = '.BMP' then
      try
        BMP.LoadFromFile(filename);
        _PicFormat := 1;
      except
        //not bmp image
      end
    else if FileEx = '.GIF' then
    begin
      GIF := TGIFImage.Create;
      try
        GIF.LoadFromFile(filename);
        _PicFormat := 3;
        BMP.Assign(GIF);
      except
        //not gif image
      end;
      GIF.Free;
    end else if (FileEx = '.JPG') or (FileEx = '.JPEG') then
    begin
      JPG := TJPEGImage.Create;
      try
        JPG.LoadFromFile(filename);
        _PicFormat := 4;
        BMP.Assign(JPG);
      except
        //not jpg image
      end;
      JPG.Free;
    end;
    //
    if _PicFormat = 0 then
      try
        BMP.LoadFromFile(FileName);
        _PicFormat := 1;
      except
      end;
    if _PicFormat = 0 then
    begin
      PNG := TPNGobject.Create;
      try
        PNG.LoadFromFile(FileName);
        _PicFormat := 2;
        BMP.Assign(PNG);
      finally
        PNG.Free;
      end;
    end;
    if _PicFormat = 0 then
    begin
      GIF := TGIFImage.Create;
      try
        GIF.LoadFromFile(FileName);
        _PicFormat := 3;
        BMP.Assign(GIF);
      finally
        GIF.Free;
      end;
    end;
    if _PicFormat = 0 then
    begin
      JPG := TJPEGImage.Create;
      try
        JPG.LoadFromFile(FileName);
        BMP.Assign(JPG);
        _PicFormat := 4;
      finally
        JPG.Free;
      end;
    end;
    Result := True;
  except
  end;
end;
//////////////////

function PIC2BMP(filename : String): TBITMAP;
var
  GIF: TGIFImage;
  jpg: TJPEGImage;
  BMP: TBITMAP;
  PNG: TPNGobject;
  FileEx: String;
  i, j, x: Byte;
  b : boolean;
  //
  SrcRGB : pByteArray;
  ClPixel : TColor;
begin
  b := False;
  ClPixel := 0;
  FileEx := UpperCase(ExtractFileExt(filename));
  BMP := TBITMAP.Create;
  if FileEx = '.PNG' then
  begin
    PNG := TPNGobject.Create;
    try
      PNG.LoadFromFile(filename);
      _PicFormat := 2;
      BMP.Assign(PNG);
    except
      //not png image
    end;
    PNG.Free;
  end else if FileEx = '.BMP' then
    try
      BMP.LoadFromFile(filename);
      _PicFormat := 1;
    except
      //not bmp image
    end
  else if FileEx = '.GIF' then
  begin
    GIF := TGIFImage.Create;
    try
      GIF.LoadFromFile(filename);
      _PicFormat := 3;
      BMP.Assign(GIF);
    except
      //not gif image
    end;
    GIF.Free;
  end else if (FileEx = '.JPG') or (FileEx = '.JPEG') then
  begin
    JPG := TJPEGImage.Create;
    try
      JPG.LoadFromFile(filename);
      _PicFormat := 4;
      JPG.Grayscale := TRUE;
      BMP.Assign(JPG);
    except
      //not jpg image
    end;
    JPG.Free;
  end;
  //
  if _PicFormat = 0 then
    try
      BMP.LoadFromFile(FileName);
      _PicFormat := 1;
    except
    end;
  if _PicFormat = 0 then
  begin
    PNG := TPNGobject.Create;
    try
      PNG.LoadFromFile(FileName);
      _PicFormat := 2;
      BMP.Assign(PNG);
    finally
      PNG.Free;
    end;
  end;
  if _PicFormat = 0 then
  begin
    GIF := TGIFImage.Create;
    try
      GIF.LoadFromFile(FileName);
      _PicFormat := 3;
      BMP.Assign(GIF);
    finally
      GIF.Free;
    end;
  end;
  if _PicFormat = 0 then
  begin
    JPG := TJPEGImage.Create;
    try
      JPG.LoadFromFile(FileName);
      JPG.Grayscale := TRUE;
      BMP.Assign(JPG);
      _PicFormat := 4;
    finally
      JPG.Free;
    end;
  end;

  _PicWidth := BMP.Width;
  _PicHeight := BMP.Height;
  //BMP.SaveToFile(_PicFile+'.BMP');

  //Fetch(_BbsType,_PicWidth,_PicHeight,_PicFormat,_CodeUrl);
  if _EffBLW then
  begin
    Grayscale(bmp);
    Ranse(bmp,clRed);
    WhiteBlackImgEx(bmp);
  end else
  begin
    Bmp.PixelFormat := pf24Bit;

  // make picture only black and white
    for j := 0 to BMP.Height - 1 do
    begin
      SrcRGB := BMP.ScanLine[j];
      for i := 0 to BMP.Width - 1 do
      begin
        if MycharInfo._ClrRect then
        begin
          x := MycharInfo._RectLen;
          if (i<x)or(j<x)or(i>BMP.Width-1-x)or(j>BMP.Height-1-x) then
          begin
            SrcRGB[i*3]   := $ff;
            SrcRGB[i*3+1] := $ff;
            SrcRGB[i*3+2] := $ff;
            continue;
          end;
        end;
        ClPixel := HexToInt(IntToHex(SrcRGB[i*3],2)+
                              IntToHex(SrcRGB[i*3+1],2)+
                              IntToHex(SrcRGB[i*3+2],2));
        if MycharInfo.CusDiv then
        begin
          case MycharInfo.DivCmp of
          0:  b := ClPixel > MycharInfo.DivColr;
          1:  b := ClPixel = MycharInfo.DivColr;
          2:  b := ClPixel < MycharInfo.DivColr;
          4:  b := ClPixel <> MycharInfo.DivColr;
          end;
        end else
          b := ClPixel > MycharInfo.DivColr;
        if b then begin
          SrcRGB[i*3]   := $ff;
          SrcRGB[i*3+1] := $ff;
          SrcRGB[i*3+2] := $ff;
        end else begin
          SrcRGB[i*3]   := 0;
          SrcRGB[i*3+1] := 0;
          SrcRGB[i*3+2] := 0;
        end;
      end;
    end;
  end;
  {BMP.Canvas.lock;
  for i := 0 to BMP.Width - 1 do
    for j := 0 to BMP.Height - 1 do
    begin
      if _ClrRect then
      begin
        x := _RectLen;
        if (i<x)or(j<x)or(i>BMP.Width-1-x)or(j>BMP.Height-1-x) then
        begin
          BMP.Canvas.Pixels[i, j] := clwhite;
          continue;
        end;
      end;
      if _CusDiv then
      begin
        case _DivCmp of
        0:  b := BMP.Canvas.Pixels[i, j] > _DivColr;
        1:  b := BMP.Canvas.Pixels[i, j] = _DivColr;
        2:  b := BMP.Canvas.Pixels[i, j] < _DivColr;
        end;
      end else
        b := BMP.Canvas.Pixels[i, j] > _DivColr;
      if b then
        BMP.Canvas.Pixels[i, j] := clwhite
      else
        BMP.Canvas.Pixels[i, j] := clblack;
    end;
  BMP.Canvas.Unlock;  }
  result := BMP;
end;

function CMPBMP(SBMP: TBITMAP; x0, m: integer): integer;
var
  i, j: integer;
  //
  SrcRGB : pByteArray;
begin
  result := 0;
  for j := 0 to MycharInfo.charheight -1 do
  begin
    SrcRGB := SBMP.ScanLine[j];
    for i := 0 to MycharInfo.charwidth -1 do
    begin
      if MycharInfo._CmpChr and (SrcRGB[(x0+i)*3] = 0) and (MycharInfo.allcharinfo[m].MyCharInfo[i, j] = 0) then
        Inc(Result);
      if MycharInfo._CmpBg and (SrcRGB[(x0+i)*3] > 0) and (MycharInfo.allcharinfo[m].MyCharInfo[i, j] = 1) then
        Inc(Result);
    end;
  end;

  {
  result := 0;
  SBMP.Canvas.Lock;
  for i := 0 to MycharInfo.charwidth - 1 do
    for j := 0 to MycharInfo.charHeight - 1 do
    begin
      if _CmpChr and (SBMP.Canvas.Pixels[x0 + i, j] = 0) and (MycharInfo.allcharinfo[m].MyCharInfo[i, j] = 0) then
        Inc(Result);
      if _CmpBg and (SBMP.Canvas.Pixels[x0 + i, j] > 0) and (MycharInfo.allcharinfo[m].MyCharInfo[i, j] = 1) then
        Inc(Result);
    end;
  SBMP.Canvas.Unlock;  }
end;


function CMPBMPPRO(SBMP: TBITMAP; x0, m: integer): integer;
var
  i, j : integer;
  xj : byte;
  Ret : Integer;
  //
  SrcRGB : pByteArray;
begin
  result := 99999;
  for xj := 0 to _BITMAP.Height - MycharInfo.charheight do
  begin
    Ret := 0;
    for j := 0 to MycharInfo.charHeight - 1 do
    begin
      SrcRGB := SBMP.ScanLine[j+xj];
      for i := 0 to MycharInfo.charwidth - 1 do
      begin
        if MycharInfo._CmpChr and (SrcRGB[(x0+i)*3] = 0) and (MycharInfo.allcharinfo[m].MyCharInfo[i, j] = 0) then
          Inc(Ret);
        if MycharInfo._CmpBg  and (SrcRGB[(x0+i)*3] > 0) and (MycharInfo.allcharinfo[m].MyCharInfo[i, j] = 1) then
          Inc(Ret);
      end;
    end;
    if result > Ret then
    result := Ret;
  end;

  {result := 99999;
  SBMP.Canvas.Lock;
  for xj := 0 to _BITMAP.Height - MycharInfo.charheight do
  begin
    Ret := 0;
    for i := 0 to MycharInfo.charwidth - 1 do
      for j := 0 to MycharInfo.charHeight - 1 do
      begin
        if _CmpChr and (SBMP.Canvas.Pixels[x0 + i, j+xj] = 0) and (MycharInfo.allcharinfo[m].MyCharInfo[i, j] = 0) then
          Inc(Ret);
        if _CmpBg  and (SBMP.Canvas.Pixels[x0 + i, j+xj] > 0) and (MycharInfo.allcharinfo[m].MyCharInfo[i, j] = 1) then
          Inc(Ret);
      end;
    if result > Ret then
    result := Ret;
  end;
  SBMP.Canvas.Unlock;   }
end;

function GetStringFromImage(SBMP: TBITMAP): String;
//const
//  SpeicalChars: array [0..6] of String = ('+','-','*','/','(',')','=');
var
  k, m, x: integer;
  alike : Integer;
  S : String;
  Sort : boolean;
  SlAlike : TStringList;
begin
  //DebugStr('SBMP_W_H',IntToStr(SBMP.Width)+'*'+IntToStr(SBMP.Height),'e:');
  result := '';
  if _Effect.To1Line = True then
  begin
    try
      To1Line(SBMP,_Effect.Y0,MycharInfo.X0,MycharInfo.charwidth,Mycharinfo.TotalChars);
    except
    end;
  end;
  SlAlike := TStringList.Create;
  for k := 0 to MycharInfo.TotalChars - 1 do
  begin
    x := MycharInfo.X0 + MyCharInfo.charwidth * k;
    //DebugLog('k:'+IntToStr(k)+'  '+'x:'+IntToStr(x));
    SlAlike.Clear;
    Sort := True;
    for m := 0 to 42 do
    begin
      if Mycharinfo.allcharinfo[m].used = True then
      begin
        {if m>35 then
          S := SpeicalChars[m-36]
        else if m>9 then
          S := Chr(m+87)
        else
          S := IntToStr(m); }
        S := Mycharinfo.allcharinfo[m].MyChar;
        if SBMP.Height = MycharInfo.charheight then
          Alike := CMPBMP(SBMP, x, m)
        else
          Alike := CMPBMPPRO(SBMP, x, m);
      //DebugLog('m:'+s+'  '+'Alike:'+IntToStr(Alike));
        if Alike = 0 then
        begin
          Result := Result + S;
          //DebugLog('get_it:'+s);
          //DebugStr('GET_IT','GET '+S+ ' AS '+IntToStr(k+1)+ 'TH NUM','e:');

          Sort := False;
          break;
        end else
          SlAlike.Add(S + Sp + IntToStr(Alike));
      end;
    end;
    if Sort then
    begin
      SlQuickSort(SlAlike,0,SlAlike.Count-1);
      result := result + GetHead(SlAlike[0],Sp);
      //DebugLog('get_it_by_sort:'+GetHead(SlAlike[0],Sp));
      //DebugStr('GET_IT_SORT','GET '+GetHead(SlAlike[0],Sp)+ ' AS '+IntToStr(k)+ 'TH NUM','e:');

      //SlAlike.SaveToFile('f:\'+IntToStr(k)+'.txt');
    end;
  end;
  SlAlike.Free;
end;

function RecogOCR(var Success: Boolean; const ImageFile: String): String;
begin
  Success := False;
  try
    _BITMAP := nil;
    LastRecogTime := GetTickCount;
    _BITMAP := PIC2BMP(ImageFile);
    Result := GetStringFromImage(_BITMAP);
    LastRecogTime := GetTickCount-LastRecogTime;
    SaveBmp;
    _BITMAP.Free;
    Success := True;
    if SSCode = 1 then Result := SSUtils.RecogSuanshi(Result);
  except
    LastRecogTime := 0;
  end;
end;
end.
/////////////////////////
ssutils.pas


unit SSUtils;

interface

uses Windows, SysUtils, CalcExpress;

function RecogSuanshi(const S: String): String;

implementation

function DeleteFh(const S: String; const Fh: Char): String;
var
  I: Integer;
begin
  Result := '';
  for I := 1 to Length(S) do
  begin
    if S[I] <> Fh then
    begin
      Result := Result + S[I];
    end;
  end;
end;

function RecogSuanshi(const S: String): String;
const
  argv: array [0..1] of Extended = (0,1);
var
  S2: String;
  cexp: TCalcExpress;
begin
  Result := '计算错误!';
  try
    cexp := TCalcExpress.Create(nil);
    try
      S2 := DeleteFh(S,'?');
      S2 := DeleteFh(S,'=');
      S2 := StringReplace(S2,'加','+',[rfReplaceAll]);
      S2 := StringReplace(S2,'减','-',[rfReplaceAll]);
      S2 := StringReplace(S2,'乘','*',[rfReplaceAll]);
      S2 := StringReplace(S2,'除','/',[rfReplaceAll]);
      S2 := StringReplace(S2,'×','*',[rfReplaceAll]);
      S2 := StringReplace(S2,'÷','/',[rfReplaceAll]);
      S2 := StringReplace(S2,'+','+',[rfReplaceAll]);
      S2 := StringReplace(S2,'-','-',[rfReplaceAll]);

      cexp.Formula := S2;
      Result := IntToStr(Round(cexp.calc(argv)));
    except
    end;
  finally
    cexp.Free;
  end;
end;

end.

AsphyreZlib.pas就是zlibex.pas(zlibex组件包里),重命名一下就可以了
CalcExpress.pas是CalcExpress组件包
PNGImage是PNGImage组件包
GIFImage.pas是GIFImage组件包
Math.pas, delphi7自带的文件啊,如果没有,重装delphi!

想要特征码dll,加我qq: 2484365584
 http://www./downloads457/sourcecode/graph/texture_mapping/detail1923426.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约