主页 > 编程资料 > Delphi >
发布时间:2015-09-22 作者:网络 阅读:180次

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;
关键字词: