http://www.googler.cc/Software.html 源代码 在这下载 unit MainFrm; //承接图像算法开发,手机应用及游戏软件开发。 //QQ : 235483710 //查找图像中的人物边缘,分离人物和背景。用于人物识别 //Find figure edge in a image, Separate figure and background in a image. //Person identification in a image //More code in www.googler.cc //All Rights Reserved --- Hu Rui interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, ComCtrls, jpeg, StrUtils, FmtBcd,Math, ShellAPI, OleCtrls, SHDocVw ; type TForm1 = class(TForm) btn1: TBitBtn; grp1: TGroupBox; Image1: TImage; dlgOpen1: TOpenDialog; lbl11: TLabel; btn8: TBitBtn; btn2: TBitBtn; mmo_Info: TMemo; lbl1: TLabel; lbl2: TLabel; lbl3: TLabel; img1: TImage; lbl4: TLabel; wb1: TWebBrowser; lbl5: TLabel; ScrollBar1: TScrollBar; // 自动计算获得合适的阈值 Get best threshold function GetBestWBValue( bmpBackGround1 : TBitmap ) : Integer ; // 根据阈值获得2极图 function CreateBestWBValue( bmpBackGround1 : TBitmap ; WBValue : Integer ) : TBitmap ; // 根据“大精”阈值获得2极图 function GetBestWBValue2( bmpBackGround1 : TBitmap) : Integer ; // 寻找图像边界,找到图像中人物的位置 Find people's edge in a image function FindEdge( bmpBackGround1 : TBitmap ) : TBitmap ; //根据阈值调整图像 // 处理移动图像 Move picture // 参数定义 bmpBackGround1 背景图片 // bmpTexture1 纹理图片 // moveX 纹理开始区域在背景图中X坐标 // moveY 纹理开始区域在背景图中Y坐标 // 返回 Bitmap移动后的图片 function CreateMoveImg( bmpBackGround1 : TBitmap ; bmpTexture1 : TBitmap ; moveX : Integer ; moveY : Integer ) : TBitmap; //图像去色 gray //参数定义 // bmpBackGround1 底图 //返回 图像去色后的图 function GrayEffect( bmpBackGround1 : TBitmap ) : TBitmap ; //云模糊 fog //参数定义 // bmpBackGround1 背景图 // cloudyValue 模糊因子 //返回 模糊处理后图片 function CloudyEffect( bmpBackGround1 : TBitmap ; cloudyValue : Integer ) : TBitmap ; procedure btn1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure btn8Click(Sender: TObject); procedure btn2Click(Sender: TObject); procedure ScrollBar1Change(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; bmpBackGround : TBitmap ; //背景位图 bmpTexture : TBitmap ; //纹理位图 isLoadBackGround : Boolean ; //是否已经加载背景图 isLoadTexture : Boolean ; //是否已经加载纹理图 alphaValue : Integer ; //alpha数值 brightValue : Integer ; //亮度 contrastValue : Integer ; //对比度 implementation {$R *.dfm} //============================================================================== // 自动计算获得合适的阈值 //============================================================================== function TForm1.GetBestWBValue(bmpBackGround1: TBitmap): Integer; var i,j : Integer ; PBmpBackGround : PbyteArray ; tmpS,tmpS1,tmpBright,tmpDark : Integer ; begin bmpBackGround1 := CloudyEffect(GrayEffect(bmpBackGround1),2) ; tmpS := 0 ; tmpS1 := bmpBackGround1.Height * bmpBackGround1.Width ; tmpBright := 0 ; tmpDark := 0 ; //获取底图颜色分量 for i := 0 to bmpBackGround1.Height-1 do begin PBmpBackGround:= bmpBackGround1.ScanLine[i]; for j := 0 to bmpBackGround1.Width-1 do begin tmpS := tmpS + PBmpBackGround[j*3] ; if PBmpBackGround[j*3] > 128 then Inc(tmpBright) else Inc(tmpDark); end ; end ; if tmpBright > tmpDark then begin //明 bright tmpS1 := tmpS div ( tmpS1 * 2 ) - 10 ; end else begin //暗 dark tmpS1 := tmpS div ( tmpS1 * 3 ) ; end ; Result := tmpS1 ; end; //============================================================================== // 根据阈值获得2极图 //============================================================================== function TForm1.CreateBestWBValue(bmpBackGround1: TBitmap; WBValue: Integer): TBitmap; var i,j : Integer ; PBmpBackGround : PbyteArray ; begin bmpBackGround1 := CloudyEffect(GrayEffect(bmpBackGround1),0) ; //获取底图颜色分量 for i := 0 to bmpBackGround1.Height-1 do begin PBmpBackGround:= bmpBackGround1.ScanLine[i]; for j := 0 to bmpBackGround1.Width-1 do begin //B if PBmpBackGround[j*3] > WBValue then begin PBmpBackGround[j*3] := 255 ; PBmpBackGround[j*3+1] := 255 ; PBmpBackGround[j*3+2] := 255 ; end else if PBmpBackGround[j*3] <= WBValue then begin PBmpBackGround[j*3] := 0 ; PBmpBackGround[j*3+1] := 0 ; PBmpBackGround[j*3+2] := 0 ; end ; end ; end ; Result := bmpBackGround1 ; end; //============================================================================== // 根据“大精”阈值获得2极图 。特此感谢谢凤英的著作 // 一个叫"精"的日本男人发明的算法 //============================================================================== function TForm1.GetBestWBValue2(bmpBackGround1: TBitmap): Integer; var i,j,k : Integer ; avr_group1,avr_group2 : Real ; //组1和组2平均值 p_group1, p_group2 : Real ; //组1和组2的概率 group1Count,totalCount : Integer ; //组1,组2的像素数,总像素数 r_t,r_maxT : Integer ; //阈值T和最佳阈值MAXT devi,maxDevi : Integer ; //方差及最大方差。 ZhiFangData : array[0..255] of Integer ; //图像的灰度直方图 PBmpBackGround : PbyteArray ; begin bmpBackGround1 := CloudyEffect(GrayEffect(bmpBackGround1),2) ; maxDevi := 0 ; r_maxT := 0 ; for i := 0 to 255 do ZhiFangData[i] := 0 ; totalCount := bmpBackGround1.Height * bmpBackGround1.Width ; //获得图像灰度直方图数据 //获取底图颜色分量 for i := 0 to bmpBackGround1.Height-1 do begin PBmpBackGround:= bmpBackGround1.ScanLine[i]; for j := 0 to bmpBackGround1.Width-1 do begin for k := 0 to 255 do begin if PBmpBackGround[j*3] = k then begin ZhiFangData[k] := ZhiFangData[k] + 1 ; end ; end ; end ; end ; //group1均值和概率 for r_t :=0 to 253 do begin avr_group1 := 0; group1Count := 0; for i := 0 to r_t do begin avr_group1 := avr_group1 + i*ZhiFangData[i] ; group1Count := group1Count + ZhiFangData[i] ; end ; // mmo1.Lines.Add('avr_group1 = ' + FloatToStr(avr_group1) + ' : group1Count = ' + IntToStr(group1Count)) ; if group1Count <> 0 then avr_group1 := avr_group1 / group1Count else avr_group1 := 0 ; p_group1 := group1Count / totalCount ; //group2均值和概率 avr_group2 := 0; for i := r_t+1 to 255 do avr_group2 := avr_group2 + i*ZhiFangData[i] ; // mmo1.Lines.Add('avr_group1 = ' + FloatToStr(avr_group2) + ' : group1Count = ' + IntToStr(totalCount - group1Count)) ; if totalCount - group1Count <> 0 then avr_group2 := avr_group2 / (totalCount - group1Count) else avr_group2 := 0 ; p_group2 := 1 - p_group1 ; //2组间方差 devi := round( p_group1 * p_group2 * (avr_group2 - avr_group1) * (avr_group2 - avr_group1) ) ; //计算最大方差和最佳阈值 if devi > maxDevi then begin maxDevi := devi ; r_maxT := r_t ; end ; end ; Result := r_maxT ; end; //============================================================================== // 寻找人体区域 // 参数定义 bmpBackGround1 背景图片 // 返回 breast区域 //============================================================================== function TForm1.FindEdge(bmpBackGround1: TBitmap): TBitmap; var i,j,k,m,n,i1,j1,tmpH,tmpW,modelS : Integer ; PBmpBackGround : PbyteArray; bmpData : array of array of Byte ; //2极图数据单元,呵呵,我喜欢用数组 bmpTmpData : array of double ; avgValue,tmpInt : Integer ; re : TRect ; begin //255是明 0是暗 SetLength(bmpData,bmpBackGround1.Width,bmpBackGround1.Height) ; //获取底图颜色分量 for i := 0 to bmpBackGround1.Height-1 do begin PBmpBackGround:= bmpBackGround1.ScanLine[i]; for j := 0 to bmpBackGround1.Width-1 do begin bmpData[j][i] := PBmpBackGround[j*3] ; end end ; i := 0 ; j := 0 ; //分析区域,从上到下逐行分析,模版采用5*5 modelS := 3 ; tmpW := bmpBackGround1.Width div modelS ; tmpH := bmpBackGround1.Height div modelS ; tmpInt := tmpW * tmpH ; //总图块数 SetLength( bmpTmpData, tmpInt + 1 ) ; try for i := 1 to tmpInt do begin //根据图块索引确定图块的坐标 //纵轴 if i / tmpW - i div tmpW > 0 then n := i div tmpW + 1 else n := i div tmpW ; n := n - 1 ; //横轴 m := i - n * tmpW - 1; //计算1个模版单位平均灰度 for i1 := m * modelS to m * modelS + modelS -1 do for j1 := n * modelS to n * modelS + modelS -1 do begin bmpTmpData[i] := bmpData[i1][j1] + bmpTmpData[i] ; end ; bmpTmpData[i] := bmpTmpData[i] / ( modelS * modelS ) ; //检测图形边缘,并用红色标记出 if ( bmpTmpData[i] <> 255 ) and ( bmpTmpData[i] <> 0 ) then begin for i1 := m * modelS to m * modelS + modelS -1 do for j1 := n * modelS to n * modelS + modelS -1 do begin bmpBackGround1.Canvas.Pixels[i1+1,j1+1] :=RGB(255,0,0) ; end ; end ; end ; finally end ; //从上到下区域检测红线弧线,找出最适弧线 定义为 头部大小 Result := bmpBackGround1 ; end; //============================================================================== // 处理移动图像 // 参数定义 bmpBackGround1 背景图片 // bmpTexture1 纹理图片 // moveX 纹理开始区域在背景图中X坐标 // moveY 纹理开始区域在背景图中Y坐标 // 返回 Bitmap移动后的图片 //============================================================================== function TForm1.CreateMoveImg( bmpBackGround1 : TBitmap ; bmpTexture1 : TBitmap ; moveX : Integer ; moveY : Integer ) : TBitmap; var i,j : Integer ; PBmpTexture1,PBmpBackGround : PbyteArray; begin //获取底图颜色分量 for i := 0 to bmpBackGround1.Height-1 do begin PBmpBackGround:= bmpBackGround1.ScanLine[i]; for j := 0 to bmpBackGround1.Width-1 do begin //在moveX,moveY开始的地方绘制图形 if ( i >= moveY ) and ( i <= moveY + bmpTexture1.Height - 1) and ( j >= moveX ) and ( j <= moveX + bmpTexture1.Width - 1) then begin //获取纹理图颜色分量 PBmpTexture1 := bmpTexture1.ScanLine[i - moveY]; PBmpBackGround[j*3] := PBmpTexture1[(j-moveX)*3] ; //B PBmpBackGround[j*3+1] := PBmpTexture1[(j-moveX)*3+1] ; //G PBmpBackGround[j*3+2] := PBmpTexture1[(j-moveX)*3+2] ; //R end ; end ; end ; Result := bmpBackGround1; end; //============================================================================== //图像去色 //参数定义 // bmpBackGround1 底图 //返回 图像去色后的图 //============================================================================== function TForm1.GrayEffect(bmpBackGround1: TBitmap): TBitmap; var i,j : Integer ; PBmpBackGround : PbyteArray; begin for i := 0 to bmpBackGround1.Height-1 do begin PBmpBackGround := bmpBackGround1.ScanLine[i]; for j := 0 to bmpBackGround1.Width-1 do begin //B PBmpBackGround[j*3] := ( PBmpBackGround[j*3] + PBmpBackGround[j*3+1] + PBmpBackGround[j*3+2] ) div 3 ; //G PBmpBackGround[j*3+1] := ( PBmpBackGround[j*3] + PBmpBackGround[j*3+1] + PBmpBackGround[j*3+2] ) div 3 ; //R PBmpBackGround[j*3+2] := ( PBmpBackGround[j*3] + PBmpBackGround[j*3+1] + PBmpBackGround[j*3+2] ) div 3 ; end ; end ; for i := 0 to bmpBackGround1.Height-1 do begin PBmpBackGround := bmpBackGround1.ScanLine[i]; for j := 0 to bmpBackGround1.Width-1 do begin //B PBmpBackGround[j*3] := ( PBmpBackGround[j*3] + PBmpBackGround[j*3+1] + PBmpBackGround[j*3+2] ) div 3 ; //G PBmpBackGround[j*3+1] := ( PBmpBackGround[j*3] + PBmpBackGround[j*3+1] + PBmpBackGround[j*3+2] ) div 3 ; //R PBmpBackGround[j*3+2] := ( PBmpBackGround[j*3] + PBmpBackGround[j*3+1] + PBmpBackGround[j*3+2] ) div 3 ; end ; end ; Result := bmpBackGround1 ; end; //============================================================================== //云模糊 //参数定义 // bmpBackGround1 背景图 // cloudyValue 模糊因子 //返回 模糊处理后图片 //============================================================================== function TForm1.CloudyEffect(bmpBackGround1: TBitmap ; cloudyValue : Integer): TBitmap; var i,j : Integer ; PBmpBackGround,PBmpTmp1,PBmpTmp2 : PbyteArray; begin //边缘像素不处理 for i := 1 to bmpBackGround1.Height-2 do begin PBmpBackGround := bmpBackGround1.ScanLine[i]; PBmpTmp1 := bmpBackGround1.ScanLine[i-1] ; PBmpTmp2 := bmpBackGround1.ScanLine[i+1] ; for j := 1 to bmpBackGround1.Width-2 do begin // 取临近9格像素的平均值 //B PBmpBackGround[j*3] := (PBmpTmp1[j*3] + PBmpTmp1[(j-1)*3] + PBmpTmp1[(j+1)*3] + PBmpTmp2[j*3] + PBmpTmp2[(j-1)*3] + PBmpTmp2[(j+1)*3] + PBmpBackGround[j*3] + PBmpBackGround[(j-1)*3] + PBmpBackGround[(j+1)*3] ) div 9 ; //G PBmpBackGround[j*3+1] := ( PBmpTmp1[j*3+1] + PBmpTmp1[(j-1)*3+1] + PBmpTmp1[(j+1)*3+1] + PBmpTmp2[j*3+1] + PBmpTmp2[(j-1)*3+1] + PBmpTmp2[(j+1)*3+1] + PBmpBackGround[j*3+1] + PBmpBackGround[(j-1)*3+1] + PBmpBackGround[(j+1)*3+1] ) div 9 ; //R PBmpBackGround[j*3+2] := ( PBmpTmp1[j*3+2] + PBmpTmp1[(j-1)*3+2] + PBmpTmp1[(j+1)*3+2] + PBmpTmp2[j*3+2] + PBmpTmp2[(j-1)*3+2] + PBmpTmp2[(j+1)*3+2] + PBmpBackGround[j*3+2] + PBmpBackGround[(j-1)*3+2] + PBmpBackGround[(j+1)*3+2] ) div 9 ; end ; end ; if cloudyValue <> 0 then begin Dec( cloudyValue ) ; CloudyEffect(bmpBackGround1,cloudyValue); end ; Result := bmpBackGround1 ; end; //============================================================================== //============================================================================== //======================以下是界面控制处理====================================== //============================================================================== //============================================================================== //============================================================================== // 窗体创建 //============================================================================== procedure TForm1.FormCreate(Sender: TObject); begin //窗体初始化位置 dlgOpen1.Title := '请选择图片文件,试用仅支持bmp。欢迎购买商用DLL版本' ; dlgOpen1.InitialDir := ExtractFilePath(Application.ExeName) ; //初始化位图 bmpBackGround := TBitmap.Create ; //背景位图 self.DoubleBuffered := true ; //打开双缓冲 //广告 // wb1.Navigate('www.googler.cc/adinfo.html'); end; //============================================================================== // 导入背景图片 //============================================================================== procedure TForm1.btn1Click(Sender: TObject); begin //打开文件选择框加载图片 dlgOpen1.Execute ; //判断选择的背景图片是否格式正确 if RightStr( dlgOpen1.FileName , 4 ) = '.bmp' then begin Image1.Picture.LoadFromFile( dlgOpen1.FileName ) ; //将jpeg图转化为位图 //jpegImg := TJPEGImage.Create ; //jpegImg.LoadFromFile( OpenDialog1.FileName ) ; //bmpBackGround.Assign( jpegImg ) ; bmpBackGround.Assign(Image1.Picture) ; isLoadBackGround := True ; end; end; //============================================================================== // 赞助商 //============================================================================== procedure TForm1.btn8Click(Sender: TObject); begin ShowMessage('My email : 235483710@qq.com -- Hu Rui . Thanks for www.googler.cc and www.j2megame.com 。'); shellexecute(handle,'open',pchar('http://www.googler.cc'),nil,nil,sw_show); shellexecute(handle,'open',pchar('http://www.j2megame.com'),nil,nil,sw_show); end; //============================================================================== // 智能定位 //============================================================================== procedure TForm1.btn2Click(Sender: TObject); var bmpBackGround1,tmpBmp : TBitmap ; begin bmpBackGround1 := TBitmap.Create ; tmpBmp := TBitmap.Create ; bmpBackGround1.Assign( bmpBackGround ); tmpBmp := CreateBestWBValue(bmpBackGround1,GetBestWBValue2(bmpBackGround1)) ; Image1.Canvas.Draw( 0 , 0 , Self.FindEdge(tmpBmp)); bmpBackGround1.Free ; end; procedure TForm1.ScrollBar1Change(Sender: TObject); var bmpBackGround1 : TBitmap ; begin bmpBackGround1 := TBitmap.Create ; bmpBackGround1.Assign( bmpBackGround ); Image1.Canvas.Draw( 0 , 0 , CreateBestWBValue(bmpBackGround1,ScrollBar1.Position) ); bmpBackGround1.Free ; end; end. 图片较大,加载很慢 使用前 使用后 使用前 使用后