Y 뱡향, X 방향 MIP 를 만들어보자.

2018, Jul 16    

이전 포스팅 에서는 Z 방향으로 MIP 를 만들어 보았는데, X 방향 Y 방향 또는 어떤 방향에서도 MIP 를 만들 수 있다.

작업을 수행하기 전에,

코드를 유연하게 만들기 위해 Volume 이미지로 하는 작업을 클래스로 만들어 캡슐화 해보자. 이전 구조는 Doc 에서 Volume class 를 부르는 구조 였는데 이제 Doc 에서는 Renderer 클래스를 호출하고 Rendere 클래스가 Volume 관련 작업을 하도록 바꿔보자.

VolumeRendererDoc.h

#pragma once
// #include "Volume.h"
#include "Renderer.h"
#include <memory>
using namespace std;

class CVolumeRendererDoc: public CDocument
{
private:
    //shared_ptr<Volume> m_pVolume;
    shared_ptr<Renderer> m_pRenderer;
}

VolumeRendererDoc.cpp

...
BOOL CVolumeRendererDoc::OnNewDocument()
{
    ...

    //m_pVolume = shared_ptr<Volume>(new Volume(temp_vol,width,height, depth));
    m_pRenderer = shared_ptr<Renderer>(new Renderer(temp_vol,width,height,depth));
    ...
}

이제 Rendere Class 를 만들자.

Renderer.h

#include "Volume.h"
#include <memory>
using namespace std;

class Renderer
{
private:
    shared_ptr<Volume> m_pVolume;
public:
    Renderer();
    Renderer(unsigned char* volume, int width, int height, int depth);
    ~Renderer();
}

Renderer.cpp

#include "stdafx.h"
#include "Renderer.h"

Renderer::Renderer()
{
    m_pVolume = nullptr;
}

Renderer::Renderer(unsigned char* volume,int width, int height, int depth)
{
    m_pVolume = shared_ptr<Volume>(new Volume(volume, width, height, depth));
}

Renderer 클래스를 거의 다 만들었다. 이제 기능만 추가해서 넣어주면 된다.

X, Y, Z 방향으로 잘라서 보여주는 기능을 만들어보자.

VolumeRendererDoc.cpp

void CVolumeRendererDoc::OnSlicerenderingXdirection()
{
    // 이미지 버퍼를 만들어 넣어주고
    // Renderer 클래스 함수에서 채워서 바깥으로 던지는 방식으로 만들 것이다.
    const int img_width = 256;
    const int img_height = 256;
    shared_ptr<unsigned char> image = 
        shared_ptr<unsigned char>(new unsigned char[img_width*img_height]);

    // x 좌표를 넣어주어서 x 좌표 중 어느 부분을 보여줄지 정한다.
    m_pRenderer->RenderSliceXDirection(image.get(), img_width, img_height, 120);

    CVolumeRendererView* pView =
		(CVolumeRendererView*)((CMainFrame*)(AfxGetApp()->m_pMainWnd))->GetActiveView();

	pView->SetDrawImage(image.get(), img_width, img_height, 1);

	pView->OnInitialUpdate();
}

Renderer.cpp

bool Renderer::RenderSliceXDirection(unsigned char* image, 
    const int img_width, const int img_height, const int depth)
{
    int vol_height = m_pVolume->GetHeight();
    int vol_depth = m_pVolume->GetDepth();

    for(int i=0; i<vol_height; i++)
    {
        for(int j=0; j<vol_depth; j++)
            image[j*img_width + i] = m_pVolume->GetVoxel(depth,i, j);
    }
    
    return true;
}

Y 방향 Z 방향은 위와 같으므로 알아서 만들어보자.

MIP 를 Y뱡향과 X 방향으로 만들어보자.

VolumeRendererDoc.cpp

void CVolumeRendererDoc::OnMiprenderingXdirection()
{
	// TODO: 여기에 명령 처리기 코드를 추가합니다.

	int img_width = 256;
	int img_height = 256;

	shared_ptr<unsigned char> image =
		shared_ptr<unsigned char>(new unsigned char[img_width*img_height]);
	memset(image.get(), 0, sizeof(unsigned char)*img_width*img_height);

	m_pRenderer->RenderMIPXDirection(image.get(), img_width, img_height);

	CVolumeRendererView* pView =
		(CVolumeRendererView*)((CMainFrame*)(AfxGetApp()->m_pMainWnd))->GetActiveView();

	pView->SetDrawImage(image.get(), img_width, img_height, 1);

	pView->OnInitialUpdate();
}

Renderer.cpp

bool Renderer::RenderMIPXDirection(unsigned char* image,
    const int width, const int height)
{
    int vol_width = m_pVolume->GetWidth();
    int vol_height = m_pVolume->GetHeight();
    int vol_depth = m_pVolume->GetDepth();

    for(int j = 0; j< vol_depth; j++)
    {
        for(int i=0; i< vol_height; i++)
        {
            unsigned char max_value = 0;
            for(int k=0; k< vol_width; k++)
            {
                max = __max(max_value, m_pVolume->GetVoxel(k,i,j));
            }
            image[width*j + i] = max;
        }
    }
}

같은 방식으로 Y 방향기능만 구현해보면 아래와 같다.

Renderer.cpp

bool Renderer::RenderMIPYDirection(unsigned char* image,
    const int width, const int height)
{
    int vol_width = m_pVolume->GetWidth();
    int vol_height = m_pVolume->GetHeight();
    int vol_depth = m_pVolume->GetDepth();

    for(int j = 0; j< vol_depth; j++)
    {
        for(int i=0; i< vol_width; i++)
        {
            unsigned char max_value = 0;
            for(int k=0; k< vol_height; k++)
            {
                max = __max(max_value, m_pVolume->GetVoxel(i,k,j));
            }
            image[width*j + i] = max;
        }
    }
}

MIP X-direction 은 아래와 같고 MIP-X

MIP Y-direction 은 아래와 같다. MIP-Y