본문 바로가기
Various Developments/3D Moire Scanner

3D Moire Scanner 개발 - sinusoidal 패턴 만들기

by 토담이아빠 2023. 1. 25.

앞서 정리한 알고리즘을 적용하기 위해서는 각 frame별 물체에 의해 왜곡된 패턴이미지가 필요합니다. 그러기 위해서는 projector에 넣어줄 이미지를 먼저 만들어야 합니다. 이미지는 opencv를 이용하여 생성하였습니다.


sinusoidal 패턴 수식 코딩하기

 

sinusoidal 패턴은 sin 또는 cos 어느 것을 선택해도 상관없습니다. 사용한 수식은 아래와 같습니다.



위 수식을 C++을 이용해 함수로 바꾸어봤습니다.


unsigned char GetCosineValue(const int& position, const int& wavelength_px, const int& shift_phase)
{
	float val = 255.f * cos((2.f * PI / (float)wavelength_px) * position - shift_angle) + 255.f;
	return (unsigned char)(val / 2.f);
}

cos값의 범위는 -1 ~ 1까지입니다. 하지만 비트맵 이미지의 표현 범위는 0~ 255이므로 최대값이 255가 되게끔 스케일링을 해야 합니다. 그래서 진폭값에는 255를 곱했습니다. 이렇게 되면 값의 표현 범위는 -255 ~ 255까지가 됩니다. 비트맵 이미지는 음수값이 없으므로 initial value로 255를 더해줍니다. 그러면 값의 범위는 0 ~ 510이 되어서 return 시 2로 나눠주면 됩니다.

 

패턴 생성하기

 

위 함수는 하나의 픽셀값에 대한 결과를 반환하므로 원하는 사이즈의 패턴을 생성하기 위해서는 반복문을 사용해야 합니다.


void MakeCosineDataY(const int& sizeX, const int& sizeY, const int& wavelength_px, const float& shift_angle, unsigned char* result)
{
	for (int y = 0; y < sizeY; y++)
	{
		unsigned char* r = &result[y*sizeX];
 
		for (int x = 0; x < sizeX; x++) // 단위는 픽셀
		{
			r[x] = GetCosineValue(y, wavelength_px, shift_angle);
		}
	}
}

이렇게 하면 이미지 한 장에 대한 패턴이 만들어집니다. 원하는 이미지는 위상이 shift 된 4장의 이미지 이므로 shift_angle 인자로 90도씩 변하는 위상값을 대입해 주면 됩니다.(여기서 각도는 전부 라디안(radian)값으로 계산됩니다. 예를 들어 90도만큼 shift 하고 싶으면 라디안 값인 PI/2씩 증가시키거나 빼줍니다.)  다음은 최종 패턴을 생성하는 함수입니다.


void SaveCosineYPatternImage(const int nFrame, const int sizeX, const int sizeY, const int wavelength_px, const char* Folder, const char* filename)
{
	std::vector<unsigned char> vecBuffer; vecBuffer.resize(sizeX*sizeY); //임시 버퍼
	float shift_angle = 0.f;
	for (int i = 0; i < nFrame; i++)
	{
		MakeCosineDataY(sizeX, sizeY, wavelength_px, shift_angle, &vecBuffer[i]); //한장의 패턴 이미지
		shift_angle += PI / 2.f; //90도씩 shift

		cv::Mat image(sizeY, sizeX, CV_8UC1, &vecBuffer[i]);
		std::string path = cv::format(Folder, filename, i + 1) + cv::format("\\%s%d.bmp", filename, i + 1); //경로 지정
		cv::imwrite(path, image); // 이미지 저장
	}
}

위 함수를 사용하여 실제 패턴을 생성해 보겠습니다. 생성할 패턴은 크기가 1920 * 1080이고 파장은 100px입니다. 


	int nFrame = 4;
	int wavelength_px = 100;
	int sizeX = 1920;
	int sizeY = 1080;
	const char* foldername = "D:\\3D 모아레 개발\\pattern";
	const char* filename = "cos_pattern_";
	SaveCosineYPatternImage(nFrame, sizeX, sizeY, wavelength_px, foldername, filename);

결과

4-frame pattern - 연속 촬영

 

4-frame pattern - 개별 이미지


 

댓글