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

3D Moire Scanner 개발 - 위상 맵(Phase Map) 계산

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

이번 포스팅에서는 전 포스팅에서 제작한 4-frame 이미지를 이용하여 실제 대상체에 투사하고 위상맵을 얻는 과정까지의 내용을 정리했습니다.

 

[4-fram 이미지 제작 참조]

2023.01.25 - [여러가지개발/3D Scanner] - 3D Scanner 개발 - sinusoidal 패턴 만들기

 

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

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

todamfather.tistory.com


투사 이미지 획득

 

측정에 사용할 대상으로 100원짜리 동전을 선택했습니다. 이순신 장군님의 형상이 새겨진 모양에 따라 투사된 패턴의 모양이 미세하게 왜곡됩니다.


Projector 패턴 투사


위상 맵을 계산하기 위에 다음 식이 사용되었습니다.



위 식의 유도는 다음 포스팅을 참고하시면 됩니다.


2023.01.18 - [여러가지개발/3D Scanner] - 3D Scanner 개발 - 모아레(Moire) 현상을 이용한 3차원 형상 측정의 원리

 

3D Scanner 개발 - 모아레(Moire) 현상을 이용한 3차원 형상 측정의 원리

개인 개발의 첫 프로젝트로 3D scanner의 핵심 알고리즘을 구현해 볼까 합니다. 3차원(3D) 측정 알고리즘에는 여러 가지가 있겠지만 산업현장에서 보편적으로 널리 쓰이는 모아레 알고리즘을 구현

todamfather.tistory.com


위상맵(Phase Map) 계산

 

다음은 위상맵을 계산하기 위한 함수입니다. 실제 코드에는 예외처리 및 노이즈처리 코드도 들어 있으나 여기서는 핵심만 정리하기 위해 제외했습니다.


bool calculate_phase_4bucket(const vector<MoireImage<unsigned char>>& src_vecimg, MoireImage<double>& dst_img)
{
        int sizeX = src_vecimg[0].getWidth();
        int sizeY = src_vecimg[0].getHeight();

        for (int y = 0; y < sizeY; y++) {
            unsigned char* p1 = &(src_vecimg[0].getBuffer()[y * sizeX]);
            unsigned char* p2 = &(src_vecimg[1].getBuffer()[y * sizeX]);
            unsigned char* p3 = &(src_vecimg[2].getBuffer()[y * sizeX]);
            unsigned char* p4 = &(src_vecimg[3].getBuffer()[y * sizeX]);
            
            double* ph = &dst_img.getBuffer()[y * sizeX];
            
            for (int x = 0; x < sizeX; x++) {
                double phase = 0.0;
                phase = std::atan2(double(p4[x] - p2[x]), double(p1[x] - p3[x]));
                ph[x] = phase;
            }
        }

    return true;
}

위 함수에 매개변수로 들어가는 MoireImage<T> 클래스는 이미지 계산을 편리하게 하기 위해 별도로 만든 이미지 처리 클래스입니다. 

 

코드를 간략하게 쓰기 위해 각 이미지 주소를 가리키는 포인터를 p1, p2, p3, p4로 새로 정의하고 (12) 수식에 대입했습니다. (12) 수식을 코드로 표현하면 다음과 같습니다.


 phase = std::atan2(double(p4[x] - p2[x]), double(p1[x] - p3[x]));

위상맵 계산 결과는 opencv를 이용해 출력했습니다. 결과는 아래 이미지와 같습니다.


위상맵 계산 결과


위 이미지가 알록달록한 이유는 위상값을 크기에 따라 색깔(RGB)로 표현했기 때문입니다.

 

댓글