이미지버퍼를 쉽게, 실수 없이 써보자

2021. 1. 4. 19:45장비제어개발관한이야기

반응형

진짜 오랜만에 포스팅을 하게 되네요. 그래도 새해 맞아 저의 회사생활을 정리 한다 생각하고 그 동안 미뤄 왔던 일을 하려합니다.

오늘따라 회의실에서 다리도 추운것이 회의에 집중이 안됩니다. 기본적인 난방, 냉방 이 필요하다 생각이 듭니다. 그래서 이미지처리(머신비전) 에서 제일 기본이되는 이미지 관리 클래스에 대해서 소개 하려합니다.

CHelaImage란?

Hela란........ 맞습니다. 당신이 생각하는 그 토르의 누나 입니다. 장난삼아 라이브러리를 만드는데, 메인 라이브러리 이름은 Ragnarok 이고, 그 및에 Vision 관련은 Hela로 이름을 지었습니다. 마블 영웅들이 하도 많아서 이름 짓기는 편한듯 합니다. (장난으로 시작하였지만,내용은 나름 장난(?) 이 아닙니다. ) 일단은, 가칭이라고 하겠습니다.

CHelaImage란? 장비시스템(가칭:R-System) 에서 영상처리시에 각 알고리즘간에 유기적으로 연동이 되는 기본적인 클래스 입니다. 거기다가 각 알고리즘간에 반복되는 작업을 묶어 놨습니다.

왜 필요한것일까?

실제로 영상처리를 하게 되면, 이미지 포맷이 RGB RawData, Bitmap, JPG, Bayer 에서 GPU 버퍼 까지 다양한 포맷을 처리해야 합니다. 각 포맷을 통일되게 구현하려면 하나로 묶을 필요가 있었습니다.

정리하자면, 3가지 이유가 있습니다.

첫째, 여러 이미지 버퍼 포맷의 효율적인관리

둘째, Color 변환 및 GPU 처리 의 등의 반복적인이고 알고리즘에 대한 편의성

셋째, 한번 만들었던 메모리구조(GPU버퍼, CMat) 등을 재활용 할수 있는 구조필요

위에 3가지 이점으로 라이브러리를 만들었습니다.

그럼, 어떻게 구현이 되어있나?

기본적인 구조는 필요한 자료형을 전부 선언이 되어있습니다. 차후에 더 필요한 자료형이 생길경우에 확장가능한 구조로 변경을 해야 하지만, 장비회사 답게 심플하게 기능 위주로 구현하였습니다. 일단 잘도는 소스가 필요하여 많이 심플합니다.

 

기본적인 Buffer(이미지관련Buffer) 관리는 OpenCV의 CMat를 사용합니다.

Color나 특수한 클래스가 필요할때는 포인터만 가지고 있다가 요청시에 생성하여 관련 포인터를 넘기는 구조로 되어 있습니다.

기본적은 Red,Green,Yellow는 CHelaImage 가 생성될때 초기화 되며 기타 Color 등의 특수한 버퍼들이 필요할경우에는 호출과 동시에 버퍼가 생성됩니다.

즉, 필요하진 특수 클래스(GPU 버퍼,Color 버퍼) 등은 호출될때 생성되고 클래스가 Delete 되기전까지 버퍼는 남아 있게 됩니다.

단계적으로 이미지 처리를 하개 되는 경우가 많아 메모리 재활용 측면에서 구현하게 되었습니다.

무엇을 얻었는가?

이부부은 제일 좀더 구체적으로 이야기 하려합니다.

500x500 R,G,B 각각 Plan 이 있는 이미지를 Cognex(ATL) 에 쓰이는 Color 이미지로 변환하기 위해서는 다음과 같이 작성해야 합니다.

void Foo(void)
{
	int iImgW = 500;
	int iImgH = 500;
    
    //<< 이미지버퍼
	unsigned char* pImageR = new unsigned char[iImgW *iImgH]; 
	unsigned char* pImageG = new unsigned char[iImgW *iImgH]; 
	unsigned char* pImageB = new unsigned char[iImgW *iImgH]; 
    //>>
	
    // 컬러정보가 들어있는 클래스
	CComPtr<ICogImage24PlanarColor> pcgRGB; 
    
    //기타
	CComPtr<ICogImage8Grey> pcgR;
	CComPtr<ICogImage8Grey> pcgG;
	CComPtr<ICogImage8Grey> pcgB;
	CComPtr<ICogImage8RootBuffer> pcgBufferR;
	CComPtr<ICogImage8RootBuffer> pcgBufferG;
	CComPtr<ICogImage8RootBuffer> pcgBufferB;	
	
	pcgBufferR->Initialize(iImgW, iImgH ,pImageR, iImgW, NULL);
	pcgR->SetRoot(m_pcgBufferR);
	pcgBufferG->Initialize(iImgW, iImgH , pImageG, iImgW, NULL);
	pcgBufferB->Initialize(iImgW, iImgH , pImageB, iImgW, NULL);
	pcgG->SetRoot(m_pcgBufferG);
	pcgB->SetRoot(m_pcgBufferB);
	pcgRGB->SetRoots(m_pcgBufferR, m_pcgBufferG, m_pcgBufferB);
}

 

 

스마트포인터(CComPtr) 생성빼고도 엄청 길기도 하고 해서 실수도 여러번 나오게 됩니다.

이제 Hela 이미지를 쓰게 되면 다음과 같이 심플해 집니다.

 

void HelaFoo(void)
{
	int iImgW = 500;
	int iImgH = 500;
    
    //>> 이미지버퍼
	unsigned char* pImageR = new unsigned char[iImgW *iImgH];
	unsigned char* pImageG = new unsigned char[iImgW *iImgH];
	unsigned char* pImageB = new unsigned char[iImgW *iImgH];
    //<<
    
    // 컬러정보가 들어있는 클래스
	CComPtr<ICogImage24PlanarColor> pcgRGB; 
    
	CHelaImage cHelaImage(iImgW,iImgH,pImageR,pImageG,pImageB);
	pcgRGB = cHelaImage.GetCogImageRGB();		
}

 

나중에 Color이미지를 다시 쓰게 될때도 새로 만들 필요도 없고 여러모로 잘쓰고 있습니다.

실제로, 코딩하기 귀찮고 자꾸 실수가 나와서 만든 클래스입니다. ^^*

항상 편하고 실수 없는 소스가 좋은 소스라 생각합니다. 장비쪽에서 일하시는 분들 추운 겨울에 항상 건강 챙기세요.

 

 

 

 

외부에 노출되는 클래스 일부만 첨부합니다. 내용은 간단합니다. 뭐, 나름 회사에서 작업한거라 회사꺼라서 풀소스 공유는 힘들어요 ㅠ.ㅠ

 

HelaImage.cpp
0.00MB
HelaImage.h
0.00MB

 

반응형