📄 liveviewdlg.cpp
字号:
HCURSOR CLiveViewDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CLiveViewDlg::OnCaptrue()
{
// TODO: Add your control notification handler code here
try
{
if(CBcam::DeviceNames().size() == 0)// 检测摄像机是否存在
{
MessageBox("没有检测到Basler摄像机", _T("错误"), MB_OK | MB_ICONEXCLAMATION);
return;
}
CString DeviceName = *(CBcam::DeviceNames().begin());// 得到本PC连接的第一台摄像机的名字
TRACE(_T("Devicename = %s\n"), DeviceName);
m_Bcam.Open( DeviceName );// 打开第一台摄像机
m_bConnectBcam = true;
const DCSVideoFormat VideoFormat = DCS_Format7;// 设定摄像机采集的图像格式,Format7,mode0,单色。Format7,Mode0是摄像机开发商自定义的工作模式,对A101f即是1300*1030*12FPS
const DCSVideoMode VideoMode = DCS_Mode0;
m_ColorCode = DCSColor_Raw8;
m_Bcam.SetVideoMode(VideoFormat, VideoMode);
m_Bcam.FormatSeven[VideoMode].ColorCoding = m_ColorCode;
// 设置采集图像尺寸,这里设定为最大,当然尺寸可以设定得比最大尺寸小
//m_ImageSize = m_Bcam.FormatSeven[VideoMode].MaxSize();
// 注意: bitmap要求宽度是4的倍数,即DWORD对齐 :-(
m_ImageSize.cx = m_ImageSize.cx & ~3;
CPoint AoiPosition(0);
CSize AoiSize(m_ImageSize);
m_Bcam.FormatSeven[VideoMode].Position = AoiPosition;
m_Bcam.FormatSeven[VideoMode].Size = AoiSize;
// 设置IEEE 1394每个数据包大小,该参数决定帧率,这里将数据包尺寸设定为最大是为了得到最大的帧率
unsigned long BytePerPacketMax = m_Bcam.FormatSeven[VideoMode].BytePerPacket.Max();
m_Bcam.FormatSeven[VideoMode].BytePerPacket = BytePerPacketMax;
// m_Bcam.Brightness.Raw = m_Bcam.Brightness.Raw.Max();
m_Bcam.Brightness.Raw = m_nBrightness ;
// m_Bcam.Gain.Raw = m_Bcam.Gain.Raw.Min();
m_Bcam.Gain.Raw = m_nGain ;
// m_Bcam.Shutter.Raw = (m_Bcam.Shutter.Raw.Max() + m_Bcam.Shutter.Raw.Min()) >>1;
m_Bcam.Shutter.Raw = m_nShutter;
m_Bcam.WhiteBalance.Raw.UBValue.SetAsync(m_nU);
m_Bcam.WhiteBalance.Raw.VRValue.SetAsync(m_nV);
m_pDispBitmap = new BYTE[m_ImageSize.cx*m_ImageSize.cy*3];
m_pBitmap=NULL;
for(int i=0; i<NUM_BUFFERS; ++i) // 为多缓冲区分配资源
m_ptrBitmaps[i] = new char[m_ImageSize.cx * m_ImageSize.cy];
// 在BCAM中建立内存
m_Bcam.AllocateResources(NUM_BUFFERS, AoiSize.cx * AoiSize.cy );
// 建立并启动采集线程
if ( ! m_GrabThread.Create(&GrabThreadProc, this, THREAD_PRIORITY_HIGHEST) )
{
throw BcamException(::GetLastError(), "CLiveViewDlg::OnCamLive : Create Grab Thread");
}
//建立并启动显示线程
if ( ! m_DispThread.Create(&DispThreadProc, this, THREAD_PRIORITY_HIGHEST) )
{
throw BcamException(::GetLastError(), "CLiveViewDlg::OnCamLive : Create Grab Thread");
}
// 设定标记,表示采集开始了
m_LiveGrabbing = true;
m_bIsDispImage = TRUE;
m_bOCROk = true;
m_nLostFrame = 0;
m_stop=true;
// 将多缓冲区同步采集指令顺序排入队列
for(i=0; i<NUM_BUFFERS; ++i)
{
m_Bcam.GrabImageAsync(m_ptrBitmaps[i], AoiSize.cx * AoiSize.cy, (void*)i, USE_ONESHOT);
}
//启动定时器,刷新窗体
SetTimer(ID_TIMER_DISPLAY, TIMER_SPACE_NUM, NULL);
//开始计算显示帧率和采集帧率
m_DisplayWatch.Start();
m_AcquisitionWatch.Start();
// 判断是否进行连续采集
if(!USE_ONESHOT)
m_Bcam.ContinuousShot = true;
}
CATCH_MSGBOX( "CLiveViewDlg::OnCaptrue" )
}
//停止采集时执行
afx_msg LRESULT CLiveViewDlg::OnGrabStopped(WPARAM wParam, LPARAM lParam)
{
try
{
// 关闭摄像机的连续采集
if(!USE_ONESHOT)
m_Bcam.ContinuousShot = false;
// 释放线程
m_GrabThread.Release(); // this waits for the thread to die
m_DispThread.Release();
// 停止I/O请求
m_Bcam.Cancel();
//释放在BCAM中建立的资源
m_Bcam.FreeResources();
// 关闭BCAM对象
m_Bcam.Close();
// 释放缓存
for(int i=0; i<NUM_BUFFERS; ++i)
delete [] m_ptrBitmaps[i];
delete m_pBitmap ;
delete m_pDispBitmap;
}
CATCH_MSGBOX( "CLiveViewDlg::OnGrabStopped" )
return 0;
}
//采集线程出错时执行
afx_msg LRESULT CLiveViewDlg::OnError(WPARAM wParam, LPARAM lParam)
{
// 显示采集线程中出现的错误信息
BcamException* pE = (BcamException*)wParam;
CString Buffer, B;
Buffer += (B.Format("Exception 0x%X occurred\n", pE->Error() ), B);
Buffer += (B.Format("Message = %s\n", pE->Description() ), B);
Buffer += (B.Format("Context = %s\n", pE->Context()), B);
MessageBox(Buffer, _T("CLiveViewDlg::OnError"), MB_OK | MB_ICONEXCLAMATION);
delete pE;
return 0;
}
DWORD CLiveViewDlg::GrabThreadProc(void* pParameter)
{
CLiveViewDlg* This = (CLiveViewDlg*) pParameter; // instance pointer
This->m_Bcam.SetCurrentThreadPriority(16);
int nSize = This->m_ImageSize.cx * This->m_ImageSize.cy;
try
{
for(;;)
{
FunctionCode_t FunctionCode;
unsigned long ErrorCode;
void *pContext;
// Wait for things to show up at the driver's completion port
This->m_Bcam.WaitForCompletion(&FunctionCode, &ErrorCode, &pContext, INFINITE);
if(ErrorCode){
TRACE(_T("GrabThreadProc Error = %d\n"), ErrorCode);
throw BcamException(ErrorCode, "CLiveViewDlg::GrabThreadProc");
}
switch(FunctionCode)
{
case AsyncGrabImage:
{
//将采集单帧的时间排入队列
This->m_AcquisitionAvg.Add(This->m_AcquisitionWatch.Stop(true));
//如果还要采集则重复将采集指令排入队列
if(This->m_LiveGrabbing)
{
This->m_Bcam.GrabImageAsync(This->m_ptrBitmaps[*(int*)&pContext],
This->m_ImageSize.cx * This->m_ImageSize.cy, pContext, USE_ONESHOT);
}
// 通知GDI线程有一帧图像采集完成
//This->PostMessage(WM_GRAB_FINISHED, *(WPARAM*)&pContext);
if(!This->m_pMyQueue->InQueue((PBYTE)This->m_ptrBitmaps[*(int*)&pContext]))
{
This->m_nLostFrame++;// 丢帧处理
}
if (This->m_bOCROk) //m_bOCROk初始值为true
{
This->m_evtNewBufferAvailable.Set();
}
}
break;
//要终止采集图像
case NotifyQuit:
// 通知GDI线程完成收尾工作
This->PostMessage(WM_GRAB_STOPPED, 0, 0 );
// 结束采集线程
return 0;
// Don't care about other function codes like AsyncSetGain etc.
default:
ErrorCode = 1;
break;
}
}
}
catch (BcamException& e )
{
// 传递错误到Gdi线程来显示
BcamException* pE = new BcamException(e);
This->PostMessage(WM_ERROR, (unsigned int)pE, 0);
return e.Error();
}
catch (...)
{
// 传递错误到Gdi线程来显示
BcamException* pE = new BcamException(DISP_E_EXCEPTION, "CLiveViewDlg::GrabThreadProc");
This->PostMessage(WM_ERROR, (unsigned int)pE, 0);
return DISP_E_EXCEPTION;
}
return 0;
}
DWORD CLiveViewDlg::DispThreadProc(void* pParameter)
{
CLiveViewDlg* This = (CLiveViewDlg*) pParameter; // instance pointer
HANDLE lpHandles[] = { This->m_evtNewBufferAvailable, This->m_evtTerminate };
try
{
DWORD result;
while (1)
{
switch ( result = WaitForMultipleObjects(2, lpHandles, FALSE, INFINITE) )
{
case WAIT_OBJECT_0: // new image to process
//说明正在处理图像
This->m_bOCROk = false;
while (!This->m_bOCROk)
{
// 取队列的队头数据
This->m_CritSect.Lock();
This->m_pBitmap = This->m_pMyQueue->OutQueue();
This->m_CritSect.Unlock();
// 如果为NULL,说明队列已空
if (This->m_pBitmap == NULL)
{
This->m_bOCROk = true;
break;//跳出循环,不显示
}
This->m_pBCameraSet->ConvertBitmap(This->m_pDispBitmap, This->m_pBitmap, This->m_ImageSize) ;
//如果做白平衡
if (This->m_bEnabledWhiteBalancer)
{
//如果白平衡结束
if ( This->m_WhiteBalancer.m_fConverged )
{
This->m_bEnabledWhiteBalancer = false;
}
//白平衡还没有结束
else
{
This->m_WhiteBalancer.Next(This->m_pDispBitmap, This->m_ImageSize);
long ub = This->m_WhiteBalancer.GetUBValue();
long vr = This->m_WhiteBalancer.GetVRValue();
// 更新状态显示
//This->m_dlgBar.SetUVal(ub);
//This->m_dlgBar.SetVVal(vr);
// Set the new white balance values.
// This is done synchronously, because we must ensure to enque the next buffer not before
// the settings are done.
if ( This->m_ColorCode != DCSColor_Mono8 )
{
This->m_Bcam.WhiteBalance.Raw.UBValue = ub;
This->m_Bcam.WhiteBalance.Raw.VRValue = vr;
This->m_nU=ub;
This->m_nV=vr;
}
else
{
This->m_pBCameraSet->SetBGain(ub / 100.0);
This->m_pBCameraSet->SetRGain(vr / 100.0);
}
}
}
if (This->m_test)
{
//加入辨识代码
This->IdentifyTest();
This->m_DisplayAvg.Add(This->m_DisplayWatch.Stop(true));
}
else if(This->m_start)
{
//假如开始比赛代码
This->StartGame();
This->m_DisplayAvg.Add(This->m_DisplayWatch.Stop(true));
}
else if(This->m_bIsDispImage)
{
// 如果显示采集图像
CDC *pDC = This->m_display.GetDC();
SetStretchBltMode(pDC->m_hDC,COLORONCOLOR);
SetDIBitsToDevice(pDC->m_hDC,0, 0,This->m_ImageSize.cx, This->m_ImageSize.cy,
0, 0,
0, This->m_ImageSize.cy, This->m_pDispBitmap,
This->m_ptrBmpInfo, DIB_RGB_COLORS);
This->m_display.ReleaseDC(pDC);
This->m_DisplayAvg.Add(This->m_DisplayWatch.Stop(true));
}
else{}
}
break;
case WAIT_OBJECT_0 + 1: // cancel
return 0;
default:
return 0;
}
}
}
catch (BcamException& e )
{
// 传递错误到Gdi线程来显示
BcamException* pE = new BcamException(e);
This->PostMessage(WM_ERROR, (unsigned int)pE, 0);
return e.Error();
}
catch (...)
{
// 传递错误到Gdi线程来显示
BcamException* pE = new BcamException(DISP_E_EXCEPTION, "CMainFrame::DispThreadProc");
This->PostMessage(WM_ERROR, (unsigned int)pE, 0);
return DISP_E_EXCEPTION;
}
return 0;
}
void CLiveViewDlg::OnStop()
{
// TODO: Add your control notification handler code here
try
{
// 停止将采集指令继续排入队列
m_RobotComm.SendCommand(0, 0, 0);
m_RobotComm.SendCommand(1, 0, 0);
m_RobotComm.SendCommand(2, 0, 0);
m_RobotComm.SendIt(0);
if(m_stop)
{
m_LiveGrabbing = false;
m_test=FALSE;
m_start=FALSE;
m_evtTerminate.Set();
InitOK=FALSE;
// 将当前已经排入队列的采集指令执行完成后从采集线程发送采集结束消息
m_Bcam.Notify(NotifyQuit, NULL);
KillTimer(ID_TIMER_DISPLAY);
m_stop=false;
UpdateData(FALSE);//是否需要??
}
}
CATCH_MSGBOX( "CLiveViewDlg::OnGrabStop" )
}
void CLiveViewDlg::SetBrightnessVal(UINT uBright)
{
m_brightness = uBright;//编辑框的变量
m_slidebrightness = uBright;//滑动条的变量
UpdateData(FALSE);
m_nBrightness = uBright;
if (m_bConnectBcam){
//采集
if (m_LiveGrabbing) {
m_Bcam.Brightness.Raw.SetAsync(uBright);
}
}
}
void CLiveViewDlg::SetGainVal(UINT uGain)
{
m_gain = uGain;
m_slidegain = uGain;
UpdateData(FALSE);
m_nGain = uGain;
//是否连接摄像机
if (m_bConnectBcam){
//采集
if (m_LiveGrabbing) {
m_Bcam.Gain.Raw.SetAsync(uGain);
}
}
}
void CLiveViewDlg::SetShutterVal(UINT uShutter)
{
m_shutter=uShutter;
m_slideshutter=uShutter;
UpdateData(FALSE);
m_nShutter=uShutter;
if(m_bConnectBcam)
{
if(m_LiveGrabbing)
{
m_Bcam.Shutter.Raw.SetAsync(uShutter);
}
}
}
void CLiveViewDlg::SetUVal(UINT uU)
{
m_u = uU;
m_slideu = uU;
UpdateData(FALSE);
m_nU=uU;
if(m_bConnectBcam)
{
if(m_LiveGrabbing)
{
if ( m_ColorCode != DCSColor_Mono8 )
{
m_Bcam.WhiteBalance.Raw.UBValue.SetAsync(uU);
}
else
m_pBCameraSet->SetBGain(uU / 100.0);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -