Basler GigE Camera를 이용하여 영상을 캡쳐해보자
- Pylon Lib 설치방법: https://cafe.daum.net/smhan/darS/3
* 샘플소스 코드: 수정함 (양진모학생 수정사항 적용함)
이번 소스에는 OpenCV를 사용하지 않고 pylon 라이브러리만 사용하여 영상처리를 한다. 내부 소스에서 bitmap을 처리하기 위해 모두 8bit 영상으로 바꾸어 처리한다. 처리하는 함수는 bmp.cpp/bmp.h에서 다룬다. 참고: bmp.cpp와 bmp.h를 사용할 때에 버그가 있을 수 있으니 SimpleBmp 클래스를 사용하길 바람 (안정적버전)
- 다음 소스코드는 vs2013버전에서 vs2023버전으로 변경한 코드이다.
* 프로젝트 작성
| 단계 | 예제 코드 |
| Pylon Lib 설치 | https://cafe.daum.net/smhan/darS/3 |
| 프로젝트 생성 | 프로젝트를 Dialog based로 생성한다. |
| BMP파일 추가 | bmp.cpp와 bmp.h bmp 소스파일: https://cafe.daum.net/smhan/cczU/67 |
| 프로젝트 속성 | 구성속성->VC++ 디렉터리 -> 포함 디렉터리 $(PYLON_DEV_DIR)\include 구성속성->VC++ 디렉터리 -> 라이브러리 디렉터리 $(PYLON_DEV_DIR)\lib\x64 |
| 전역변수와 함수를 선언한다. | BOOL m_bThreadFlag; // 쓰레드 루프 돌기 UINT ThreadImageCaptureFunc(LPVOID param); // 쓰레드 함수 Image* m_Image; // 화면에 그리는 영상 이미지 CInstantCamera *m_pCamera; // Basler Camera CGrabResultPtr ptrGrabResult; // This smart pointer will receive the grab result data. |
| 초기화 | BOOL CbaslerCam2013Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); ... // TODO: 여기에 추가 초기화 작업을 추가합니다. PylonInitialize(); CTlFactory& tlFactory = CTlFactory::GetInstance(); DeviceInfoList_t devices; if (tlFactory.EnumerateDevices(devices) == 0) { MessageBox(L"Basler Camera가 연결되지 않았습니다."); } else { // Create an instant camera object with the camera device found first. m_pCamera = new CInstantCamera(CTlFactory::GetInstance().CreateFirstDevice()); INodeMap *m_pNodeMap; //GenericParameterAccess try { if (m_pCamera->IsOpen()) AfxMessageBox(_T("Camera is opened!")); else { //카메라 이벤트 처리가 먼저 활성화되어야합니다, 기본값은 꺼짐입니다. m_pCamera->GrabCameraEvents = true; // 카메라가 발견되었습니다. 생성하고 인스턴트 카메라의 객체에 연결합니다. m_pCamera->Attach(tlFactory.CreateDevice(devices[0])); if (m_pCamera->IsPylonDeviceAttached()) { m_pCamera->Open(); m_pCamera->MaxNumBuffer = 1; m_pNodeMap = &m_pCamera->GetNodeMap(); CIntegerPtr offsetX(m_pNodeMap->GetNode("OffsetX")); CIntegerPtr offsetY(m_pNodeMap->GetNode("OffsetY")); CIntegerPtr width(m_pNodeMap->GetNode("Width")); CIntegerPtr height(m_pNodeMap->GetNode("Height")); int new_width = 1024; int new_height = 624; width->SetValue(new_width); height->SetValue(new_height); offsetX->SetValue((int)(new_width / 2)); offsetY->SetValue((int)(new_height / 2)); CString str; str.Format(_T("Found camera: %s\nWidth: %d\nHeight: %d"), CString(m_pCamera->GetDeviceInfo().GetModelName()), width->GetValue(), height->GetValue()); AfxMessageBox(str); m_pCamera->Close(); } } } catch (GenICam::GenericException &e) //Error Handling { // Error handling CString strTrace; strTrace.Format(_T("Open_Camera - GenericException : %s\n"), (CString)e.GetDescription()); AfxMessageBox(strTrace); return FALSE; } } return TRUE; // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다. } |
| 화면출력 | void CbaslerCam2013Dlg::OnPaint() { if (IsIconic()) { .... } else { CDialogEx::OnPaint(); if (m_pImage != NULL) { // --------------------------------------------------------------- // 카메라에서 읽어들인 영상을 화면에 그리기 // --------------------------------------------------------------- CRect rect; CDC* pDC; pDC = m_View.GetDC(); m_View.GetClientRect(rect); DrawImage(&m_View, m_pImage); ReleaseDC(pDC); // --------------------------------------------------------------------- // 칼라영상을 이진화 한다. // --------------------------------------------------------------------- pDC = m_ViewBin.GetDC(); m_ViewBin.GetClientRect(rect); Image* image2 = CreateImage(m_pImage->width, m_pImage->height); for (int y = 0; y < image2->height; y++) { for (int x = 0; x < image2->width; x++) { if (m_pImage->imageData[y*m_pImage->width + x] > 100) image2->imageData[y*m_pImage->width + x] = 255; else image2->imageData[y*m_pImage->width + x] = 0; } } DrawImage(&m_ViewBin, image2); FreeImage(image2); ReleaseDC(pDC); // --------------------------------------------------------------- } } } |
| 카메라 영상 캡처 시작 버튼을 누르면 쓰레드를 실행한다. | void CbaslerCam2013Dlg::OnBnClickedCamStart() { if (m_pCamera == NULL) { MessageBox(L"Basler Camera를 연결 후 다시 실행시켜주세요."); return; } m_pCamera->StartGrabbing( /*c_countOfImagesToGrab*/); m_bThreadFlag = TRUE; CWinThread *pThread = ::AfxBeginThread(ThreadImageCaptureFunc, this); } |
| 멈춤 버튼을 누르면 쓰레드 플래그를 false로 만들어 종료시킨다. | void CbaslerCam2013Dlg::OnBnClickedCamStop() { if (m_pCamera == NULL) { MessageBox(L"Basler Camera를 연결 후 다시 실행시켜주세요."); return; } m_pCamera->StopGrabbing(); m_bThreadFlag = FALSE; } |
| 쓰레드 함수 | UINT ThreadImageCaptureFunc(LPVOID param) { CbaslerCam2013Dlg *pDlg = (CbaslerCam2013Dlg *)param; if (m_pCamera == NULL) return 0; while (m_bThreadFlag) { // 영상 획득 try { if (m_pCamera->IsGrabbing()) { // Wait for an image and then retrieve it. A timeout of 5000 ms is used. m_pCamera->RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException); if (ptrGrabResult->GrabSucceeded()) { // Access the image data. const uint8_t *pImageBuffer = (uint8_t *)ptrGrabResult->GetBuffer(); if (m_pImage == NULL) { m_pImage = CreateImage(ptrGrabResult->GetWidth(), ptrGrabResult->GetHeight()); } memcpy(m_pImage->imageData, pImageBuffer, ptrGrabResult->GetWidth() * ptrGrabResult->GetHeight()); } else { CString str; str.Format(_T("Error: %d %s", CString(ptrGrabResult->GetErrorCode()), CString(ptrGrabResult->GetErrorDescription())) ); AfxMessageBox(str); } pDlg->Invalidate(FALSE); } } catch (GenICam::GenericException &e) { cerr << "An exception occurred. " << e.GetDescription() << endl; } } return 0; } |
첨부파일첨부된 파일이 3개 있습니다.
다음검색