• Delphi识别读取验证码


    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
         char byte; //字符宽度
        charheight: byte; //字符高度
        X0: byte; //第一个字符开始x偏移
        TotalChars: byte; //图象字符总数
        CusDiv : boolean;  //自定义二值化运算
        DivCmp : Byte; //  0:>  1:=  2:<<br>     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 (iBMP.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 (iBMP.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.
    //----------------------------------------------------------
     //----------------------------------------------------------
    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.
  • 相关阅读:
    数据仓库- 建模理念
    SpringBoot- springboot集成Redis出现报错:No qualifying bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory'
    CDH- cdh kafka已经卸载了,但是服务器还有kafka-topics这些命令可用,导致重新安装kafka出现问题
    【JZOJ6217】【20190614】最大面积
    【JZOJ6216】【20190614】序列计数
    【JZOJ6228】【20190621】ni
    【JZOJ6227】【20190621】ichi
    【JOISC2019|2019】【20190622】cake3
    【JOISC2018|2019】【20190622】mergers
    【JOISC2018|2019】【20190622】minerals
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/3927102.html
Copyright © 2020-2023  润新知