在Delphi中利用VFW和简易摄像头实现图像采集和处理
Delphi基本图像处理方法.
本文实例汇总了Delphi基本图像处理方法。
分享给大家供大家参考。
具体分析如下: //浮雕 procedureEmboss(SrcBmp,DestBmp:TBitmap;AzimuthChange:integer;overload; var i, j, Gray, Azimuthvalue, R, G, B: integer; SrcRGB, SrcRGB1, SrcRGB2, DestRGB: pRGBTriple; begin for i := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[i]; DestRGB := DestBmp.ScanLine[i]; if (AzimuthChange >= -180 and (AzimuthChange < -135 then begin if i > 0 then SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; Inc(SrcRGB1; SrcRGB2 := SrcRGB; Inc(SrcRGB2; end else if (AzimuthChange >= -135 and (AzimuthChange < -90 then begin if i > 0 thenSrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; Inc(SrcRGB2; end else if (AzimuthChange >= -90 and (AzimuthChange < -45 then begin if i > 0 then SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; end else if (AzimuthChange >= -45 and (AzimuthChange < 0 then begin SrcRGB1 := SrcRGB; if i > 0 then SrcRGB2 := SrcBmp.ScanLine[i-1] else SrcRGB2 := SrcRGB; end else if (AzimuthChange >= 0 and (AzimuthChange < 45 then begin SrcRGB2 := SrcRGB; if (i < SrcBmp.Height - 1 then SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; end else if (AzimuthChange >= 45 and (AzimuthChange < 90 then begin if (i < SrcBmp.Height - 1 then SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; end else if (AzimuthChange >= 90 and (AzimuthChange < 135 then begin if (i < SrcBmp.Height - 1 then SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; Inc(SrcRGB1; end else if (AzimuthChange >= 135 and (AzimuthChange <= 180 then begin if (i < SrcBmp.Height - 1 then SrcRGB2 := SrcBmp.ScanLine[i+1] else SrcRGB2 := SrcRGB; Inc(SrcRGB2; SrcRGB1 := SrcRGB; Inc(SrcRGB1; end; for j := 0 to SrcBmp.Width - 1 do begin if (AzimuthChange >= -180 and (AzimuthChange < -135 then begin Azimuthvalue := AzimuthChange + 180; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= -135 and (AzimuthChange < -90 then begin Azimuthvalue := AzimuthChange + 135; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= -90 and (AzimuthChange < -45 then begin if j=1 then Inc(SrcRGB1,-1; Azimuthvalue := AzimuthChange + 90;R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= -45 and (AzimuthChange < 0 then begin if j=1 then begin Inc(SrcRGB1,-1; Inc(SrcRGB2,-1; end; Azimuthvalue := AzimuthChange + 45; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= 0 and (AzimuthChange < 45 then begin if j=1 then begin Inc(SrcRGB1,-1; Inc(SrcRGB2,-1; end; Azimuthvalue := AzimuthChange; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= 45and (AzimuthChange < 90 then begin if j=1 then Inc(SrcRGB2,-1; Azimuthvalue := AzimuthChange - 45; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= 90 and (AzimuthChange < 135 then begin Azimuthvalue := AzimuthChange - 90;R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= 135 and (AzimuthChange <= 180 then begin Azimuthvalue := AzimuthChange - 135;R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end; R:=Min(R,255; R:=Max(R,0; G:=Min(G,255; G:=Max(G,0; B:=Min(B,255; B:=Max(B,0; Gray := (R shr 2 + (R shr 4 + (G shr 1 + (G shr 4 + (B shr 3; DestRGB.rgbtRed:=Gray; DestRGB.rgbtGreen:=Gray; DestRGB.rgbtBlue:=Gray; if (j=-180 and (AzimuthChange<-135 or ((AzimuthChange>=90 and (AzimuthChange<=180 then begin Inc(SrcRGB1; end; if (j=135 and (AzimuthChange<180 or ((AzimuthChange>=-180 and (AzimuthChange<=-90 then begin Inc(SrcRGB2; end;Inc(SrcRGB; Inc(DestRGB; end; end; end; procedureEmboss(Bmp:TBitmap;AzimuthChange:integer;ElevationChange:integer;WeightChange: integer;overload; var DestBmp:TBitmap; begin DestBmp:=TBitmap.Create; DestBmp.Assign(Bmp;Emboss(Bmp,DestBmp,AzimuthChange,ElevationChange,WeightChange;Bmp.Assign(DestBmp; end; //反色 procedure Negative(Bmp:TBitmap; var i, j: Integer; PRGB: pRGBTriple; begin Bmp.PixelFormat:=pf24Bit; for i := 0 to Bmp.Height - 1 do begin PRGB := Bmp.ScanLine[i]; for j := 0 to Bmp.Width - 1 do beginPRGB^.rgbtRed :=not PRGB^.rgbtRed ; PRGB^.rgbtGreen :=not PRGB^.rgbtGreen; PRGB^.rgbtBlue :=not PRGB^.rgbtBlue; Inc(PRGB; end; end; end; //曝光 procedure Exposure(Bmp:TBitmap; var i, j: integer; PRGB: pRGBTriple; beginBmp.PixelFormat:=pf24Bit; for i := 0 to Bmp.Height - 1 do begin PRGB :=Bmp.ScanLine[i]; for j := 0 to Bmp.Width - 1 do begin if PRGB^.rgbtRed<128 then PRGB^.rgbtRed :=not PRGB^.rgbtRed ; if PRGB^.rgbtGreen<128 thenPRGB^.rgbtGreen :=not PRGB^.rgbtGreen; if PRGB^.rgbtBlue<128 thenPRGB^.rgbtBlue :=not PRGB^.rgbtBlue; Inc(PRGB; end; end; end; //模糊 procedure Blur(SrcBmp:TBitmap; var i, j:Integer; SrcRGB:pRGBTriple; SrcNextRGB:pRGBTriple; SrcPreRGB:pRGBTriple; Value:Integer; procedure IncRGB; begin Inc(SrcPreRGB;Inc(SrcRGB; Inc(SrcNextRGB; end; procedure DecRGB; begin Inc(SrcPreRGB,-1;Inc(SrcRGB,-1; Inc(SrcNextRGB,-1; end; begin SrcBmp.PixelFormat:=pf24Bit; for i := 0 to SrcBmp.Height - 1 do begin if i > 0 then SrcPreRGB:=SrcBmp.ScanLine[i-1] else SrcPreRGB := SrcBmp.ScanLine[i]; SrcRGB := SrcBmp.ScanLine[i]; if i <SrcBmp.Height - 1 then SrcNextRGB:=SrcBmp.ScanLine[i+1] elseSrcNextRGB:=SrcBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if j > 0 then DecRGB; Value:=SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed; if j > 0 then IncRGB;Value:=Value+SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed; if j < SrcBmp.Width - 1 then IncRGB;Value:=(Value+SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed div 9; DecRGB; SrcRGB.rgbtRed:=value;if j > 0 then DecRGB;Value:=SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen; if j > 0 thenIncRGB;Value:=Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen; if j < SrcBmp.Width - 1 then IncRGB;Value:=(Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen div 9; DecRGB; SrcRGB.rgbtGreen:=value; if j > 0 then DecRGB;Value:=SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue; if j > 0 then IncRGB; Value:=Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue; if j < SrcBmp.Width - 1 then IncRGB;Value:=(Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue div 9; DecRGB; SrcRGB.rgbtBlue:=value; IncRGB; end; end; end; //锐化 procedureSharpen(SrcBmp:TBitmap; var i, j: integer; SrcRGB: pRGBTriple; SrcPreRGB: pRGBTriple; Value: integer; begin SrcBmp.PixelFormat:=pf24Bit; for i := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[i]; if i > 0 then SrcPreRGB:=SrcBmp.ScanLine[i-1] else SrcPreRGB:=SrcBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if j = 1 then Dec(SrcPreRGB;Value:=SrcRGB.rgbtRed+(SrcRGB.rgbtRed-SrcPreRGB.rgbtRed div 2;Value:=Max(0,Value; Value:=Min(255,Value; SrcRGB.rgbtRed:=value;Value:=SrcRGB.rgbtGreen+(SrcRGB.rgbtGreen-SrcPreRGB.rgbtGreen div 2;Value:=Max(0,Value; Value:=Min(255,Value; SrcRGB.rgbtGreen:=value;Value:=SrcRGB.rgbtBlue+(SrcRGB.rgbtBlue-SrcPreRGB.rgbtBlue div 2;Value:=Max(0,Value; Value:=Min(255,Value; SrcRGB.rgbtBlue:=value; Inc(SrcRGB; Inc(SrcPreRGB; end; end; end; [图像的旋转和翻转] 以下代码用ScanLine配合指针移动实现,用于24位色! //旋转90度 procedure Rotate90(const Bitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Height; Bmp.Height := Bitmap.Width; Bmp.PixelFormat := pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do beginrowOut := Bmp.ScanLine[i]; Inc(rowOut,Height - j; rowOut^ := rowIn^; Inc(rowIn; end;end; Bitmap.Assign(Bmp; end; //旋转180度 procedure Rotate180(constBitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap;Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Width; Bmp.Height := Bitmap.Height; Bmp.PixelFormat := pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut := Bmp.ScanLine[Height - j]; Inc(rowOut,Width - i; rowOut^ := rowIn^; Inc(rowIn; end; end; Bitmap.Assign(Bmp; end; //旋转270度procedure Rotate270(const Bitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Height; Bmp.Height := Bitmap.Width; Bmp.PixelFormat :=pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut :=Bmp.ScanLine[Width - i]; Inc(rowOut,j; rowOut^ := rowIn^; Inc(rowIn; end; end; Bitmap.Assign(Bmp; end; //任意角度 functionRotateBitmap(Bitmap:TBitmap;Angle:Integer;BackColor:TColor:TBitmap; vari,j,iOriginal,jOriginal,CosPoint,SinPoint : integer; RowOriginal,RowRotated : pRGBTriple; SinTheta,CosTheta : Extended; AngleAdd : integer; beginResult:=TBitmap.Create; Result.PixelFormat := pf24bit;Result.Canvas.Brush.Color:=BackColor; Angle:=Angle Mod 360; if Angle<0 then Angle:=360-Abs(Angle; if Angle=0 then Result.Assign(Bitmap else if Angle=90 then begin Result.Assign(Bitmap; Rotate90(Result;//如果是旋转90度,直接调用上面的代码 end else if (Angle>90 and (Angle<180 then begin AngleAdd:=90; Angle:=Angle-AngleAdd; end else if Angle=180 then begin Result.Assign(Bitmap; Rotate180(Result;//如果是旋转180度,直接调用上面的过程 end else if (Angle>180 and (Angle<270 then begin AngleAdd:=180; Angle:=Angle-AngleAdd; end else if Angle=270 then begin Result.Assign(Bitmap; Rotate270(Result;//如果是旋转270度,直接调用上面的过程end else if (Angle>270 and (Angle<360 then begin AngleAdd:=270; Angle:=Angle-AngleAdd; end else AngleAdd:=0; if (Angle>0 and (Angle<90 then begin SinCos((Angle+ AngleAdd * Pi / 180, SinTheta, CosTheta; if (SinTheta * CosTheta < 0 then begin Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta; Result.Height := Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta; end else begin Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta; Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta; end; CosTheta:=Abs(CosTheta; SinTheta:=Abs(SinTheta; if (AngleAdd=0 or (AngleAdd=180 then begin CosPoint:=Round(Bitmap.Height*CosTheta;SinPoint:=Round(Bitmap.Height*SinTheta; end else beginSinPoint:=Round(Bitmap.Width*CosTheta; CosPoint:=Round(Bitmap.Width*SinTheta; end; for j := 0 to Result.Height-1 do begin RowRotated := Result.Scanline[j]; for i := 0 to Result.Width-1 do begin Case AngleAdd of 0: begin jOriginal := Round((j+1*CosTheta-(i+1-SinPoint*SinTheta-1; iOriginal := Round((i+1*CosTheta-(CosPoint-j-1*SinTheta-1; end; 90: begin iOriginal := Round((j+1*SinTheta-(i+1-SinPoint*CosTheta-1; jOriginal := Bitmap.Height-Round((i+1*SinTheta-(CosPoint-j-1*CosTheta; end; 180: begin jOriginal := Bitmap.Height-Round((j+1*CosTheta-(i+1-SinPoint*SinTheta; iOriginal := Bitmap.Width-Round((i+1*CosTheta-(CosPoint-j-1*SinTheta; end; 270: begin iOriginal := Bitmap.Width-Round((j+1*SinTheta-(i+1-SinPoint*CosTheta; jOriginal := Round((i+1*SinTheta-(CosPoint-j-1*CosTheta-1; end; end; if (iOriginal >= 0 and (iOriginal <= Bitmap.Width-1and (jOriginal >= 0 and (jOriginal <=Bitmap.Height-1 then begin RowOriginal := Bitmap.Scanline[jOriginal];Inc(RowOriginal,iOriginal; RowRotated^ := RowOriginal^; Inc(RowRotated; end else begin Inc(RowRotated; end; end; end; end; end; //水平翻转 procedure FlipHorz(const Bitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap;Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Width; Bmp.Height := Bitmap.Height; Bmp.PixelFormat := pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut := Bmp.ScanLine[j]; Inc(rowOut,Width - i; rowOut^ := rowIn^; Inc(rowIn; end; end; Bitmap.Assign(Bmp; end; //垂直翻转 procedureFlipVert(const Bitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple;Bmp:TBitmap; Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Height; Bmp.Height := Bitmap.Width; Bmp.PixelFormat := pf24bit;Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do beginrowIn := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut :=Bmp.ScanLine[Height - j]; Inc(rowOut,i; rowOut^ := rowIn^; Inc(rowIn; end; end; Bitmap.Assign(Bmp; end; [亮度、对比度、饱和度的调整] 以下代码用ScanLine配合指针移动实现! function Min(a, b: integer: integer; begin if a < b then result := a else result := b; end; function Max(a, b: integer: integer; begin if a > b then result := a else result := b; end; //亮度调整 procedure BrightnessChange(constSrcBmp,DestBmp:TBitmap;ValueChange:integer; var i, j: integer; SrcRGB, DestRGB: pRGBTriple; begin for i := 0 to SrcBmp.Height - 1 do begin SrcRGB :=SrcBmp.ScanLine[i]; DestRGB := DestBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if ValueChange > 0 then begin DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange; DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange; DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange; end else begin DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed + ValueChange; DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + ValueChange; DestRGB.rgbtBlue := Max(0,SrcRGB.rgbtBlue + ValueChange; end; Inc(SrcRGB; Inc(DestRGB; end; end; end; //对比度调整 procedure ContrastChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer; var i, j: integer; SrcRGB, DestRGB: pRGBTriple; begin for i := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[i]; DestRGB := DestBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if ValueChange>=0 then begin if SrcRGB.rgbtRed >= 128 then DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange else DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed - ValueChange; if SrcRGB.rgbtGreen >= 128 then DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange else DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen - ValueChange; ifSrcRGB.rgbtBlue >= 128 then DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue - ValueChange; end else begin if SrcRGB.rgbtRed >= 128 then DestRGB.rgbtRed := Max(128,SrcRGB.rgbtRed + ValueChange else DestRGB.rgbtRed := Min(128, SrcRGB.rgbtRed - ValueChange; if SrcRGB.rgbtGreen >= 128 then DestRGB.rgbtGreen := Max(128, SrcRGB.rgbtGreen + ValueChange else DestRGB.rgbtGreen := Min(128,SrcRGB.rgbtGreen - ValueChange; if SrcRGB.rgbtBlue >= 128 thenDestRGB.rgbtBlue := Max(128, SrcRGB.rgbtBlue + ValueChange elseDestRGB.rgbtBlue := Min(128, SrcRGB.rgbtBlue - ValueChange; end; Inc(SrcRGB; Inc(DestRGB; end; end; end; //饱和度调整 procedure SaturationChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer; var Grays: array[0..767] of Integer; Alpha: array[0..255] of Word; Gray, x, y: Integer; SrcRGB,DestRGB: pRGBTriple; i: Byte; begin ValueChange:=ValueChange+255; for i := 0 to 255 do Alpha[i] := (i * ValueChange Shr 8; x := 0; for i := 0 to 255 do begin Gray := i - Alpha[i]; Grays[x] := Gray; Inc(x; Grays[x] := Gray; Inc(x; Grays[x] := Gray; Inc(x; end; for y := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[Y]; DestRGB := DestBmp.ScanLine[Y]; for x := 0 to SrcBmp.Width - 1 do begin Gray :=Grays[SrcRGB.rgbtRed + SrcRGB.rgbtGreen + SrcRGB.rgbtBlue]; if Gray +Alpha[SrcRGB.rgbtRed]>0 then DestRGB.rgbtRed := Min(255,Gray +Alpha[SrcRGB.rgbtRed] else DestRGB.rgbtRed := 0; if Gray +Alpha[SrcRGB.rgbtGreen]>0 then DestRGB.rgbtGreen := Min(255,Gray +Alpha[SrcRGB.rgbtGreen] else DestRGB.rgbtGreen := 0; if Gray +Alpha[SrcRGB.rgbtBlue]>0 then DestRGB.rgbtBlue := Min(255,Gray +Alpha[SrcRGB.rgbtBlue] else DestRGB.rgbtBlue := 0; Inc(SrcRGB; Inc(DestRGB; end; end; end; //RGB调整 procedureRGBChange(SrcBmp,DestBmp:TBitmap;RedChange,GreenChange,BlueChange:integer; var SrcRGB, DestRGB: pRGBTriple; i,j:integer; begin for i := 0 to SrcBmp.Height- 1 dobegin SrcRGB := SrcBmp.ScanLine[i]; DestRGB :=DestBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if RedChange> 0 then DestRGB.rgbtRed:= Min(255, SrcRGB.rgbtRed + RedChange else DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed + RedChange; if GreenChange> 0 then DestRGB.rgbtGreen :=Min(255, SrcRGB.rgbtGreen + GreenChange else DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + GreenChange; if BlueChange> 0 then DestRGB.rgbtBlue :=Min(255, SrcRGB.rgbtBlue + BlueChange else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + BlueChange; Inc(SrcRGB; Inc(DestRGB; end; end; end; [颜色调整] //RGB<=>BGR procedure RGB2BGR(const Bitmap:TBitmap; var X: Integer; Y: Integer; PRGB: pRGBTriple; Color: Byte; begin for Y := 0 to (Bitmap.Height - 1 do begin forX := 0 to (Bitmap.Width - 1 do begin Color := PRGB^.rgbtRed; PRGB^.rgbtRed := PRGB^.rgbtBlue; PRGB^.rgbtBlue := Color; Inc(PRGB; end; end end; end; //灰度化(加权 procedure Grayscale(const Bitmap:TBitmap; var X: Integer; Y: Integer; PRGB: pRGBTriple; Gray: Byte; begin for Y := 0 to (Bitmap.Height - 1 do begin PRGB := Bitmap.ScanLine[Y]; for X := 0 to (Bitmap.Width - 1 do begin Gray := (77 * Red + 151 * Green + 28 * Blue shr 8; PRGB^.rgbtRed:=Gray; PRGB^.rgbtGreen:=Gray;PRGB^.rgbtBlue:=Gray; Inc(PRGB; end; end; end; 绘图区-即窗口显示图像的区域,亦可为全屏幕(在全屏幕下绘图的效果比一般窗口下好)中心点-即要绘图区显示的中心点在原始图像的坐标(声明:这个概念特别重要)先说说图像的放大,要放大一张图片,我们一般的做法是直接放大图像,但本文介绍的方法仅放大我们能够看到的部分,放大分两种情况,一种是放大后比绘图区还要小,这种情况没什么好说,当然是显示全部的图像;第二种是放大后的图像比绘图区大,这才是我们今天要讨论的重点话题,这种情况下我们先要确定图像放大后的大小,然后根据“中心点”计算在原始图像的位置和大小,最后把截取的图像放大到绘图区。
DIY个照相机-Delphi实现摄像头拍照功能
简介:本⽂提供⼀段完整的Delphi代码,实现利⽤摄像头进⾏拍照的功能。
注意需要TVideoCap控件⽀持。
procedure Tfrm1.Button2Click(Sender: TObject); Var jpeg: TJPEGImage; bmp: TBitmap; MyStm:TMemoryStream; strfilename,strcard:String; begin inherited; strfilename:=extractfilepath(Application.ExeName); with DBEdit12.DataSource.DataSet do begin if not VideoCap1.SaveAsDIB then begin ShowMessage('拍摄照⽚失败'); Abort; end;// bmp:= TBitmap.Create; try bmp.LoadFromFile(strfilename+ 'Capture.bmp' ); MyStm:=TMemoryStream.Create; jpeg:= TJPEGImage.Create; try jpeg.Assign( bmp ); press; jpeg.SaveTofile( strfilename+'Capture.jpg'); strfilename:=strfilename+'Capture.jpg'; jpeg.LoadFromFile(strfilename); jpeg.SaveToStream(MyStm); MyStm.Position:=0; OpenQry(query1,'select count(1) as cnt from tb_photo where card_no='''+strcard+'''');//先查找是否有此卡号 OpenQry(pubqry,'select * from tb_photo where card_no='''+strcard+'''');//打开卡号数据表 {OpenQry是⾃定义打开数据表的函数 OpenQry(qry1:TQuery,ssql:String); begin with qry1 do beign if active then close; sql.clear; sql.add(ssql); try open catch on E: Exception do ErrorDialog(E.Message, E.HelpContext); end;//try end; end; } with query1 do begin if pubqry.Fields[0].AsInteger >0 then //先判断此卡号的图⽚是否存在,若存在,替换;否则,插⼊。
用Delphi编写视频软件
用Delphi编写视频聊天软件内容概要:一、引言我们知道视频聊天软件的关键技术在于采集视频,并实时传输给聊天软件在线的人。
对于视频的采集,这里采用微软公司的关于数字视频的一个软件包VFW(Video for Windows)。
相信很多人对它都很熟习,VFW能使应用程序一、引言咱们明白视频交谈软件的关键性能在于采集视频,并实时传输给交谈软件在线的人。
对于视频的采集,那里采用Microsoft个人公司的涉及数字视频的一个的软件包VFW(视频 for win界面)。
相信很多人对它都很熟习,VFW能使实际运用程序经过数字化设备从习惯的模仿视频源得到数字化的视频剪辑,VFW的一个的关键思想是播放时不需求专用Hardware 。
为了解决数字视频数据量大的难点,需求对停止压缩,而VFW招进了AVI的文档达标。
该达标未规定如何对视频停止捕捉、压缩及播放,仅规定视频和MP3该如何存储在硬盘上及在AVI文档中交替存储视频帧和与之相匹对相配的MP3数据。
经过VFW,开发经过发送消息或设置属性来捕捉、播放和编辑视频剪辑。
当用户在安装VFW时,安装程序会自动地安装配置视频所需求的组件,如设备驱动程序、视频压缩程序等。
VFW主要由6个模块组成。
VFW功能模块:AVICAP.DLL 包含运行视频捕捉的参数,它给AVI文档的I/O处理和视频、MP3设备驱动程序帮助一个的高级接口MSVIDEO.DLL 包含一套特殊的DrawDib参数,用来处理屏幕上的视频操作MCIAVI.DRV 包括对VFW的MCI命令解释器的驱动程序AVIFILE.DLL 包含由达标多媒体I/O(mmio)参数帮助的更高的命令,用来访问.AVI文档ICM 压缩管理器,用于管理的视频压缩/解压缩的编译码器(Codec)ACM MP3压缩管理器,帮助与ICM相似的服务,适用于波形MP3对于视频的传输,咱们应用UDP来传,由于UDP传输速度快,TCP是面向连接的,建立连接时双方需经过三次握手,数据传输可靠,FTP、telnet等那是基于TCP 的,UDP是面向非连接的,发出消息不需对方确认,但那样速度比TCP快,但有估计丢失数据,象SMTP、tftp等那是基于UDP的。
Dephi实现屏幕录像
Dephi实现屏幕录像delphi利用VFW函数实现录制屏幕的功能:1.通过Timer实现抓屏,将屏幕抓图存为BMP格式。
2.调用AVIFileInit初始化3.调用AVIFileOpen创建视频文件4.调用AVIFileCreateStream创建视频流5.调用AVIMakeCompressedStream压缩视频流6.调用AVIStreamSetFormat设置视频流格式7.调用AVIStreamWrite写入视频8.调用AVIStreamClose关闭视频流指针,AVIFileRelease释放视频文件,AVIFileExit关闭视频文件。
源码:1.抓屏存为BMP//抓屏幕, Flag = SRCCOPY,不抓透明窗口,Flag=SRCCOPY or CAPTUREBLT 抓透明窗口//CAPTUREBLT要自己定义//const//{$ifndef CAPTUREBLT}// CAPTUREBLT = $40000000;//{$endif}varScreenBmp: TBitmap;PicIndex: Integer; //图片序号RecTransFlag: Cardinal; //录制屏幕标志,是否录制透明窗体AppPath:string; //应用程序路径TempPath:string; //临时文件夹路径BmpFileName:string; //BMP文件存储路径procedure TForm1.FormCreate(Sender: TObject);beginPicIndex := 0;BmpFileName := '';ScreenBmp := TBitmap.Create;ScreenBmp.PixelFormat := pf24bit;ScreenBmp.Width := Screen.Width;ScreenBmp.Height := Screen.Height;ScreenBmp.Canvas.Brush.Style := bsClear;RecPause := False;//不录制透明窗体RecTransFlag := SRCCOPY;//录制透明窗体//RecTransFlag := SRCCOPY or CAPTUREBLT;AppPath := ExtractFilePath(Application.ExeName);TempPath := AppPath + 'Temp\';if not DirectoryExists(TempPath) thenCreateDirectory(PAnsiChar(TempPath), nil);end;procedure TForm1.DrawCursorToBmp(var ScrBmp: TBitmap);varhCur : HICON;MousePt: TPoint;beginif not Assigned(ScrBmp) thenExit;hCur := GetCursor();GetCursorPos(MousePt);// 画光标DrawIcon(ScrBmp.canvas.handle, MousePt.x, MousePt.y, hCur); end;procedure TForm1.Timer1Timer(Sender: TObject);vardc: HDC;beginDC := GetDC(0);tryBitBlt(ScreenBmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, dc, 0, 0, Flag);finallyReleaseDC(0, dc);end;//根据标记判断是否画上光标DrawCursorToBmp(ScreenBmp);BmpFileName := TempPath + IntToStr(PicIndex) + '.bmp';ScreenBmp.SaveToFile(BmpFileName );end;tryInc(PicIndex);excepton EIntOverflow doend;procedure TForm1.Button1Click(Sender: TObject);begintimer1.Enabled := True;end;2.取保存的bmp图片生成avi并添加声音.uses VFW;varAviFileName:string; //AVI文件存储路径Tempbmp:TBitmap; //生成AVI前读出的BMPfunction GetBitmapData(bmp: TBitmap): TImageData;beginbmp.PixelFormat := pf24bit;Result.Width := bmp.Width;Result.Height := bmp.Height;Result.Stride := Result.Width shl 2;Result.Scan0 := bmp.ScanLine[Result.Height - 1];Result.PixelFormat := -1; // Windows bitmap format flagResult.Reserved := 0;end;procedure CreateAVI;varhr: Integer;Strhdr: TAVIStreamInfo; //AVI流信息Wavehdr: TWaveFormatEx;Opts: TAVICOMPRESSOPTIONS; //压缩选项POpts: PAVICOMPRESSOPTIONS; //压缩选项指针Bi: BITMAPINFOHEADER; //BMP头信息B: Boolean;P: Pointer;i: Integer;bmpData: TImageData;nRet : Integer;beginif FileExists(AviFileName) thenDeleteFile(AviFileName);AVIFileInit;hr := AVIFileOpen(PFile, PChar(AviFileName), OF_CREATE or OF_WRITE, nil);if (hr <> 0) thenExit;//设置AVI流信息ZeroMemory(@Strhdr, SizeOf(TAVIStreamInfo));strhdr.fccType := streamTypeVIDEO;strhdr.fccHandler := mmioFOURCC('D', 'I', 'V', 'X');strhdr.dwFlags := 0;strhdr.dwCaps := 0;strhdr.wPriority := 0;strhdr.wLanguage := 0;strhdr.dwScale := 1;strhdr.dwRate :=5; //pfsstrhdr.dwStart := 0;strhdr.dwLength := 0;strhdr.dwInitialFrames := 0;strhdr.dwSuggestedBufferSize := ((Screen.Width * 3 + 3) and $FFFC) * screen.Height; //Screen.Height * screen.Width * 3;strhdr.dwQuality := 0;strhdr.dwSampleSize := 1;strhdr.rcFrame := Rect(0, 0, Screen.Width, Screen.Height);strhdr.dwEditCount := 0;strhdr.dwFormatChangeCount := 0;strhdr.szName[0] := #0;strhdr.szName[1] := #0;//设置WAV流信息ZeroMemory(@Wavehdr, SizeOf(TWaveFormatEx));Wavehdr.cbSize := 0;Wavehdr.nChannels := 1;Wavehdr.wFormatTag:= 1;Wavehdr.wBitsPerSample := 16;Wavehdr.nSamplesPerSec := 8000;Wavehdr.nBlockAlign := Wavehdr.wBitsPerSample *Wavehdr.nChannels div 8;Wavehdr.nAvgBytesPerSec := Wavehdr.nBlockAlign *Wavehdr.nSamplesPerSec;ZeroMemory(@opts, SizeOf(TAVICOMPRESSOPTIONS));//设置压缩信息//Indeo? Video 5.10opts.fccType := streamTypeVIDEO; // vidsopts.fccHandler := 808810089;opts.dwKeyFrameEvery := 0;opts.dwQuality := 8500;opts.dwBytesPerSecond := 0;opts.dwFlags := 8;opts.lpFormat := nil;opts.cbFormat := 0;opts.cbParms := 48;opts.dwInterleaveEvery := 0;//设置BMP头信息ZeroMemory(@bi, SizeOf(BITMAPINFOHEADER));bi.biSize := SizeOf(bi);bi.biWidth := Screen.Width;bi.biHeight := Screen.Height;bi.biPlanes := 1;bi.biBitCount := 24;bi.biCompression := 0;bi.biSizeImage := ((Screen.Width * 3 + 3) and $FFFC) * screen.Height; //(((bih.biWidth * 3) + 3) & 0xFFFC) * bih.biHeight//Screen.Height * screen.Width * 3; //_stride * _height;bi.biXPelsPerMeter := 0;bi.biYPelsPerMeter := 0;bi.biClrUsed := 0;bi.biClrImportant := 0;hr := AVIFileCreateStream(PFile, PSrcStream, @strhdr);if (hr <> 0) thenExit;hr := AVIMakeCompressedStream(PCompStream, PSrcStream, @opts, nil);if (hr <> 0) thenAbort;hr := AVIStreamSetFormat(PCompStream, 20, @bi, 40);if (hr <> 0) thenAbort;Tempbmp := TBitmap.Create;Tempbmp.LoadFromFile(bmpFile);bmpData := GetBitmapData(Tempbmp);hr := AVIStreamWrite(PCompStream,FrameCount, //存在第几帧1,bmpData.Scan0,((Screen.Width *3 + 3) and $FFFC) * screen.Height,0,nil,nil);if (hr <> 0) thenAbort;//添加声音AddAVISound;end;end;procedure AddAVISound;varwfx: TWAVEFORMATEX;buf: array of char;wav: PWavChunk;hf: HWND;size: DWORD;Strhdr: TAVIStreamInfo;hr: Cardinal;numbytes, numsamps: DWORD;beginZeroMemory(@wfx, sizeof(TWAVEFORMATEX));hf := CreateFile(PChar(WavFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);if (hf = 0) thenExit;trysize := GetFileSize(hf, nil);SetLength(buf, size);ReadFile(hf, buf[0], size, size, nil);finallyCloseHandle(hf);end;wav := PWavChunk(buf);wfx.wFormatTag := wav.fmt.wFormatTag;wfx.cbSize := 0;wfx.nAvgBytesPerSec := wav.fmt.dwAvgBytesPerSec;wfx.nBlockAlign := wav.fmt.wBlockAlign;wfx.nChannels := wav.fmt.wChannels;wfx.nSamplesPerSec := wav.fmt.dwSamplesPerSec;wfx.wBitsPerSample := wav.fmt.wBitsPerSample;ZeroMemory(@Strhdr, SizeOf(TAVIStreamInfo));Strhdr.fccType := streamtypeAUDIO;Strhdr.dwScale := wfx.nBlockAlign;Strhdr.dwRate := wfx.nSamplesPerSec * wfx.nBlockAlign;Strhdr.dwSampleSize := wfx.nBlockAlign;Strhdr.dwQuality := DWORD(-1);hr := AVIFileCreateStream(PFile, PWavStream, @Strhdr);if (hr <> 0) thenbeginif (buf <> nil) thenbuf := nil;Exit;end;hr := AVIStreamSetFormat(PWavStream, 0, @wfx, SizeOf(TWAVEFORMATEX)); if (hr <> 0) thenbeginif (buf <> nil) thenbuf := nil;Exit;end;// now we can write the datanumbytes := wav.dat.size;if wfx.wBitsPerSample <> 0 thennumsamps := numbytes * 8 div wfx.wBitsPerSampleelsenumsamps := 0;hr := AVIStreamWrite(PWavStream, 0, numsamps, wav, numbytes, 0, nil, nil);if (buf <> nil) thenbuf := nil;if (hr <> 0) thenExit;。
基于Delphi视频采集个人照片的实现
视频捕获到后, 保存方法一般有以下几种: ① 保存在 BMP 静态图中; ②保存在 AVI 动画 文件中; ③拷贝到剪贴板中, 以供其他程序调 用。
下面介绍在 Delphi 中如何将视频捕获的结果 拷贝到剪贴板中,并由 Image 组件粘贴剪贴板中内 容的方法。 图 1 为视频捕获的结果。
图 1 视频捕获Βιβλιοθήκη 结果2008 年第 5 期 91
··
宁波职业技术学院学报
一定的优势,它能直接访问视频缓冲区,不需要生 成中间文件,实时性很强,效率很高。 同时,它也可 将数字视频捕获到文件。
利用 AVICAP 进行视频捕获的开发步骤[2]有: ①创建“捕获窗”;②关联捕获窗和驱动程序;③设 置视频设备的属性;④打开预览。
通过以上 4 步就可以建立一个基本的视频捕 获程序。 下面介绍 2 种方法来实现基于 Delphi 的 视频捕获。
视频捕获方法一: (1) 打 开 Delphi, 新 建 一 个 工 程 , 并 把 VFW. PAS 加 到 USE 中 。 需 要 说 明 的 是 , 微 软 的 VFW SDK 没有 Delphi 版,不过在网上可以下载到 VFW. PAS 文件,VFW.PAS 文件声明了调用 DLL 中的各 个函数和变量。 (2)新建一个窗口 Form1,并 在 窗 口 上 放 置 一 个 Panel,添加二个按钮,Caption 设 置 为 “开 始 ”和 “停止”,并定义一个全局变量 Cwin1:THandle; / / 定 义捕捉窗句柄。 “开始”按钮代码如下: Cwin1:=capCreateCaptureWindowA (‘My CAP Win’,WS_CHILD or WS_VISIBLE,Panel1. Left,Panel1.Top,Panel1.Width,Panel1.Height, Form1.Handle,0); / / 创建捕获窗 capDriverConnect (Cwin1,0); / / 关 联 捕 获 窗 和驱动程序 capPreviewRate (Cwin1,66); / / Rate 设 置 速 度 CapPreviewScale (Cwin1,TRUE); / / Scale 设 置预览的比例 capPreview(Cwin1,TRUE); / / 打开预览 运行 Delphi,这时也可以在屏幕上看到来自摄 像头的图像了。 “停止”按钮代码如下: capCaptureAbort(Cwin1); / / 停止捕获 capDriverDisconnect(Cwin1); / / 将捕获窗和 驱动器断开 视频捕获方法二: 使用微软的 AVICAP32.DLL 实现对视频摄像 头控制: (1)打开 Delphi,新建一个工程,并新建一个窗 口。 先定义一个函数和部分常量 (定义成全局类 型)。
用VFW和简易摄像头实现图像采集和处理
说明:Vfw单元文件当中包含了V聊常用模块的各个函
数和变量。 3)定义变量,方法如下:
Private
hWndC:THandle;/片甫获窗句柄 4)在窗体}放置一个T Panel控件、四个TBitBtn控件、 两个TRadioButton控件、两个TSaveDialog控件。T Panel控件 用来显示视频,四个TBitBtn控件分别用作打开视频、开始捕 获、停止捕获、关闭视频,两个TRadioButton控件用来选择 是进行视频流捕获还是单帧捕获,两个TSaveDialog控件用来 指定捕获的视频流文件或单帧文件的文件名。 5)编写相应控件的代码,在开始捕获TbitBtn控件中写入 以下代码: procedure Tforml.BitBtn2Click(Sender:TObject); var pathName:string;
利用函数SendMessage(hWndC,WM—CAP—SET—PREVIEWR ATE,66,0)和函数SendMessage(hWndC,WM—CAP_SET_SCAL E,1,0)设置预览的速度与比例,也可以使用设备的默认值。 利用函数SendMessage(hWndC,WM_CAP_SET_OVERLAY,l, 0)选择是否采用叠加模式预览,以保证视频速度快,占用系 统资源少。最后利用函数sendMessage(hWndC, WM_CAP_SET_PREVIEW,1,o)实现视频的预览。
Delphi中图像的像素级操作
Delphi中图像的像素级操作Delphi中图像的像素级操作华软源码一般的可视性编程语言,如VB本身只具有图像的一般显示功能, 加上简单的图像伸缩处理, 在进行一些图像复杂的特技显示时必须借助于Windows的有关API 函数。
但Delphi为用户提供了更为完善的图像处理能力, 依靠它本身的功能完全可以实现图像的像素级操作?疚慕樯芰薉elphi中像素级图像操作的基本原理、应用和实例。
一、基本原理在Delphi中有很多控件具有CANVAS属性, 即所谓的画布, 利用这一属性可以在控件的表面进行图形图像处理工作, 其中有一个CopyRect命令, 具体参数格式:Copyrect(Dest:TRect;Canvas:Tcanvas;Source:TRect);其中:Dest:目标画布矩形 Canvas:源画布 Source:源矩形,其功能是把图像从一个源矩形RECT内,复制到目标矩形RECT内, 复制的图像具有自动伸缩性质。
从这个命令的表面看只能进行图像的全部或部分复制功能,其实如果把矩形RECT定义成只有一个像素大小, 即可以从源图像中取出一个像素点, 即进行图像的像素级操作, 比如:Rect(0,0,1,1)可指定某图像源的左上角第一个像素。
二、像素级操作的应用图像的像素级操作可广泛应用在图像的特技显示效果制作工作中, 并且可以实现较为复杂的图像处理工作, 举例如下:1.图像的旋转: 在Delphi中利用其他方法显示图像时,比如利用图像框IMAGE 或者DRAW命令, 只能按原图的方向显示, 进行图像的旋转显示必须以像素为单位进行处理,重新安排像素的排列位置, 比如按先横向后纵向的方式读取原图像,然后按先纵向后横向的方式写像素,最终将形成旋转90度的图像,按同样的原理可形成旋转180度或270度的图像。
2.图像尺寸的改变: 图像尺寸的改变在Windows 中好象并不需要像素级操作, 利用图像框的伸缩性可以简单地完成这一工作, 但利用像素操作改变图像尺寸是图像放大或缩小操作的根本, 并且可以具有更高的精确和更高的灵活性?热绾嶙菹蚓扛粢坏闳∫幌袼? 连续写在目标画布上, 即可使图像缩小到原来的四分之一;而读出一点像素后, 在目标画布上连续写两点以上, 即可实现图像的放大显示。
Delphi实现网络视频编程
用Delphi实现网络视频编在MSN、QQ等聊天类的应用程序中,都应用到了网络视频技术。
Delphi使用Object Pascal 语言是一种完全面向对象语言,可以开发出灵活强大的程序,开发网络视频程序也不在话下。
一个完整的网络视频程序应包括以下几个关键技术:视频捕获、视频压缩与解压、数据传输。
一、视频获捕1.基本概念微软为软件开发人员提供了一个专门用于视频捕获的VFW (Video for Windows) SDK,为在Windows系统中实现视频捕获提供了标准的接口,从而大大方便了视频捕获程序的开发。
由于VFW SDK只有VC和VB版,没有Delphi版,因此需要在Delphi中重新声明DLL中的各个函数和变量(可以参考MSDN中的VC的函数声明以及变量定义,也可以从网上下载写好的头文件vfw.pas)。
VFW是Microsoft 1992年推出的关于数字视频的一个软件包,它能使应用程序数字化并播放从传统模拟视频源得到的视频剪辑。
VFW的一个关键思想是播放时不需要专用硬件,为了解决数字视频数据量大的问题,需要对数据进行压缩。
它引进了一种叫A VI的文件标准,该标准未规定如何对视频进行捕获、压缩及播放,仅规定视频和音频该如何存储在硬盘上,在A VI文件中交替存储视频帧和与之相匹配的音频数据。
VFW给程序员提供VBX和A VICap 窗口类的高级编程工具,使程序员能通过发送消息或设置属性来捕获、播放和编辑视频剪辑。
2.A VICap编程A VICap支持实时的视频流捕获和单帧捕获并提供对视频源的控制,它能直接访问视频缓冲区,不需要生成中间文件,实时性很强,效率很高。
同时,它也可将数字视频捕获到文件。
A VICap编程的基本步骤包括:第一步,创建A VICap窗口。
通过capCreateCaptureWindow函数创建一个捕获窗,所有的捕获操作及其设置都以它为基础。
窗口风格一般为WS_CHILD和WS_VISIBLE。
Delphi编程控制摄像头
Delphi编程控制摄像头你的电脑有没有摄像头?看到别人用QQ玩视屏你会不会去想怎么实现的?这里介绍使用DELPHI使用MS的A VICAP32.DLL就可轻松的实现对摄像头编程,假如再加上你的网络编程水平,实现一个视屏聊天就不成什么问题了。
看看下面代码的代码:constWM_CAP_START=WM_US...你的电脑有没有摄像头?看到别人用QQ玩视屏你会不会去想怎么实现的?这里介绍使用DELPHI使用MS的A VICAP32.DLL就可轻松的实现对摄像头编程,假如再加上你的网络编程水平,实现一个视屏聊天就不成什么问题了。
看看下面代码的代码:constWM_CAP_START=WM_USER;constWM_CAP_STOP=WM_CAP_START 68; constWM_CAP_DRIVER_CONNECT=WM_CAP_START 10;constWM_CAP_DRIVER_DISCONNECT=WM_CAP_START 11;constWM_CAP_SA VEDIB=WM_CAP_START 25;constWM_CAP_GRAB_FRAME=WM_CAP_START 60;constWM_CAP_SEQUENCE=WM_CAP_START 62;constWM_CAP_FILE_SET_CAPTURE_FILEA=WM_CAP_S TART 20;constWM_CAP_SEQUENCE_NOFILE=WM_CAP_START 63 constWM_CAP_SET_OVERLAY=WM_CAP_START 51 constWM_CAP_SET_PREVIEW=WM_CAP_START 50constWM_CAP_SET_CALLBACK_VIDEOSTREAM=WM_C AP_START 6;constWM_CAP_SET_CALLBACK_ERROR=WM_CAP_STA RT 2;constWM_CAP_SET_CALLBACK_STATUSA=WM_CAP_ST ART 3;constWM_CAP_SET_CALLBACK_FRAME=WM_CAP_STA RT 5;constWM_CAP_SET_SCALE=WM_CAP_START 53 constWM_CAP_SET_PREVIEWRATE=WM_CAP_START 52functioncapCreateCaptureWindowA(lpszWindowName:PCHA R;dwStyle:longint;x:integer;y:integer;nWidth:integer;nHeight:integer;ParentWin:HWND;nId:integer):HWND;STDCALLEXTERNAL‘A VICAP32.DLL‘;上面的代码就是我们主要用到的一个函数和常量的定义。
基于VfW的实时视频图像采集处理程序设计
(CAPSTA TUS) ) ; cap GetVideo Format (cap Wnd , bmp Info , ( WORD) vfs) ; 5) 获取并设置捕获控制参数 : capCapture GetSetup ( cap Wnd , &Cap Parm , sizeof
(Cap Parm) ) ; Cap Parm. dwRequestMicroSecPerFrame = 66667 ; ( 15
Abstract : Since t he growing application of realtime video acquisition and process technology in t he fields of security moniter , video conference and network chatting ,t his paper introduces how to develop t he framework of video image acquistion project based on video for windows library ;and because call - back function being t he common interface of video card on capturing and processing video data ,t his paper analyzes how to process t he acquired video data in real time wit h self - defined call - back function ,and explains t he adoption of grads differential met hod to acquire t he active contour of video image in real time , which could be applied in t he video image processing project , such as video object moniter , face detection. Key words :capture window ;self - defined call back function ;grads differential image
Delphi实现计算机视觉常用图像处理算法
Delphi实现计算机视觉常用图像处理算法摘要:由于图像处理涉与到了大量的程序编制工作,因此,如何合理选择一种简洁高效的编程工具,减少研究工作中的复杂性,就成为了计算机数字图像处理中不可回避的问题。
本文就利用Delphi实现对计算机视觉中常用图像处理方法。
关键词:计算机视觉;数字图像处理;DelphiThe Algorithms for Image Processing ofComputerVision Implemented in Delphi Abstract:Image processing involves lots ofprogramming. Hence how to select a programming toolwith simplicity andhigh efficiency became an unavoidable problem in computer-based digital image processing. For reference, this articleimplemented the image processing algorithms in common usewith Delph.iKey words:computer vision; digital image processing; Delphi1 引言计算机视觉[1]是采用各种成象系统代替视觉器官作为输入手段,并通过计算机技术来完成替代大脑完成处理和解释任务的一门学科,其最终研究目标就是使计算机能象人那样通过视觉观察和理解世界,具有自主适应环境的能力。
在计算机视觉的发展过程中,图像处理、模式识别、图像理解这一系列相关学科的发展对其有着至关重要的推动作用。
本文中,就将如何利用Delphi开发工具对计算机视觉中应用较多的一些数字图像处理方法进行实现进行详细讨论。
1 Delphi实现技术在Delphi中,专门定义了一组对象和部件用以绘制图形[2],完成一些简单的图像功能。
利用Delphi?3.0开发微机数据采集与处理软件系统
<meta charset="utf-8"/><h1 align="center">利用Delphi 3.0开发微机数据采集与处理软件系统</h1><div bdsfid="69" class="content"><p bdsfid="103">利用Delphi 3.0开发微机数据采集与处理软件系统</p>张建军(中国人民解放军合肥炮兵学院研究生系)<br bdsfid="104"/> <br bdsfid="105"/> 摘要:结合开发“无线电话务模拟训练系统”Win32版软件的实例,本文详细介绍利用Delphi3.0开发微机数据采集与处理软件系统的方法。
<br bdsfid="106"/> <br bdsfid="107"/> <br bdsfid="108"/> 关键词:DelphiADCDAC<br bdsfid="109"/><br bdsfid="110"/>微机数据采集与处理系统简介<br bdsfid="111"/> 数据采集与处理是计算机应用的一个重要分支,主要研究信息数据的采集、存贮、处理及控制等内容。
70年代以来,由于微机技术的快速发展及其在军、民用工程领域的广泛应用,尤其是适于通用微机(如IBMPC系列)使用的板卡级数据采集产品的大量出现,以微机为核心的可编程数据采集与处理技术得到迅速发展。
现在的微机,只需在其扩展槽内插上一块数据采集板,并辅以应用软件,即可组成一套微机数据采集与处理系统,实现信息处理和实时控制功能。
基于Delphi的摄像头软件控制设计
河南科技学院200X 届本科毕业论文(设计)论文(设计)题目:基于Delphi的摄像头软件控制设计学生姓名:X X所在院系:信息工程学院所学专业:计算机科学与技术导师姓名:XXX完成时间:2007-05-20摘要本文介绍了在Delphi中如何实现视频捕捉、音频的同步录制、图像的实时捕获、视频流的回放等功能,着重分析了视频监控系统中高性能硬盘录像与适时保存的实现。
本设计主要利用微软公司的VFW软件包和AVICap窗口类的成员函数来实现视频流的捕获,并借助于Delphi自带的多媒体组件Mediaplayer来实现音频信息的同步录制;对于捕捉到的视频信息,通过帧回调函数将其送往用户视窗,完成视频流的适时显示;对于需要进行视频录像的用户来说,软件提供了长时与短时两种模式,并能实现硬盘空间的自动检测和录像的适时保存。
本软件技术切实可行,运行环境稳定可靠,对那些需要视频捕捉而对系统要求不是很高的部门和领域,本文提供了一种简单易行的办法,同时为广大视频编程爱好者提供了有益的借鉴。
关键词:VFW,AVICap窗口类,视频捕捉,捕捉窗口,视频对话框The Software Control Design of Camera Based on DelphiInformation engineering schoolcomputer science and technology departmentzhou jingAbstractThis paper introduces how to achieve the functions such as video capture,synchronous recroding of audio,real-time image capture,video streaminp and so on in Delphi,and focused on analysing the timely preservation of the high-performance hard disk video in the video monitoring system.In the process of designing the software,the VFW packages of Microsoft software and AVIcap window category members were taken advantage primarily to achieve the function of video streaming capture.At the same time ,it realized the Synchronized record of audio information with the aid of multimedia components of Delphi.As to captured video information,it sends windows users through frame callback function to complete the display of the timely video.As to the users need to be videotaped,the software provides a long and short time in two modes and achieved automatic detection of the hard disk space and timely preservation of the viedo.The technology of software is practical and the enviroment is stable and reliable.In addition,this article provides a simple and acceptable approach for those sectors and areas that the need of video capture system is not in very high demand.In the meantime,it supplys a useful reference to the majority enthusiasts who love video programming.Key words : VFW, AVICap windows class, video capture, window capture, video dialog目录1.引言 (1)2.开发环境与基本技术 (1)2.1开发环境 (1)2.2VFW简介 (2)2.3AVICap类的功能与函数 (2)2.3.1AVICap类的基本功能 (2)2.3.2AVICap窗口类的主要函数与宏 (3)2.3.3视频捕捉结构 (5)3.软件的结构与功能 (5)3.1软件的层次结构 (5)3.2软件的功能 (5)4.软件控制设计的实现 (6)4.1视频捕获流程 (6)4.2软件设计的实现 (7)4.2.1主窗体设计 (7)4.2.2启动摄像与音频录制 (10)4.2.3帮助文件的设计 (16)4.3设计中的问题 (17)5.软件测试 (17)5.1测试技术 (17)5.2测试结果与评价 (18)6.结束语 (18)致谢 (19)参考文献 (20)1.引言随着数字视频监控、可视电话、电视会议等多媒体技术应用的迅速兴起,越来越多的场合需要对数字视频信号进行捕捉。
VC++关于的VFW视频采集方案(续)
VC++关于的VFW视频采集方案(续)2.2.6 视频录像设计方案在VFW中,可以有3种方式实现视频录像。
其中,最简单的方式是调用capFileSetCaptureFile函数和capCaptureSequence函数。
该种方式存在许多缺点,例如,在录像时无法响应用户界面,无法实现视频压缩等。
第二种方式是调用capCaptureSetSetup函数,将CAPTUREPARMS结构的fYield成员设置为TRUE,启动后台线程来实现录像,然后调用capDlgVideoCompression函数让用户选择压缩器进行压缩,最后调用capFileSetCaptureFile函数和capCaptureSequence函数开始录像。
第二种方式的缺点是每次录像时都需要弹出一个对话框,让用户选择一种压缩器。
第三种方式是注册回调函数capSetCallbackOnVideoStream,在回调函数中压缩数据并写入AVI文件。
相对于前两种方式,第三种方式更为灵活和实用,因此在进行视频录像时,通常采用该种方式实现。
具体实现过程如下:(1)定义一个回调函数,该回调函数实现数据压缩,并将压缩的数据写入文件流中。
(2)调用capSetCallbackOnVideoStream注册回调函数。
(3)调用ICOpen函数打开一个压缩器,并调用ICCompressBegin函数开始压缩。
(4)调用AVIFileOpen函数打开一个AVI文件,并调用AVIFileCreateStream函数创建文件流。
(5)调用capCaptureSequenceNoFile函数开始录像。
下面以一个具体实例介绍如何采用第三种方式实现视频录像。
效果如图2.8所示。
图2.8 视频录像设计方案实例位置:光盘mr.2.2.6(1)创建一个基于对话框的工程,在对话框中添加按钮、图像控件,如图2.9所示。
图2.9 对话框资源设计(2)在对话框的头文件中引用“vfw.h”头文件,并导入“vfw32.lib”库文件。
用VfW实现的图像采集超声工作站的体会
影像诊断与介入放射学 !""# 年第 $% 卷第 $ 期
极缓慢的速度流动 极缓慢的速度流动。 。 这时动脉灌注利多卡因可以增加 留在肌瘤组织内的利多卡因浓度。 留在肌瘤组织内的利多卡因浓度。 这些药物能在动脉 彻底闭塞后留在组织内 彻底闭塞后留在组织内。 。有些学者提倡用活血化淤 治疗来缓解术后疼痛。 治疗来缓解术后疼痛。 我们则不主张这样。 我们则不主张这样。 那是考虑 到活血化淤治疗有可能会影响栓塞疗效, 到活血化淤治疗有可能会影响栓塞疗效,或者促使 肌瘤在栓塞后侧支循环的形成和血管再通的可能。 肌瘤在栓塞后侧支循环的形成和血管再通的可能。 结 论
作者单位 作者单位: : ’$"""( !"###$
) 徐子宁 *! ) 钟孟儿 ! * 浙江中医院附属二院超声科 ! 徐子宁、 、 张竹君 ! + 广州市中医院 !
影像诊断与介入放射学 #$$% 年第 &’ 卷第 & 期 !"#$%&’()* + ,-%./ %01(,$,). 2’$3&#%#,’) !"#$% (&,). &’#%( 4,*/’ )#*+$ 5’$ ,$- 2,)*’2& .#%*$.’
此外随着医学图像处理技术的发展针对超声图像的处理方法也逐步在临床实践中采用噪声去除图像增强直方图测定等经典的处理方法已比较成熟而一些专用的处理方法如血管内超声图像的轮廓自动探测也在迅速发展高分辨率超声图像的采集为这些处理手段的运用奠定了良好的基础
・&!・ !"#$%&’ 等,都证实了子宫动脉利多卡因灌注对缓 7/8094: #! $ #, (! ! 解栓塞后疼痛无效! 。众所周知 众所周知, , 利多卡因的半衰 期极短, 期极短, 在栓塞术前进行子宫动脉灌注, 在栓塞术前进行子宫动脉灌注, 其疗效根本 维持不到治疗结束, 维持不到治疗结束, 更何况术后止痛 更何况术后止痛。 。而且 而且, ,伴随 !"# 颗粒一同注入的液体对药物的不断冲刷更加快 ;,< 了利多卡因的流失, 了利多卡因的流失 , 使止痛效果更差。 使止痛效果更差 。 其次, 其次 , 由于栓塞 中断了动脉血供系统, 中断了动脉血供系统 , 故栓塞后又不存在利多卡因动 脉灌注的可能。这样 脉灌注的可能。 这样, , 单纯利多卡因子宫动脉灌注无 效就可以理解了。 效就可以理解了 。 , 因而获 我们设计了 “ 栓塞剂 ! = 麻药缓释系统” 得良好的疗效。 得良好的疗效。 本项研究使用的主要是 ;,< !"# = $ 利多 卡因缓释技术。 卡因缓释技术。这一技术中的缓释机制主要有二方 面。 ! !"# ;,< 内部吸收的利多卡因在栓塞后缓慢地向 外释放。 外释放。 "伴随 !"# ! ;,< 一起注入的包含在液体中的利 多卡因, 多卡因,在肌瘤组织内的停留时间延长。 在肌瘤组织内的停留时间延长。血流的停 止和血栓的形成使肌瘤组织内的液体循环趋于停 滞。这使留在组织内利多卡因的流失趋于缓慢。 这使留在组织内利多卡因的流失趋于缓慢。这 大大弥补了利多卡因半衰期短的缺点。 大大弥补了利多卡因半衰期短的缺点。由于子宫肌 瘤栓塞术的术后疼痛主要表现为急性梗死痛。 瘤栓塞术的术后疼痛主要表现为急性梗死痛。时间 主要在术后 (! 中对照组曲线来看, 从 !" > # 内。从图 ! #中对照组曲线来看, 栓塞结束开始到术后 (! 是疼痛峰值区, 且疼痛在 !" > # 是疼痛峰值区, 术后 !& 已达到峰值。 利多卡因的缓慢释放恰恰正 !" > # 已达到峰值。 是缓解了这一急性梗死痛, 是缓解了这一急性梗死痛,使患者得以较为平稳地 度过急性缺血水肿期。 度过急性缺血水肿期。 ;,< !"# = $ 利多卡因缓释技术缓 解了术后 (! 内峰值区的疼痛: 治疗组较对照组峰 !" > # 内峰值区的疼痛: 值下降 ! 个疼痛等级。 个疼痛等级 。 这一技术更是缓解了术后 $ !& !" 的疼痛峰值 : 治疗组较对照组下降近 ! 个疼痛等 > 的疼痛峰值: ! 级。 颗粒栓塞后, 明胶海绵补充栓塞前, 明胶海绵补充栓塞前, 子宫动 ;,< 颗粒栓塞后, !"# 脉内血栓尚未形成。 脉内血栓尚未形成。此时动脉内的血液依然可以以
在Delphi中利用VFW和简易摄像头实现图像采集和处理
在Delphi中利用VFW和简易摄像头实现图像采集和处理程刚;金毅仁
【期刊名称】《电脑编程技巧与维护》
【年(卷),期】2010(000)004
【摘要】在多媒体系统中,视频的捕获以及处理技术是其非常重要的一个组成部分.主要介绍在Delphi应用程序中利用VFW和简易摄像头实现图像采集和处理,实现了视频流的捕获和单帧数据的捕获,并可进行存储.
【总页数】4页(P93-96)
【作者】程刚;金毅仁
【作者单位】安徽省教育招生考试院,合肥230022;合肥工业大学电气及自动化工程学院,合肥230009
【正文语种】中文
【相关文献】
1.在PB中调用Delphi图像处理程序实现旋转打印 [J], 孟昭林;武俊鹏
2.在Delphi中利用多线程实现数据采集的方法 [J], 贾静
3.Delphi应用程序中图像采集及处理技术 [J], 汪张生;陈玉萍;蒋先刚
4.织物检测中图像预处理的Delphi实现 [J], 潘陆益
5.利用图像处理技术实现物体运动信息的采集与处理 [J], 张竞夫;司丽荣;邓永龙因版权原因,仅展示原文概要,查看原文内容请购买。
Delphi客户端通过FTP服务器上传或下载文件或图片方法
Delphi客户端通过FTP服务器上传或下载文件或图片方法第一篇:Delphi客户端通过FTP服务器上传或下载文件或图片方法Delphi客户端通过FTP服务器上传或下载文件或图片方法首先在服务器端建立FTP服务器,网上有这种类型的软件,安装好后,在客户端建立服务器连接,然后再上传或下载文件或图片。
一、服务器连接procedure TForm1.ConnectButtonClick(Sender: TObject);begin if not IdFTP1.Connected then //如果与服务器断开连接begintryername:=UserIDEdit.Text;IdFTP1.Password:=PasswordEdit.Text;IdFTP1.Host:=FtpServerEdit.Text;IdFTP1.Connect;//Connect;Except //异常处理Application.MessageBox('服务器连接失败!','智博软件');end;ConnectButton.Enabled:=true;if IdFTP1.Connected thenbeginConnectButton.Caption:='断开';DebugListBox.Items.Add('主机名为:'+IdFTP1.Host);DebugListBox.Items.Add('连接成功');ConnectButton.Default:=false;end;endelsetryIdFTP1.Quit;//关闭客户端与服务器端的连接finallyConnectButton.Caption:='连接';DebugListBox.Items.Add('连接失败'); ConnectButton.Enabled:=true;ConnectButton.Default:=true;end;end;二、文件或图片上传Procedure TFrmMain.UploadFileCleck(Sender:TObject); varFileName : string;Item : TListItem;SendFileItem : TListItem;beginif not FTPClient.Connected thenexit;if ListViewLocalFile.Selected =nil thenexit;Item :=ListViewLocalFile.Selected; ListViewSendFile.Clear;//处理所有选中文件while Item <>nil dobeginSendFileItem := ListViewSendFile.Items.Add; SendFileItem.Caption := Item.Caption;//文件名SendFileItem.SubItems.Add(Item.SubItems[1]);//文件大小SendFileItem.SubItems.Add(LocaLPath);//本地路径SendFileItem.SubItems.Add('==>');//图示SendFileItem.SubItems.Add(RemotePath);//远程路径SendFileItem.SubItems.Add('');//状态//下一个选中的项目Item:=ListViewLocalFile.GetNextItem(Item,sdAll,[isSelected]); end;ListViewSendFile.Refresh;//刷新传送文件列表//传送文件ListViewLocalFile.Enabled :=false;DriveComboBox1.Enabled:=false; ListViewRemoteFile.Enabled:=False;IsTransFerring:=True;try//处理所有要传送的文件while ListViewSendFile.Items.Count>0 dobeginFileName:=ListViewSendFile.Item[0].Caption;//文件名ListViewSendFile.Item[0].SubItems[4]:='正在上传...'; FTPClient.Put(LocalPath+''+FileName);//上传DisplayRemoteFileList();ListViewSendFile.items[0].Delect;//传送完毕,删除待传送文件列表ListViewSendFile.Refresh;end;//设置相关控件是否可用ListViewLocalFile.Enabled:=True;DriveComboBox1.Enabled:=True; ListVieewRemoteFile.Enabled:=True; IsTransferring:=False;exceptListViewSendFile.Items[0].SubItems[4]:='上传错误!'; MessageDlg('上传文件发生错误!',mtError,[mbyes],0);//设置相关控件是否可用ListViewLocalFile.Enabled:=True;DriveCombBox1.Enabled:=True; ListViewRemoteFile.Enabled:=True;IsTransferring:=False;//没有传送状态end;end;三、文件或图片下载procedure TFrmMain.DownloadFileClick(Sender:TObject); varFileName :String;Item ,SendFileItem : TListItem;beginif not FTPClient.Connected Then//没有连接到服务器,退出exit;if ListViewRemoteFile.Selected;//得到选中的文件ListViewSendFile.Clear;//清空要传送的文件列表//处理所有选中的文件While Item <> nil dobeginSendFileItem :=ListViewSendFile.Items.Add;//增加到列表//列表项赋值SendFileItem.Caption := Item.Caption;//文件名SendFileItem.SubItems.Add(Item.SubItems[1]);//文件大小SendFileItem.SubItems.Add(LocaLPath);//本地路径SendFileItem.SubItems.Add('<==');//图示SendFileItem.SubItems.Add(RemotePath);//远程路径SendFileItem.SubItems.Add('');//下一个选中的项目Item:=ListViewRemoteFile.GetNextItem(Item,sdAll,[isSelecte d]);end;ListViewSendFile.Refresh;//刷新传送文件列表//传送文件ListViewRemoteFile.Enabled:=false;//禁止操作相关控件IsTransferring:=True;//设置正在传送try//处理所有要传送的文件while ListViewSendFile.Items.Count >0 dobeginFileName := ListViewSendFile.Items[0].Caption;//文件名ListViewSendFile.Items[0].SubItems[4]:='正在下载...';ListViewSendFile.Refresh;//刷新传送文件列表if FileExists(FileName)then //判断文件是否存在beginif MessageDlg('文件己存在,继续下载吗?',mtConfirmation,[mbYes,mbNo],0)=mrYes thenFTPClient.Get(FileName,LocalPath+''+FileName,false,true) //续传elseFTPClient.Get(FileName,LocalPath+''+FileName,true,False);//覆盖endelseFTPClient.Get(FileName,LocalPath+''+FileName,false);//下载ListViewSendFile.items[0].Delect;//传送完毕,删除待传送文件列表ListViewSendFile.Refresh;//刷新待传送列表DisplayLocalFileList();//刷新本地文件列表end;ListViewRemoteFile.Enabled:=true;IsTransferring:=False;//没有传送状态exceptListViewSendFile.Items[0].SubItems[4]:='下载错误';ListViewSendFile.Refresh;//刷新待传送文件列表MessageDlg('下载文件发生错误!',mtError,[nbYes],0);ListViewRemoteFile.Enabled:=True;IsTransferring:=False;//没有传送状态end;end;以上代码在Delphi7中调试通过。
基于Delphi的VFW视频捕获程序的开发
基于Delphi的VFW视频捕获程序的开发
于永彦
【期刊名称】《国外电子元器件》
【年(卷),期】2003(000)008
【摘要】许多关于视频的软件(如视频会议、可视电话等)开发都应用了视频捕获技术.微软为软件开发人员提供了一个专门用于视频捕获的VFW SDK,从而为在Windows系统中实现视频捕获提供了标准的接口,并大大降低了程序的开发难度.由于VFW SDK只有VC和VB版,没有Delphi版,因此需要在Delphi中一一声明DLL中的各个函数和变量.文中详细介绍了如何利用VFW在Delphi中开发视频捕获程序的步骤,同时给出了程序实例.
【总页数】3页(P27-29)
【作者】于永彦
【作者单位】淮阴工学院计算机工程系
【正文语种】中文
【中图分类】TP317.4
【相关文献】
1.基于VFW实时视频捕获原理与实现 [J], 李江华;谢红;王晓丹
2.基于VFW的远程视频捕获技术研究 [J], 周梦婷;罗森林
3.在VB中基于VFW视频捕获技术的研究 [J], 王瑜
4.基于VFW的远程专家会诊系统中的实时音视频捕获 [J], 龚伟
5.基于VFW的视频捕获方法的研究与应用 [J], 马连峰;汤赛楠
因版权原因,仅展示原文概要,查看原文内容请购买。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图1VFW模块关系图在Delphi 中利用VFW 和简易摄像头实现图像采集和处理程刚1,金毅仁2(1.安徽省教育招生考试院,合肥230022;2.合肥工业大学电气及自动化工程学院,合肥230009)摘要:在多媒体系统中,视频的捕获以及处理技术是其非常重要的一个组成部分。
主要介绍在Delphi 应用程序中利用VFW 和简易摄像头实现图像采集和处理,实现了视频流的捕获和单帧数据的捕获,并可进行存储。
关键词:VFW ;AVICAP ;SendMessage ;视频捕获;帧捕获Use VFW and Simple Camera to Carry out Image Capturing and Processingin DelphiCHENG Gang 1,JIN Yiren 2(1.Anhui Education Examinations Authority,Hefei 230022;2.School of Electric and Automation Engineering,Hefei University of Technology,Hefei 230009)Abstract:The technology of Image capturing and processing is a very important part of the multimedia system.The scheme mainly introduces how to use VFW and simple camera to carry out image capturing and processing technologies in Delphi,achieving the capturing of image-stream data and frame data and the storage of them.Key words:VFW ;AVICAP ;SendMessage ;ideo capture ;frame capture多媒体技术的不断发展给人们的生活带来了生机与活力,它已经深入到人们生活的方方面面,与人们的生活息息相关。
现代的多媒体通信在电视会议、可视电话、可视图文业务等领域得到了广泛的应用。
另外,在很多工程应用程序设计中,会涉及到大量的图像捕捉与图像处理的问题,如防盗报警系统的设计、银行录像监控系统的设计、交通监控系统的设计以及运动系统图像处理的设计等等。
可见,在多媒体系统中,视频的处理技术是非常重要的一个组成部分,如何才能有效地处理视频数据是多媒体技术当中的一个难点。
1基本概念1.1概述当前,在Windows 平台下开发视频应用程序一般采用两种方式:一种是基于视频采集卡所附带的二次软件开发包SDK 进行。
这种方式的优点是应用方便,实现便捷,但是这种方式的缺点是对硬件的依赖性较强,而且各种视频采集卡的功能不完全相同,往往不能充分满足各种工程视频应用程序的开发需要。
另一种方式是基于VFW 进行的。
VFW 是Microsoft 公司为开发Windows 平台下的视频应用程序提供的软件工具包,提供了一系列应用程序编程接口(API ),用户可以通过它们很方便地实现视频捕获、视频编辑及视频播放等通用功能,还可利用回调函数开发更复杂的视频应用程序。
它的特点是播放视频时不需要专用的硬件设备,而且应用灵活,可以满足视频应用程序开发的需要。
Windows 操作系统自身就携带了VFW ,系统安装时,会自动安装VFW 的相关组件。
由于VFW 只有VC 和VB 版,没有Delphi 版,因此需要在Delphi 中一一声明DLL 中的各个函数和变量。
目前,PC 机上多媒体应用程序的视频部分,大都是利用VFW API 开发的。
1.2体系结构VFW 主要由以下6个模块组成,如图1所示。
(1)AVICAP.DLL :主要实现视频捕获功能,包含了用于视频捕获的函数,为音像交错AVI 格式文件和视频、音频设备程序提供一个高级接口。
(2)MSVIDEO.DLL :能够将视频捕获窗口与获驱动设备连接起来,支持ICM 视频编码服务。
(3)MCIAVI.DRV :包含MCI 命令解释器,实现回放功能。
(4)AVIFILE.DLL :提供对AVI 文件的读写操作等文件管理功能。
(5)ICM :即压缩管理器,提供对存储在AVI 文件中视频图像数据的压缩、解压缩服务。
收稿日期:2009-10-27(6)ACM:即音频压缩管理器,提供实时音频压缩及解压缩功能。
1.3视频捕获及其功能AVIcap窗口类是VFW的一个重要组成部分,它主要作用是实现视频的捕获。
AVIcap为应用程序提供一个简单的基于消息的接口,通过该接口,程序可以访问视频和波形音频硬件并控制视频流到硬件的捕获。
通过AVIcap,程序员可以轻松地将视频捕获功能加入到自己的应用程序中。
AVIcap支持实时视频流捕获和单帧图像捕获。
此外,AVIcap使程序员可以控制视频的开始和结束位置,并加入了如序列帧捕获等功能。
使用AVIcap生成的捕获窗具有以下的功能:(1)将视频流和音频流捕获到一个AVI文件中。
(2)动态地同视频和音频输入器件连接或断开。
(3)以Overlay或Preview模式对输入的视频流进行实时显示。
(4)在捕获时,可指定所用的文件名,并可将捕获文件的内容拷贝到另一个文件。
(5)设置捕获速率。
(6)显示控制视频源、视频格式及视频压缩的对话框。
(7)创建、保存或载入调色板。
(8)将图像和相关的调色板拷贝到剪贴板。
(9)将捕获的单帧图像保存到DIB格式文件。
1.4SendMessage函数SendMessage是Windows API(应用程序接口)函数之一,SendMessage函数的功能是“发送消息”,即将一条消息发送到指定对象(操作系统、窗口或控件等)上,以产生特定的动作。
函数原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);参数:hWnd:其窗口程序将接收消息的窗口的句柄。
如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息。
IParam:指定附加的消息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息。
1.5开发视频捕获程序步骤1.5.1创建视频捕获窗视频捕获利用AVIcap类的“capCreateCaptureWindowA”函数来创建,并可以以此为基础,进行后续的设置操作。
1.5.2将捕获窗和设备驱动程序关联创建好的视频捕获窗需要和一个设备相关联才能获得视频信号。
可以利用函数SendMessage(hWndC,WM_CAP_DRIVE R_CONNECT,0,0)来实现。
1.5.3视频的预览利用函数SendMessage(hWndC,WM_CAP_SET_PREVIEWR ATE,66,0)和函数SendMessage(hWndC,WM_CAP_SET_SCAL E,1,0)设置预览的速度与比例,也可以使用设备的默认值。
利用函数SendMessage(hWndC,WM_CAP_SET_OVERLAY,1, 0)选择是否采用叠加模式预览,以保证视频速度快,占用系统资源少。
最后利用函数SendMessage(hWndC, WM_CAP_SET_PREVIEW,1,0)实现视频的预览。
2Delphi实现视频捕获(1)AVICAP类支持实时视频流捕获和单帧捕获,并提供对视频流的控制。
通常使用的MCI虽然也提供数字视频服务,并为视频叠加提供了overlay命令集,但这些命令主要是基于文件的操作,还不能满足实时的从视频缓存中提取数字的要求,对于没有视频叠加能力的捕获卡的PC机来说,用MCI提供的命令是无法捕获视频流的。
而AVICAP窗口类在捕获视频方面具有一定的优势,它能直接访问视频区,而不需要生成中间文件,因而实用性强,效率高。
另外,它还能将数字视频捕获到一个文件中去。
下面举例说明如何利用AVICAP类和SendMessage函数实现视频流捕获和单帧捕获以及如何将它们捕捉到一个文件中去。
1)在PC机上安装摄像头及其驱动程序,以保证其能正常工作。
2)利用Delphi新建一个工程,然后将Vfw.pas单元文件包含进去。
方法如下:implementationuses Vfw;{$R*.dfm}说明:Vfw单元文件当中包含了VFW常用模块的各个函数和变量。
3)定义变量,方法如下:PrivatehWndC:THandle;//捕获窗句柄4)在窗体上放置一个T Panel控件、四个TBitBtn控件、两个TRadioButton控件、两个TSaveDialog控件。
T Panel控件用来显示视频,四个TBitBtn控件分别用作打开视频、开始捕获、停止捕获、关闭视频,两个TRadioButton控件用来选择是进行视频流捕获还是单帧捕获,两个TSaveDialog控件用来指定捕获的视频流文件或单帧文件的文件名。
5)编写相应控件的代码,在开始捕获TbitBtn控件中写入以下代码:procedure Tform1.BitBtn2Click(Sender:TObject);var pathName:string;beginif RadioButton1.Checked thenbeginif saveDialog1.Execute thenbeginpathName:=saveDialog1.FileName;//指定视频流的保//存路径if hWndC <>0then beginSendMessage (hWndC,WM_CAP_FILE_SET_CAPTURE_FILEA,0,Longint (pchar (pathName)));//指定视频流文件名SendMessage (hWndC,WM_CAP_SEQUENCE,0,0);//保存视频流数据end;end;end;if RadioButton2.Checked then beginif saveDialog2.Execute then beginpathName:=saveDialog2.FileName;//指定帧数据的保存路径if hWndC <>0then beginSendMessage (hWndC,WM_CAP_FILE_SAVEDIB,0,Longint (pchar (pathName)));//保存帧数据end;end;end;end;在停止TbitBtn 控件中写入以下代码:procedure Tform1.BitBtn4Click (Sender:TObject);beginif hWndC <>0then beginSendMessage (hWndC,WM_CAP_ABORT,0,0);//停止捕获SendMessage (hWndC,WM_CAP_DRIVER_DISCONNECT,0,0);//将捕获窗和设备驱动程序断开end;end;运行程序能在自己指定的路径下获得保存的AVI 视频流文件和DIB 帧文件,运行如图2所示。