태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

[Vision] Camera management class - 카메라 관리 클래스

Posted on 2008.04.08 00:59
Filed Under Project


[code][Header]
#include <pylon/TlFactory.h>
#include <pylon/Result.h>
using namespace Pylon;
using namespace GenApi;
//#define USE1394
#ifdef USE1394
// settings to use  Basler 1394 cameras
#include <pylon/1394/Basler1394Camera.h>
typedef Pylon::CBasler1394Camera Camera_t;
using namespace Basler_IIDC1394CameraParams;
using namespace Basler_IIDC1394StreamParams;
#else
// settings to use Basler GigE cameras
#include <pylon/gige/BaslerGigeCamera.h>
typedef Pylon::CBaslerGigECamera Camera_t;
using namespace Basler_GigECameraParams;
using namespace Basler_GigEStreamParams;
using namespace Basler_GigETLParams;
#endif
#pragma once
class CCamera
{
public:
    BOOL Init();                    //객체 초기화
    int Connect();                   //카메라 연결
    void Close();                   //카메라 닫기
    void ReadParameter();                //파라미터 리드
    void LiveGrabStart();                 //라이브그랩 시작
    void LiveGrabStop();                 //라이브그랩 중지
    void Display(unsigned char* Buffer);           //외부에 정의될 Display 멤버
    static UINT LiveThread(LPVOID pParam);          //라이브그랩 스레드
   
    /* PylonSDK member */
    ITransportLayer *pTI;
    eviceInfoList_t m_devices;           // Connect camera list
    Camera_t *m_pCamera;                 // Select Camera
    Camera_t::StreamGrabber_t *m_pStreamGrabberCamera;  // StreamGrabber
    StreamBufferHandle hBuffer;
   
    /* Genicam member */
    GenApi::CNodeMapRef *m_pCameraNodeMap; 
    CIntegerPtr ptrOffsetX;             
    CIntegerPtr ptrOffsetY;             
    CIntegerPtr ptrAoiWidth;           
    CIntegerPtr ptrAoiHeight;           
    CCommandPtr ptrAcquisitionStart;
    CCommandPtr ptrAcqStopCamera;
   
    /* Camera Work Flag */
    BOOL m_bStopLiveThread;     // Live Thread flag
    BOOL m_bStopFlg;      // Stop flag
      
    /* Image Infomation */
    size_t m_ImageSize;
    int  reSizeWidth;
    int m_iOffsetX;
    int m_iOffsetY;
    int m_iWidth;
    int m_iHeight;
   
    /* Camera Image  Original Buffer */
    unsigned char *pImageOrgBuffer;         // Camera Buffer
}; [/code]

[code][Source]
#include "StdAfx.h"
#include "Camera.h"
#define PYLON_MSG_FAILD_CAMERA_FOUND  0
#define PYLOG_MSG_SUCCESS_OPEN    1
//라이브그랩 쓰레드
UINT CCamera::LiveThread(LPVOID pParam)
{   
    CCamera *ThreadReference = (CCamera*)pParam;
      
    ThreadReference->hBuffer = ThreadReference->m_pStreamGrabberCamera->
    RegisterBuffer(ThreadReference->pImageOrgBuffer,ThreadReference->m_ImageSize);
    ThreadReference->m_pStreamGrabberCamera->QueueBuffer( ThreadReference->hBuffer, NULL );
    // Start acquisition on the camera 
    ThreadReference->ptrAcquisitionStart = ThreadReference->m_pCameraNodeMap->_GetNode ("AcquisitionStart");
    ThreadReference->ptrAcquisitionStart->Execute ();
    while(ThreadReference->m_bStopLiveThread==TRUE){
        // Wait for grabbed image with timeout of 3 seconds
        GrabResult Result;     
        if (ThreadReference->m_pStreamGrabberCamera->GetWaitObject().Wait( 3000 ) ){
            // Get the grab result from the grabber's result queue
            ThreadReference->m_pStreamGrabberCamera->RetrieveResult( Result );
            if ( Result.Succeeded() ){
                ThreadReference->pImageOrgBuffer = (uint8_t *) Result.Buffer(); 
                ThreadReference->Display(ThreadReference->pImageOrgBuffer);
                if(ThreadReference->m_bStopLiveThread==TRUE){
                    ThreadReference->m_pStreamGrabberCamera->QueueBuffer( Result.Handle(), NULL );
                }
                if(ThreadReference->m_bStopFlg==FALSE){
                    ThreadReference->m_bStopLiveThread=FALSE;
                }
            }
            else {
                if(ThreadReference->m_bStopLiveThread==TRUE){
                    ThreadReference->m_pStreamGrabberCamera->QueueBuffer( Result.Handle(), NULL );
                }
            }
            }
        else{
            if(ThreadReference->m_bStopFlg==FALSE){     
                ThreadReference->m_bStopLiveThread=FALSE;
            }
        }
    }
    ThreadReference->ptrAcqStopCamera = ThreadReference->m_pCameraNodeMap->_GetNode ("AcquisitionStop");
    ThreadReference->ptrAcqStopCamera->Execute ();     
    ThreadReference->m_pStreamGrabberCamera->CancelGrab (); 
    Sleep(1);
    for ( GrabResult r; ThreadReference->m_pStreamGrabberCamera->RetrieveResult( r ););
    Sleep(1);
    ThreadReference->m_pStreamGrabberCamera->DeregisterBuffer(ThreadReference->hBuffer);
    Sleep(10);
    return 0;
}

BOOL CCamera::Init( )
{
    m_pCamera = NULL;
    m_pStreamGrabberCamera = NULL;
    m_iOffsetX = NULL;
    m_iOffsetY = NULL;
    m_iWidth = NULL;
    m_iHeight = NULL;
    m_bStopLiveThread= FALSE; 
    m_bStopFlg = TRUE;
    CTlFactory& TlFactory = CTlFactory::GetInstance();
    pTI = TlFactory.CreateTl( Camera_t::DeviceClass() );
    if ( ! pTI ){
        return TRUE;
    }
    return FALSE;
}

int CCamera::Connect()
{
    try {
        /* 1.디바이스 오픈 */
        m_devices.clear ();     
        pTI->EnumerateDevices (m_devices);   
        if (m_devices.empty ()) { //장치가 없을 경우
            return PYLON_MSG_FAILD_CAMERA_FOUND;
            }
        else {
            for (DeviceInfoList_t::iterator it = m_devices.begin (); it != m_devices.end (); it++)
            {         
                CString m_strCamName;
                m_strCamName=(*it).GetFriendlyName ().c_str ();
        
                /*CString m_LogString;
                m_LogString.Format(_T("[INFOMATION] Camera model : %s\n"),m_strCamName);
                m_Log.WriteLog(SUCCESS_CAMERA_FOUND);
                m_Log.WriteLogString(m_LogString);*/
            }
        }
       
        /* 2.카메라 오픈 */
        if (m_pCamera && m_pCamera->IsOpen ()){       
            m_pStreamGrabberCamera->Close (); 
            m_pCamera->Close ();
            pTI->DestroyDevice (m_pCamera);
            //m_Log.WriteLog(SUCCESS_CAMERA_CLOSE);
        }

        m_pCamera = NULL;
        m_pCamera =  dynamic_cast<Camera_t*>(pTI->CreateDevice(m_devices[0]));  // 카메라가 한대만 연결했을때는 인덱스가 0
        m_pStreamGrabberCamera =  dynamic_cast<Camera_t::StreamGrabber_t*>(m_pCamera->GetStreamGrabber(0));  // 현재 Pylon SDK1.0은 Streamgrabber 0만 지원 한다.           
        m_pCamera->Open (); 
        m_pStreamGrabberCamera->Open (); 
        m_pCameraNodeMap = m_pCamera->GetNodeMap ();
        m_pCamera->PixelFormat.SetValue(PixelFormat_YUV422Packed);
        ReadParameter();

        /* 3.카메라 연결 */
        // Set
        ptrOffsetX->SetValue (m_iOffsetX);
        ptrOffsetY->SetValue (m_iOffsetY);
        ptrAoiWidth->SetValue (m_iWidth);
        ptrAoiHeight->SetValue (m_iHeight);
        // buffer alloc
        reSizeWidth=(((m_iWidth*8)+31)/32*4);  // width 4byte 배수 계산
        // 파라미터 전달
        CIntegerPtr ptrPayloadSize = m_pCameraNodeMap->_GetNode ("PayloadSize");
        m_ImageSize = (size_t) (ptrPayloadSize->GetValue ());
        GenApi::CNodeMapRef *pGrabberNodeMap = m_pStreamGrabberCamera->GetNodeMap ();
        CIntegerPtr ptrMaxBufferSize = pGrabberNodeMap->_GetNode ("MaxBufferSize");
        ptrMaxBufferSize->SetValue (m_ImageSize);
        CIntegerPtr ptrMaxNumBuffer = pGrabberNodeMap->_GetNode ("MaxNumBuffer");
        ptrMaxNumBuffer->SetValue (1);
        m_pStreamGrabberCamera->PrepareGrab (); 
        /* 카메라에서 입력받을 이미지공간 할당*/
        pImageOrgBuffer =new unsigned char[m_iWidth*m_iHeight*3];  // 원본 이미지       
        memset(pImageOrgBuffer,0,m_iWidth*m_iHeight*3);
        return PYLOG_MSG_SUCCESS_OPEN;
    }
    catch(CFileException* pEx)
    {
        if(pEx->m_cause  == CFileException::fileNotFound)              
        pEx->Delete();
    }
}

/*  카메라 닫기 */
void CCamera::Close()
{
    try
    {
        if (m_pCamera && m_pCamera->IsOpen ()){ 
            if(m_pStreamGrabberCamera->IsOpen()){ 
                m_pStreamGrabberCamera->Close ();
            }   
            m_pCamera->Close ();
            pTI->DestroyDevice (m_pCamera);
        }
        m_pCamera = NULL; 
    }
    catch(CFileException* pEx)
    {
        if(pEx->m_cause  == CFileException::fileNotFound)              
        pEx->Delete();
    }     
}

/* 파라미터 읽기 */
void CCamera::ReadParameter()
{
    try{
        // AOI control info
        ptrOffsetX = m_pCameraNodeMap->_GetNode ("OffsetX"); 
        m_iOffsetX = (int)ptrOffsetX->GetValue ();
        ptrOffsetY = m_pCameraNodeMap->_GetNode ("OffsetY"); 
        m_iOffsetY = (int)ptrOffsetX->GetValue (); 
        ptrAoiWidth = m_pCameraNodeMap->_GetNode ("Width");
        m_iWidth = (int)ptrAoiWidth->GetValue ();
        ptrAoiHeight = m_pCameraNodeMap->_GetNode ("Height"); 
        m_iHeight = (int)ptrAoiHeight->GetValue ();
    }
    catch(CFileException* pEx)
    {
        if(pEx->m_cause  == CFileException::fileNotFound)              
        pEx->Delete();
    }
}

void CCamera::LiveGrabStart()
{
    if(m_bStopLiveThread == FALSE){
        AfxBeginThread(CCamera::LiveThread,this);
        m_bStopLiveThread = TRUE;
    }
}

void CCamera::LiveGrabStop()
{
    m_bStopLiveThread = FALSE;
    m_bStopFlg = FALSE;
} [/code]


Camera Management Class


 Class : CCamera
Include : Camera.h


[Member Method]
BOOL Init();                    //객체 초기화
int Connect();                   //카메라 연결
void Close();                   //카메라 닫기
void LiveGrabStart();                 //라이브그랩 시작
void LiveGrabStop();                 //라이브그랩 중지
void Display(unsigned char* Buffer);           //외부에 정의될 Display 멤버

static UINT LiveThread(LPVOID pParam);          //라이브그랩 스레드
void ReadParameter();                //파라미터 리드



 일반적인 초기화 밑 사용 순서는 다음과 같다.
Init -> Connect -> LiveGrabStart() -> (LiveThread 생성, 내부적으로 Display 를 호출) -> LiveGrabStop -> Close

디펜던시한 구조를 가지기 위해 Display 메소드는 사용자가 적절한 위치에 정의하여야 한다.
LiveThread 에서 실질적으로 가져온 이미지의 결과를 Display 메소드를 통해 호출하기 때문에 받아온 이미지를 실제로 처리할 위치에서 정의하는 것이 일반적인 사용의 예다.

다중 카메라에 대한 지원은 되지 않으며 이에 대한 추가는 쓰레드에 대한 부분과 초기화 작업의 수정이 필요하다.

현재 프로젝트에 적용된 예를 보면 메인 다이얼로그에는 자체 다이얼로그를 전역으로 선언해놓은 객체포인터를 가진다.
컨트롤 메뉴와 다른 클래스에서도 참조되는 중요한 객제포인터이기 때문에 Display 메소드 구현도 메인 다어얼로그에 되어있다.
메인다이얼로그에 정의된 Display 메소드는 메인다이얼로그의 멤버 Display 메소드를 호출하는 간단한 구조로 되어있다.
다른 프로그램에 적용할 때는 이 Display 메소드만 적절하게 구현해주면 디펜던시를 유지할 수 있다.



신고

댓글을 달아 주세요

About



모바일 페이지 QR 코드

Counter

· Total
: 468,751
· Today
: 103
· Yesterday
: 142


DNS server, DNS service