!!!200分请教实时采集图像后在屏幕上显示时的闪烁问题!!! ( 积分: 200 )

  • 主题发起人 主题发起人 forfor
  • 开始时间 开始时间
F

forfor

Unregistered / Unconfirmed
GUEST, unregistred user!
我编了一个实时采集图像并对其进行图像处理的程序,但图像不停的闪烁,请大侠指点,将倾尽我所有的热情真诚来感谢你:)

采集卡用的大恒的CG300,程序的大致结构如下:
implementation
uses
CGCardAPI;
{$R *.dfm}
var


//用户创建的一帧图像数据缓冲区大小,用来将图像卡采集到内存的数据读出到该缓冲区
ImgBufLength: LongWord;
//图像卡采集的每帧数据数据大小
BufLength: LongWord;

pBMIInfo: PBITMAPINFO;
pBuffer: PChar;
Bmp: TBitmap;

const
INPUT_WINDOW_X = 0;
INPUT_WINDOW_Y = 0;
INPUT_WINDOW_WIDTH = 300;

procedure TForm1.FormCreate(Sender: TObject);
begin
if (BeginCGCard(1, hCGCard) = CG_OK) then
begin
//设置输入视频窗口大小
CG_VERIFY(CGSetInputWindow(hCGCard, INPUT_WINDOW_X,
INPUT_WINDOW_Y,
INPUT_WINDOW_WIDTH,
INPUT_WINDOW_HEIGHT));
//设置输出图像大小
CG_VERIFY(CGSetOutputWindow(hCGCard, OUTPUT_WINDOW_X,
OUTPUT_WINDOW_Y,
OUTPUT_WINDOW_WIDTH,
OUTPUT_WINDOW_HEIGHT));
ImgBufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 3;
pBuffer := AllocMem(ImgBufLength);
pBMIInfo := AllocMem(sizeof(TBITMAPINFO)+ (255 * sizeof(TRGBQuad)));
end;

Bmp := TBitmap.Create;

//Self.DoubleBuffered:=true; //消除闪烁,但这种方法无效果
end;

function SnapExCallback(var info: SNAP_INFO): Integer; stdcall
begin

Form1.Draw(info.nNumber);
result := 1;
end;


function TForm1.Draw (nNumber: Integer): boolean;
var
MemHandle: LongWord;
LineAddr: PChar;
VideoDc: HDC;
r, g, b: Byte;
begin
VideoDc := GetDc(VideoPanel.Handle);
//已经固定用GRB565来采集数据了,每帧图像768*576,所以图像卡需要的帧缓冲区大小是
BufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 2;

//锁定全部保留静态内存给图像卡使用
CG_VERIFY(CGStaticMemLock(Longword(nNumber) * BufLength, BufLength, MemHandle, LineAddr));
SetStretchBltMode(VideoDC, COLORONCOLOR);
Bmp.Width:= OUTPUT_WINDOW_WIDTH;
Bmp.Height := OUTPUT_WINDOW_HEIGHT;
Bmp.PixelFormat := pf24bit;
//设定BMP的头信息
pBMIInfo^.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
pBMIInfo^.bmiHeader.biWidth := OUTPUT_WINDOW_WIDTH;
pBMIInfo^.bmiHeader.biHeight := OUTPUT_WINDOW_HEIGHT;
pBMIInfo^.bmiHeader.biPlanes := 1;
pBMIInfo^.bmiHeader.biBitCount := 24;
pBMIInfo^.bmiHeader.biCompression := BI_RGB;
pBMIInfo^.bmiHeader.biSizeImage := 0;
pBMIInfo^.bmiHeader.biXPelsPerMeter := 0;
pBMIInfo^.bmiHeader.biYPelsPerMeter := 0;
pBMIInfo^.bmiHeader.biClrUsed := 0;
pBMIInfo^.bmiHeader.biClrImportant := 0;
//读出数据
CGDataTransform(pBuffer , LineAddr , OUTPUT_WINDOW_WIDTH, OUTPUT_WINDOW_HEIGHT, 16, True);
SetStretchBltMode(Bmp.Canvas.Handle, COLORONCOLOR);
SetDIBitsToDevice(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height,
0, 0, 0, pBMIInfo^.bmiHeader.biHeight,
pBuffer, pBMIInfo^, DIB_RGB_COLORS);
Image1.Picture.Bitmap.Assign(Bmp); //*******用这种方法的显示画面闪烁*********
Bmp.Free;
CG_VERIFY(CGStaticMemUnlock(MemHandle));
ReleaseDC(VideoPanel.Handle, VideoDC);
result := true;
end;

为了大家看得方便,以及篇幅限制,我中间省略了初始化图像卡的语句。程序注释中画*号的语句用来在屏幕上画出图像,但图像会不停闪烁。
请各位大侠一定要指点我!!叩谢!!!
 
我编了一个实时采集图像并对其进行图像处理的程序,但图像不停的闪烁,请大侠指点,将倾尽我所有的热情真诚来感谢你:)

采集卡用的大恒的CG300,程序的大致结构如下:
implementation
uses
CGCardAPI;
{$R *.dfm}
var


//用户创建的一帧图像数据缓冲区大小,用来将图像卡采集到内存的数据读出到该缓冲区
ImgBufLength: LongWord;
//图像卡采集的每帧数据数据大小
BufLength: LongWord;

pBMIInfo: PBITMAPINFO;
pBuffer: PChar;
Bmp: TBitmap;

const
INPUT_WINDOW_X = 0;
INPUT_WINDOW_Y = 0;
INPUT_WINDOW_WIDTH = 300;

procedure TForm1.FormCreate(Sender: TObject);
begin
if (BeginCGCard(1, hCGCard) = CG_OK) then
begin
//设置输入视频窗口大小
CG_VERIFY(CGSetInputWindow(hCGCard, INPUT_WINDOW_X,
INPUT_WINDOW_Y,
INPUT_WINDOW_WIDTH,
INPUT_WINDOW_HEIGHT));
//设置输出图像大小
CG_VERIFY(CGSetOutputWindow(hCGCard, OUTPUT_WINDOW_X,
OUTPUT_WINDOW_Y,
OUTPUT_WINDOW_WIDTH,
OUTPUT_WINDOW_HEIGHT));
ImgBufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 3;
pBuffer := AllocMem(ImgBufLength);
pBMIInfo := AllocMem(sizeof(TBITMAPINFO)+ (255 * sizeof(TRGBQuad)));
end;

Bmp := TBitmap.Create;

//Self.DoubleBuffered:=true; //消除闪烁,但这种方法无效果
end;

function SnapExCallback(var info: SNAP_INFO): Integer; stdcall
begin

Form1.Draw(info.nNumber);
result := 1;
end;


function TForm1.Draw (nNumber: Integer): boolean;
var
MemHandle: LongWord;
LineAddr: PChar;
VideoDc: HDC;
r, g, b: Byte;
begin
VideoDc := GetDc(VideoPanel.Handle);
//已经固定用GRB565来采集数据了,每帧图像768*576,所以图像卡需要的帧缓冲区大小是
BufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 2;

//锁定全部保留静态内存给图像卡使用
CG_VERIFY(CGStaticMemLock(Longword(nNumber) * BufLength, BufLength, MemHandle, LineAddr));
SetStretchBltMode(VideoDC, COLORONCOLOR);
Bmp.Width:= OUTPUT_WINDOW_WIDTH;
Bmp.Height := OUTPUT_WINDOW_HEIGHT;
Bmp.PixelFormat := pf24bit;
//设定BMP的头信息
pBMIInfo^.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
pBMIInfo^.bmiHeader.biWidth := OUTPUT_WINDOW_WIDTH;
pBMIInfo^.bmiHeader.biHeight := OUTPUT_WINDOW_HEIGHT;
pBMIInfo^.bmiHeader.biPlanes := 1;
pBMIInfo^.bmiHeader.biBitCount := 24;
pBMIInfo^.bmiHeader.biCompression := BI_RGB;
pBMIInfo^.bmiHeader.biSizeImage := 0;
pBMIInfo^.bmiHeader.biXPelsPerMeter := 0;
pBMIInfo^.bmiHeader.biYPelsPerMeter := 0;
pBMIInfo^.bmiHeader.biClrUsed := 0;
pBMIInfo^.bmiHeader.biClrImportant := 0;
//读出数据
CGDataTransform(pBuffer , LineAddr , OUTPUT_WINDOW_WIDTH, OUTPUT_WINDOW_HEIGHT, 16, True);
SetStretchBltMode(Bmp.Canvas.Handle, COLORONCOLOR);
SetDIBitsToDevice(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height,
0, 0, 0, pBMIInfo^.bmiHeader.biHeight,
pBuffer, pBMIInfo^, DIB_RGB_COLORS);
Image1.Picture.Bitmap.Assign(Bmp); //*******用这种方法的显示画面闪烁*********
Bmp.Free;
CG_VERIFY(CGStaticMemUnlock(MemHandle));
ReleaseDC(VideoPanel.Handle, VideoDC);
result := true;
end;

为了大家看得方便,以及篇幅限制,我中间省略了初始化图像卡的语句。程序注释中画*号的语句用来在屏幕上画出图像,但图像会不停闪烁。
请各位大侠一定要指点我!!叩谢!!!
 
不要在窗口或者Panel,Image中画,放个PaintBox 在PaintBox中画。
 
谢谢独孤客!

我放了个PaintBox,将原来程序中的语句
Image1.Picture.Bitmap.Assign(Bmp);
改成了
PaintBox1.Canvas.Brush.Bitmap.Assign(Bmp);
此时不显示图像。
能告诉我具体怎么用吗?
 
我刚才又改了一下,改成
PaintBox1.Canvas.draw(Bmp);
此时图像不再闪烁,但当我移动鼠标时,图像位置会移动一点点,从而造成图像有重影,当鼠标停止时,图像又恢复正常,请问这是什么原因啊~~~~
 
在图像处理前添加一句:
application.processmessage;
 
谢谢饭前饭后!我尝试着在各个位置添加你所说的
application.processmessage;
但是没效果呀,不知是不是位置错了还是别的什么原因
 
怎么没人理我了啊:(

我再把我的问题概括下:
现在程序里有个TBitmap,其内容根据摄像头采集的图像不断更新,我要将该TBitmap实时显示在屏幕上,且不能闪烁,大家告诉我该用哪个控件?TImage还是TPaintBox?用TPaintBox可以做到不闪烁,但移动鼠标时会有重影,且移动速度稍快的话,系统就死机了。请各位大佬指教!!!
 
用Timage 控件:
Image1.Parent.DoubleBuffered:=true;
Image1.Picture.Bitmap.Assign(Bmp);
 
多人接受答案了。
 
后退
顶部