分享

使用DELPHI对图片中的文字进行识别的过程(最简单实现)

 360大测试 2016-12-03
unit bmp2number;
{将传递进来的图像进行对比,识别出图片中的数字。
本程序使用的是模式识别的方式,需要照片标准,数字无反光。
电表只有4位数字+1位小数,小数因为在拍照中不能保证停止,所以本程序也不作小数位的识别
因此。如果当前的数字 已经识别到了4位,程序就返回,
我们预设一个记录,用来记录这被识别的出4位数字的具体位置,再通过对TOP及LEFT位置的进行排序组合后返回
对于本模板的重要方法说明:
Function GetNumber:string
功能:返回识别出的数字字符串
按照对TBmp2Number对象的下列属性:
  SoruceBitmap:需要被识别的图像
  Temp_Index:模板编号
  Temp_path:模板文件目录
  discern_rate:识别率

}

interface
uses windows,math,classes,controls,graphics,jpeg,sysutils,dialogs,extctrls,forms,
stdctrls,ComCtrls;

Type
  pRGBTripleArray = ^TRGBTripleArray;
  TRGBTripleArray = array [0 .. 65535] of TRGBTriple;
  Ptemplate=^Ttemplate;  //被识别的数字当用记录保存起来
  Ttemplate=record
    number:integer;
    top:Integer;
    Left:Integer;
  end;
  
  TBmp2Number=class(Tobject)
    private
     FSourceBitMap:Tbitmap;
     FTempl_index:integer;
     Ftempl_Path:String;
     Fdiscern_rate:Double;
     FNumber:string;
     FNumberList:TList;
     tmeplate:Ptemplate;
     fStop:Boolean;
     FShowDemo:Boolean;
    protected
      procedure SetTempl_index(value:Integer);
      procedure SetTempl_path(Value:String);
      procedure InitTemplate;
      Function GetNumber:String;
     
    public
      memo1:TRichedit;
      image1,image2:Timage;
      pb_Count,pb_deta:TProgressbar;
      constructor Create;
   
    published
      property SourceBitMap:Tbitmap read FSourceBitMap write FSourceBitmap;
      property Templ_index:integer read Ftempl_index write SetTempl_index;
      Property Templ_Path:String read Ftempl_Path write SetTempl_path;
      property discern_rate:Double read Fdiscern_rate write Fdiscern_rate ;
      property Number:String read GetNumber;
      property Stop:Boolean read Fstop write FStop;
      property ShowDemo:Boolean read FShowDemo write FShowDemo;
    end;

//SourceBitmap:电表图片,template_index:调用的模板号   template_path;模板存放的目录

   
Function Pic2Bmp(PicFileName:String):TBitmap;


implementation

//将图片转换成BMP格式,以便比较,主要是因为数码相机采集的图片基本上是JPEG 格式的。
//所以在装入时需要将其转换成BMP图片,便于比较
Function Pic2Bmp(PicFileName:String):TBitmap;
var
  Str:String;
  Icon: TIcon;
  Jpeg1:TJPEGIMAGE;
  MetaFile:TMetafile; 
begin
 result:=TBitMap.create;
 result.PixelFormat:=pf24bit;
 Str := ExtractFileExt(PicFileName);
 Str :=Uppercase(Copy(Str,2,3));
  if (Str='BMP')   then
      result.LoadFromFile(PicFileName)
  else  //Jpeg转换成BMP
  if (Str='JPG') or (Str='JPEG') then
  begin
    Jpeg1 := TJPEGIMAGE.Create;
    Jpeg1.LoadFromFile(PicFileName);
    result.Assign(Jpeg1);
    Jpeg1.free;
  end
  else       //ICO 转换成BMP
  if (Str='ICO') or (Str='ico') then
  begin
     Icon := TIcon.Create;
     Icon.LoadFromFile(PicFileName);
     result := TBitmap.Create;
     result.Width := Icon.Width;
     result.Height := Icon.Height;
     result.Canvas.Draw(0, 0, Icon);
     Icon.Free;

  end
  else  //WMF转换成BMP
  if Str='WMF' then
  begin
      Metafile:=TMetaFile.create;
    
      MetaFile.LoadFromFile(PicFileName);
     with result do
     begin
        Height:=Metafile.Height;
        Width:=Metafile.Width;
        Canvas.Draw(0,0,MetaFile);

     end;
     MetaFile.Free; 
  end;

end;

constructor TBmp2Number.Create;
begin
  inherited Create;
  Ftempl_index:=1;
  Ftempl_Path:='template';
  Fdiscern_rate:=100;
end;

//设置模板索引
procedure TBmp2Number.SetTempl_index(value:integer);
begin
  FtempL_index:=Value;
  initTemplate;
end;

procedure TBmp2Number.SetTempl_path(value:String);
begin
  FTempl_path:=value;
  initTemplate;
end;

//初始化运行模板库
procedure TBmp2Number.InitTemplate;
begin
  if tempL_Index=0 then exit;
  if Not DirectoryExists(Templ_Path) then exit;
  
end;
 
//逐行扫描的方式识别图片中的数字
function TBmp2Number.GetNumber:string;

var
  tmpleBmp,midbmp:TBitMap;
  row,Col,mRow,mCol,numberNo:integer;
  NewRow,NewCol:integer;
  PSource, Ptemple: pRGBTripleArray;
  mR, mG, mB, tR, tG, tB: Integer;
  mP, tP: pRGBTripleArray;
  succ:Boolean;//对比是否成功
begin
  //数据的初步检查
  if sourcebitmap=nil then
  begin
    showmessage('请装入目标图片!');
    exit;
  end;
  FNumberList:=Tlist.Create;
  try
  if assigned(pb_Count) then
     pb_Count.Max:= SourceBitMap.width;
    if assigned(pb_deta) then
      pb_deta.Max:= SourceBitMap.Height;   
     
  for Col:=0 to  SourceBitMap.width-1 do
  begin
   if stop then exit;
    if  ShowDemo then
    memo1.Lines.Add('本列是:'+inttostr(col));
    if assigned(pb_Count) then
    begin
     pb_Count.Position:=col;
     Application.ProcessMessages;
    end; 
    for Row:=0 to SourceBitMap.Height-1   do
    begin
       if assigned(pb_deta) then
        begin
          pb_deta.Max:= SourceBitMap.Height;
          pb_deta.Position:=Row;
          Application.ProcessMessages;
        end;
      if stop then exit;
      for numberNo:=0 to 9 do   //0至9的数字分别装入模板
      begin
        if    not fileexists(Templ_Path+inttostr(numberNo)+'_'+inttostr(Templ_index)+'.bmp') then continue;

          if stop then exit;
         tmpleBmp:=TBitMap.create;
         tmpleBmp:=Pic2Bmp(Templ_Path+inttostr(numberNo)+'_'+inttostr(Templ_index)+'.bmp');
//         tmpleBmp.LoadFromFile(Templ_Path+inttostr(numberNo)+'_'+inttostr(Templ_index)+'.bmp');
          if  ShowDemo then
         image1.Picture.bitmap:=tmplebmp;
        
         //从原图像中驳离出来与模板文件同样大小的文件来
         midbmp:=Tbitmap.Create;
         midbmp.PixelFormat:= tmpleBmp.PixelFormat;
         midbmp.Width:=tmplebmp.Width;
         midbmp.height:=tmplebmp.Height;

         application.ProcessMessages;
       //

         midbmp.Canvas.CopyRect(Rect(0,0,midbmp.width,midbmp.height),
                sourcebitmap.canvas,
                Rect(Col,row,Col+tmpleBmp.width,row+tmpleBmp.height));
         if  ShowDemo then
               image2.picture.bitmap:=midbmp;
          Assert(midbmp.PixelFormat = tmpleBmp.PixelFormat);
         //然后逐行取值比较
         for mRow:=0 to MidBmp.Height-1 do
         begin
           mp:= midBmp.ScanLine[mRow];
           tp:= tmplebmp.ScanLine[mRow];
              if stop then exit;
           for mcol:=0 to MidBmp.Width -1 do
           begin
            if stop then exit;
             mR := mp[mcol].rgbtRed;
             mG := mP[mcol].rgbtGreen;
             mB := mP[mcol].rgbtBlue;
             tR := tP[mcol].rgbtRed;
             tG:= tP[mcol].rgbtGreen;
             tB:=tP[mcol].rgbtBlue;
            if  ShowDemo then
             memo1.Lines.Add('Mrow:'+Inttostr(mrow)+'MCol:'+inttostr(Mcol)+'mr:'
             +inttostr(mr)+'mg:'+inttostr(mg)+'mb:'+
               inttostr(mb)+'tr:'+inttostr(tr)+'tg:'+inttostr(tg)+'tb:'+
               inttostr(tb));
             if (mR <> tR) or (mG <> tG) or (mB <> tB) then//如果像素不等
             begin
               succ:=false;
               break;

             end
             else
             succ:=true;

           end; // end mcol:=0 to midbmp.width -1 do


       end;   //end mrow:=0 to midbmp.height-1 do
       freeandnil(midbmp);
        if succ then
         begin//对比成功
          new(tmeplate);
          tmeplate.number:= numberNo;
          tmePlate.top := Row;
          tmePlate.left:=col;
          FNumberList.Add(tmeplate);
         end  ;
        // else
        //  break;
        freeandnil(tmpleBmp);
     end;              //end for number


   end;    //end for row
   end; // end for col
   except
     showmessage('对比失败!');
   end;

 for   row:=0 to  FNumberList.Count -1 do
   Result:=result+inttostr(Ptemplate(FNumberlist.Items[row]).number);
 for row:=FNumberList.count-1 downto 0 do
 begin
  Dispose(Ptemplate(FNumberList[Row]));
  FNumberlist.Delete(row);
 end;
 FNumberlist.free;
end;



end.

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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多