일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 코멘토 후기
- 논문리뷰
- 42seoul
- 3d object recognition
- 코멘토
- stereo image
- 카메라
- miniRT
- spinnaker
- AOLP
- point grey
- 라이다
- 객체인식
- 의사 라이다
- 편광카메라
- 42seoul #printf
- ft_server
- ouster
- 5월종합소득세
- 머신비전
- extrinsic
- intrinsic
- 동시취득
- LIDAR
- superresolution
- Python
- 직무부트캠프
- pseudo LiDAR
- 삼쩜삼
- FLIR
- Today
- Total
문무겸비
FLIR+LUCID 카메라 취득프로그램 개발기 - with Visual Studio 본문
목표
FLIR + LUCID 카메라 2ea간 동시 데이터 취득 프로그램 개발
(초기에는 FLIR 카메라 2ea간을 목표로 개발하였음)
개발환경
visual studio 20022
windows
타겟
spinnaker sdk(FLIR)
arena sdk(LUCID)
FLIR blackfly camera(모델명 :BFS-U3-51S5C-C)
LUCID triton camera(모델명:TRI050s-QC)
전후상황
FLIR 사의 blackfly camera sdk는 python으로 된 'PySpin' 이 있어 이것으로 좀 진행해 보았으나 결과가 미진.
실제 취득에 있어서 실시간성이나 렉을 감안하면 C++ 개발이 좀 더 유리할것으로 판단됨
blackfly 동기화 취득 관련 사이트
http://justinblaber.org/acquiring-stereo-images-with-spinnaker-api-hardware-trigger/ (pyspin으로 동기화 취득 구현)
환경세팅 과정
spinnaker sdk 처음 설치할때 spinview만 설치할지, spinview와 sdk를 함께 설치할지 묻는 부분 나오는데 둘 다 설치해야 한다.
spinnaker sdk는 헤더파일도 있고 lib 파일도 있고 dll 파일도 있고..그렇다. c++ sdk는 opencv 말곤 써본적이 없어 opencv에서 환경 구성하는 방법을 최대한 따라고보려고 한다
https://life-with-coding.tistory.com/86 (opencv 경로 설정법)
https://blessingdev.wordpress.com/2017/09/26/visual-studio%ec%97%90-%ec%99%b8%eb%b6%80-%eb%9d%bc%ec%9d%b4%eb%b8%8c%eb%9f%ac%eb%a6%ac-%ec%b6%94%ea%b0%80%ed%95%98%ea%b8%b0/ (Visual Studio에 외부 라이브러리 추가하기)
spinnaker에도 opencv마냥 dll이 있는데, 아래 링크를 통해 유추해 보건대 VS2010, 2013, 2015만 지원한다(이게 말이 되나....) https://www.flirkorea.com/support-center/iis/machine-vision/knowledge-base/distributing-spinnaker-applications/
근데 마소에서도 이제 VS community 2015를 지원안해주네?? 아래 링크에서 다운받았다..
바로 쓸 수는 없고, c++ 도구를 추가적으로 설치해야만 한다 ㅋㅋㅋㅋㅋㅋ
https://icdwkang.tistory.com/4
VS2015버전 코드라 하여도 Visual studio 2015를 다운받을 필요는 없다.
기존 프로젝트를 쓰면 되며, VS2022 에서도 VS2015환경을 사용할 수 있다
src 폴더에 예시 프로젝트가 다 있다... 우선 2015 설치부터 마무리 하자
아래 링크와 같은 문제가 있었고 (your license is expired) 링크를 통해 해결했다
sln 파일을 열면, 일단 다음과 같은 창이 뜬다.
옛날 버전이어서 어떻게 바꿀것이냐 묻는거 같은데 우선 업그레이드 안함으로 설정.(업그레이드를 해도 일단 동작하긴 한다)
동작 잘된다.
fopen을 못쓰게 하는데, 전처리기를 통해 그냥 넘어가자
spinnaker에서 제공해주는 프로젝트는 vs2022 에서도 잘 동작이 되는것을 확인했고 이를 직접 만들어 보고, 어떤 설정이 필요한지 정리가 필요한지 정리하자
왼쪽이 기본 제공 프로젝트, 오른쪽이 직접 만든 것이다. 리소스 파일 공부 필요 (없어도 돌아가는데..?)
만들때, 빈프로젝트를 생성해서 만들면 안되고, 기존 파일을 이용해서 프로젝트 생성을 해야 리소스파일, 소스파일, 헤더파일을 다 구분해서 생성해준다. (사실 파일 구조는 그렇게 중요한거 같지 않다.)
window sdk 버전은 10.0으로, 플랫폼 도구 집합을 2022로 해도 돌아가긴 한다.
추가 포함 디렉터리는 spinnaker\include 폴더를 넣어준다.
_DEBUG
WIN32
_CONSOLE
_CRT_SECURE_NO_DEPRECATE
전처리기 정의는 위 내용을 포함시켜준다
추가 라이브러리 디렉터리는 spinnaker\lib64, spinnaker\lib64\vs2015 를 포함시킨다
추가 종속성은 Spinnakerd_v140을 포함시킨다
_DEBUG
WIN32
_CONSOLE
_CRT_SECURE_NO_DEPRECATE
리스소 탭의 경우, 리소스 파일이 없으면 활성화 되지 않는것으로 보인다. 프로젝트 생성할때 분터
전처리기에는 위 내용을 포함시키고, 추가 포함 디렉터리는 spinnaker\include를 포함시킨다
sdk의 경우 선언, 헤더파일까지는 공개되어있고 열람 및 뜯어보는게 가능하나 소스코드는 dll이나 lib 형태로 컴파일 된 것을 제공해주기 때문에 모든 것을 다 분석할 수는 없다.
취득프로그램 개발
enum에서, 237은 BayerRGPolarized8을 의미하고, 4은 BayerRG8을 의미한다. 현재 만든 쓰레드 기반 취득 프로그램은 237일때 오류를 일으킨다
// pixel format을 바꾸는 코드
INodeMap& nodeMap = pCam->GetNodeMap();
CEnumerationPtr ptrPixelFormat = nodeMap.GetNode("PixelFormat");
cout << "Pixel format set to " << ptrPixelFormat->GetCurrentEntry()->GetSymbolic() << "...";
cout << "pCam->PixelFormat()" << pCam->PixelFormat() << endl;
if (IsAvailable(ptrPixelFormat) && IsWritable(ptrPixelFormat))
{
// Retrieve the desired entry node from the enumeration node
CEnumEntryPtr ptrPixelFormatMono8 = ptrPixelFormat->GetEntryByName("Mono8");
if (IsAvailable(ptrPixelFormatMono8) && IsReadable(ptrPixelFormatMono8))
{
// Retrieve the integer value from the entry node
int64_t pixelFormatMono8 = ptrPixelFormatMono8->GetValue();
// Set integer as new value for enumeration node
ptrPixelFormat->SetIntValue(pixelFormatMono8);
cout << "Pixel format set to " << ptrPixelFormat->GetCurrentEntry()->GetSymbolic() << "..." << endl;
}
else
{
cout << "Pixel format mono 8 not available..." << endl;
}
}
else
{
cout << "Pixel format not available..." << endl;
}
BayerPolarized8에서 Mono8으로 바꿀수가 없다.. 왜일까
Acquisition 실행결과를 볼 때, 껏다 키면, 그러니까 초기 상태는 BayeRG8이다
polarization_vs2015를 실행시키면 BayerRG8 -> BayerRGPolarized8로 변화되는것을 확인할 수 있다.
Acquisition 재실행 결과, BayerRGPolarized8로 여전히 되어있다.
polarization 재실행 결과, BayerRGpolarized8 로 고정되어 있다. Mono8은 원래 안되는 건가?
ImagePtr convertedImage = pResultImage->Convert(PixelFormat_Mono8, HQ_LINEAR);
생각해보니 convert를 했지 pixel format을 mono8로 바꾸는 경우는 없었네..
void ImageAcquisition(CameraPtr pCam)
{
for (size_t i = 0; i < 30; i++)
{
cout << "Acq! " << i << endl;
ImagePtr pResultImage = pCam->GetNextImage(1000);
myQueue.push(pResultImage);
}
}
void SaveImages(const char* filename)
{
ofstream file(filename, std::ios::binary);
file << "P6\n" << "\n255\n";
for (size_t i = 0; i < 30; i++)
{
//cout << "save!! " << i << endl;
if (!myQueue.empty())
{
file.write(reinterpret_cast<const char*>(&myQueue.front()), sizeof(ImagePtr));
myQueue.pop();
}
else
{
this_thread::sleep_for(chrono::milliseconds(10));
i--;
}
}
file.close();
}
image 취득을 한뒤, 저장하는 코드를 짰다. 헌데 데이터 크기가 16byte밖에 안되길래 왜 그럴까 고민해 봤는데.. 나는 이제까지 pointer의 크기 만큼을 저장하고 있었던 것이다. 데이터에 접근하도록 하자..
데이터에 접근하려니, ImagePtr이 무엇을 가리키고 있는지조차 알기 어렵고, 저장하는 과정은 ImagePtr->Save()로 멤버변수화 되어있는데 무슨 객체인지 알 수가 없다.
void ImageAcquisition(CameraPtr pCam)
{
for (size_t i = 0; i < 200; i++)
{
cout << "Acq! " << i << endl;
ImagePtr pResultImage = pCam->GetNextImage(1000);
myQueue.push(pResultImage);
}
}
void SaveImages(const char* filename)
{
ofstream file(filename, std::ios::binary);
file << "P6\n" << "\n255\n";
for (size_t i = 0; i < 200; i++)
{
cout << "save!! " << i << endl;
if (!myQueue.empty())
{
ostringstream filename_;
filename_ << "test";
filename_ << i << ".jpg";
//myQueue.front()->Save(filename_.str().c_str());
myQueue.front()->Save("test.bmp");
file.write(reinterpret_cast<const char*>(&myQueue.front()), sizeof(myQueue.front()));
myQueue.pop();
}
else
{
this_thread::sleep_for(chrono::milliseconds(100));
i--;
}
}
file.close();
}
연속 데이터 취득에 성공하였다. 다만.. 속도가 제대로 취득 되는것 같지가 않다. frame rate와 exposure time, 취득 시간을 모니터링 하면서 하자.
조금 괴상한 형태인데.. acq와 save가 thread로 설계되어 있으니까 적어도 acq는 꾸준히 되는게 맞는거 같은데 어째선지 acq부분이 save 속도에 종속되어있는것처럼 보인다. 어쩌면 queue 가 너무 쌓이면 문제가 되는게 아닐까 라는 생각이 좀 든다.
ImagePtr->Save()는 매개변수로 const char*만 받는다. 그러니까, "test.bmp"는 받아들이는데, string형태의 "test" + string(i) + ".bmp"는 안받아들인다.
ImagePtr은 Release()를 안해주니까 10개까지만 쌓이고 그 이상부터는 에러가 나오는것처럼 보인다. 근데 Release를 하면 queue에 얹어놓은 데이터도 해제되는게 아닐까? 확인이 필요하다. frame rate와 exposure time, 취득 시간을 모니터링 하면서 하자.
https://gitlab.ruhr-uni-bochum.de/ikn/syncflir
IKN / syncFLIR · GitLab
A synchronized multiview video recording setup in C++ using FLIR cameras and Spinnaker SDK on Windows machines.
gitlab.ruhr-uni-bochum.de
blackfly 카메라를 여러개 동시에 데이터 취득하는 프로젝트를 발견했다.
1. 멀티카메라
2. 연속데이터
3. 우선 raw 데이터 저장 이후 컨버팅 과정을 거치는 방식
여러모로 내가 원하던 조건을 만족한다ㅠㅠ
RECtoBIN, BINtoAVI 크게 두가지 프로그램으로 나뉘며, 각 프로그램 내용은 이름에서 쉽게 유추할 수 있다.
AVI 파일을 굳이 만들 필요는 없으니까 BINtoIMG 함수를 하나 만들어서 작업을 진행.
향후 개발 방향 및 세부 사항
1. 취득을 위한 GUI, 모니터링 기능 개발(두 카메라 다)
2. exposure time, frame rate 손쉽게 가변 가능하게.(향후 GUI에서 모니터링 및 조작 가능하게)
3. 편광, 가시광 각각 적절한 exposure time 찾기 (우선 가시광은 편광의 0.5배로 설정(16666[usec]))
this_thread를 쓰지 않고, windows API를 사용하여 thread를 구성. 카메라 취득 (2) + 모니터링(1) 하여 3개의 쓰레드가 돌아가게 설계.
100초가량 취득해보았을 때 문제 없었음
오래 취득할경우 용량 관리 잘 해야한다. 용량이 부족해 프로그램이 꺼질 경우, 재취득이 잘 안됨.
5분 이상 취득 문제 없음
myconfig.txt 파일이 없으면 취득이 안된다
일반 카메라 exposure time을 편광의 1/3로 하고 grayscale로 변환하여 비교해보았다.
opencv에서 cv::waitkey() GetAsyncKeyState를 이용해 키보드 이벤트를 받을 수 있는데, 이를 이용해 데이터 취득/일시정지를 구현하였다
그러나 취득 용량이 달라져버리는 현상이 생겼다..
키보드 이벤트를 받는 순간에서 동기화가 깨진다. 그러나 저장된 데이터를 이용해 매칭이 가능하니까 그냥 이 방식대로 가기로.
사실 키보드 이벤트를 받으면 취득 프로그램 종료로 하는게 낫겠다. 그러니까 '일시정지'보다는 '정지'.
일시정지 - 종료가 키보드 이벤트로 구현 되었고, 취득 장수가 정확하게 매칭이 되진 않지만 엑셀 데이터를 이용하여 매칭이 가능하다
향후 개발 방향 및 세부 사항
1. 취득을 위한 GUI, 모니터링 기능 개발(두 카메라 다) -> GUI는 제외, 모니터링 기능만 구현 完
2. exposure time, frame rate 손쉽게 가변 가능하게.(향후 GUI에서 모니터링 및 조작 가능하게) -> 모니터링 기능 구현 完
3. 편광, 가시광 각각 적절한 exposure time 찾기 -> (우선 가시광은 편광의 1/3배로 설정)
4. 카메라 지그 제작 , 카메라 제원, 차량 제원, 장착 위치,
5. pxie 환경에서 동작되는지 확인 필요 , 실행파일로 제작, pxie 환경에서 VS 깔리는지 확인 필요.
2023년03월24일
세부사항 5번 : pxie 환경 하에서 작동하는것을 진행하였다. (pxie환경에 굳이 vs를 깔 필요는 없었다)
release 모드에서 하면 cv::resize에서 에러가 나는데, release 속성에서 dll 참조를 debug용 dll이 참조가 되어있어서 생긴 문제로 보인다. 편광 카메라 취득에 있어서도 기존 프로젝트의 실행 파일(syncFLIR) 은 속도가 빠른데, 내가 만든 코드의 경우 매우 느리고 release로 바꿔도 속도 차이가 없어서 고심이었는데, release용 dll을 참조시켜주니 매우 빠른 속도로 동작했다.
vs 프로젝트를 실행파일로 만드는게 필요하다
https://splendidlolli.tistory.com/25
https://coding-factory.tistory.com/648 (release 모드, debug 모드 차이)
[비주얼 스튜디오] 콘솔 실행파일(exe)만들기 / "빌드를 통해서" | 2017, 2019
비주얼 스튜디오에서 만들어 본 프로젝트를 exe파일로 만들어보고 싶으실텐데요, 빌드를 통해 exe를 만드는 방법을 알아보겠습니다. 1단계. 솔루션 정리 빌드 메뉴에서 솔루션 정리를 클릭합니다
splendidlolli.tistory.com
실행파일로 만드는것 뿐 아니라 링크된 dll을 같이 넣어줘야 한다. 알아낸 바에 따르면, dll의 경로는 그냥 실행파일과 같은 폴더에 있는것만으로 자동 참조가 된다
이때, dependency walker나 dependencies를 이용하여 링크 관계를 알아낼 수 있으며, 이를 이용해 필요한 dll을 넣어준다.
https://www.dependencywalker.com/
https://github.com/lucasg/Dependencies
근데 사실 크게 도움이 된건진 모르겠다.. 그냥 bin 폴더에 있던 dll 다 넣는것과 크게 다르지 않은 작업을 했기 때문에..
pxie는 win7이고 거리도 멀어서 몇번 실패를 경험한 뒤에 삼성노트북으로(win10)으로 작업을 했는데 이런! 내 프로젝트는 물론이고 기존 프로젝트(syncFLIR) 실행파일도 안돌아가는것이 아닌가?
참조가 필요하다고 경고가 뜬 dll은 다음과 같다. 보시다시피 FLIR와 관련된것이 아니다.
단순히 dll을 복붙하는 문제가 아니라고 생각이 됐고, spinnaker sdk를 까는 과정에서 System32폴더에 여러 dll이 생성되는것이라고 판단, sdk를 깔아보니 내 프로젝트가 동작이 된다.
이에 착안하여, pxie에도 spinnaker sdk를 깔았고, 동작이 되는것을 확인하였다!!
이제 이미지 매칭이 정상적으로 이루어지는지 확인해보자
pxie 환경에서 취득해 봤을 때 9hz 으로 취득되기도, 30hz으로 취득되기도 하는 현상이 발생했다
21159646이(primary, filnumber=1)가 22623682보다 한프레임 빠르게 취득되어 나온다.
그리고 primary 카메라가 secondary 카메라보다 늦게 취득되어보이는 현상도 있다.
실도로 취득 결과. jpg로 추출하면 데이터 손상이 있다. bmp로 추출하여 이미지 변경이 없어야 훨씬 유의미해 보이는 데이터가 나온다. 이미지 프로세싱은(ex: hq linear)은 영향이 없는것으로 보임.
jpg로 추출하면 이미지 프로세싱을 하든 말든 안좋은 결과가 나온다.
FLIR 2ea -> FLIR+LUCID로 개발 방향 변경
기존 개발을 진행했던 FLIR 편광카메라 모델의 경우 auto algorithm이 적용이 되어있지 않아 부득이하게 LUCID 사의 편광카메라를 사용하여 취득 시스템을 구축하기로 하였다. 광량이 수시로 변하는 환경에서 auto algorithm이 없으면 사용가능한 이미지 취득이 어렵다.
변경된 HW로 인해 코드상의 수정이 필요했는데, 1.FLIR사에서 제공해준 example 2. LUICD사에서 제공해준 example 3. syncflir 프로젝트를 참고하여 취득 프로그램을 수정할 수 있었다. 코드설명은 github 참고
FLIR-FLIR 동기화 취득프로그램을 이해하고, 완성한 상태에여서 LUCID로 카메라를 교체하는것은 크게 어려운 부분은 없었다. 산업용 카메라는 보통 유사한 구조로 sdk를 설계하는듯 보인다.
서로 다른 회사의 카메라에 대해 동기화취득을 하기 위해 고려해야할 점이 있다. 기본적으로 자회사의 동기화 취득만 고려해서 설명을 해놓기 때문에 trigger 시스템을 구축하기 위해 각 회사 동기화 취득 문서를 숙지할 필요가 있다. 아래는 최종적으로 완성된 회로도이다.
프로그램 완성
https://github.com/lucas-korea/FLIR_LUCID_acquire
- FLIR 카메라(일반 가시광), LUCID 카메라(편광) 동시 취득 기능
- 센서별 동작 상태 확인기능
- 실시간 모니터링 기능
- 취득 로그 저장기능
'개인공부' 카테고리의 다른 글
센서간 캘리브레이션 개요 (0) | 2024.01.26 |
---|---|
c++을 이용한 serial 통신 (0) | 2023.06.07 |
PCL (point cloud library) 뜯어보기 (0) | 2023.01.11 |
편광카메라 이미지 분석 (0) | 2022.12.09 |
super reolution 프로젝트 따라하기, Simulation-based Lidar Super-resolution for Ground Vehicles 리뷰 (0) | 2022.05.31 |