BLOG main image
FunnyPR (32)
OpenGL (20)
PatternRecognition (7)
Tips (2)
XML (1)
DataMining (1)
Visitors up to today!
Today hit, Yesterday hit
daisy rss
tistory 티스토리 가입하기!
'FunnyPR'에 해당되는 글 32건
2014. 5. 4. 18:48

■ OpenGL: Normal Vector


1. 법선벡터

법선(法線, normal)벡터: 임의 두 점사이 직선에 90도 각도로 수직을 이루는 선을 법선이라고 함.

- 아나 한국말은 용어가 어렵다. 한문 하나하나 봐야 이해가 된다. 법은 法일반적인 법법이고 선은 줄선線인데 법에 다른 의미로 모형 도는 꼴 법이라고도 할 수 있고.... 모형의 선? 아놔.. 이렇게 만드니 이해하기 어렵다. 그냥 그림으로 보는게 좋다. 



그림에 파란색 아이를 법선 벡터라고 하고 이 벡터는 각 꼭지점을 지나는 평면을 그리면 무수하게 많이 표현될 수 있다. 


3D 개념에서 법선벡터를 이해하는게 중요하다고 한다. 


왜 모든 꼭지점(Vertex)에 법선 벡터를 만들어야 하나?

-  모든 꼭지점에 법선 벡터를 사용함으로써 울퉁불퉁한 곡면을 부드럽게 표현, 완벽한 조명 적용 가능 하다고 함


http://opengl.czweb.org/ch09/275-279.html



 

위 그림에서 x, y 평면에 면이 하나 있고 점 (1,1,0)이 존재 한다. 이 점을 기준으로 수직으로 (1,10,0)을 그었을때 이 직선을 법선벡터(Normal Vector)이라고 함 





법선벡터를 좀더 간단히 표현하기 위해 기존의 (1, 1, 0 ) - (1, 10 ,0)을 하면 그림에서 볼 수 있듯이 Translated Normal vector이 나오게 된다.


벡터란 방향을 알려주는 역할을 하며 여기서는 버텍스나 폴리곤이 어떤 방향으로 위치해 있는지 OpenGL에게 알려주게 됨


1
2
3
4
5
6
glBegin(GL_TRIANGLES);
        glNormal3f(0.0f, -1.0f, 0.0f);
        glVertex3f(0.0f, 0.0f, 60.0f);
        glVertex3f(-15.0f, 0.0f, 30.0f);
        glVertex3f(15.0f,0.0f,30.0f);
glEnd();


위 소스에 보면 삼각형을 만드는데 3개의 꼭지점이 있고 법선벡터가 y 축의 -1.0으로 설정된것을 확인할 수 있다. 법선벡터 설정은 glNormal3f 함수를 사용한다. 


폴리곤 설정시 법선벡터는 폴리곤의 앞으로 나아감.


2. 단위 법선 벡터

법선벡터 -->정규화 --> 단위 벡터 --> OpenGL

단위가 1인 벡터를 단위벡터라고 함. 

단위가 1인 법선벡터를 만들기 위해서 정규화(Normalization) 과정이 들어간다. 

glEnable(GL_NORMALIZE); // 효율적이지 못하다. 

glEnable(GL_RESCALE_NORMALS); // 단위 길이(1)이 아니지만 같은 비율을 통해 단위길이로 변환할 수 있음

때문에 직접 계산하는것이 프로세싱 속도를 높이는데 도움이 된다. 


단위벡터 만들기: (x^2 + y^2 + z^2)^1/2 하면 됨



3. 법선 벡터 찾기 




위 4점으로 만들어진 Polygon(면)에서 법선 벡터를 어떻게 구할까?

3점만 있으면 구하기 쉽다. 

위 점들 중 3개점을 각각 P1, P2, P3라 지정하고 P1과 P2를 연결하는 V1 벡터, P1과 P3를 연결하는 V2벡터로 지정





수학: 두 벡터가 한점에서 만나면 평면을 만들 수 있고, 두 벡터 V1, V2 외적을 구하면 그 평면의 법선벡터를 구할 수 있다.

1. 3지점을 얻어 한점에서 만나는 두개의 벡터를 그림 

2. 두 벡터의 외적을 구하여 법선벡터를 구함




http://opengl.czweb.org/ch09/279-282.html


법선벡터 구하는 예제

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
// Points p1, p2, & p3 specified in counterclockwise order
void calcNormal(float v[3][3], float out[3])
        {
        float v1[3],v2[3];
        static const int x = 0;
        static const int y = 1;
        static const int z = 2;
 
        // Calculate two vectors from the three points
        v1[x] = v[0][x] - v[1][x];
        v1[y] = v[0][y] - v[1][y];
        v1[z] = v[0][z] - v[1][z];
 
        v2[x] = v[1][x] - v[2][x];
        v2[y] = v[1][y] - v[2][y];
        v2[z] = v[1][z] - v[2][z];
 
        // Take the cross product of the two vectors to get
        // the normal vector which will be stored in out[]
        out[x] = v1[y]*v2[z] - v1[z]*v2[y];
        out[y] = v1[z]*v2[x] - v1[x]*v2[z];
        out[z] = v1[x]*v2[y] - v1[y]*v2[x];
 
        // Normalize the vector (shorten length to one)
        ReduceToUnit(out);
        }


좀 더 공부해서 법선벡터를 많이 사용할때의 곡면 표현의 차이점을 봐야 겠다. 










'OpenGL' 카테고리의 다른 글

OpenGL: Text in OpenGL  (0) 2014.05.15
OpenGL: Selection and Picking  (0) 2014.05.05
OpenGL: Index of Vertex Array  (0) 2014.05.04
OpenGL: Geometric and Vertex  (0) 2014.05.04
OpenGL: gluPerspective, glFrustum  (0) 2014.04.20
2014. 5. 4. 17:25

 OpenGL: Index of Vertex Array


요번에는 꼭지점배열과 인덱스의 관계를 알아 보려 한다. 


꼭지점 인덱스 배열사용 이유

 - 메모리 절약과 불필요한 변환을 줄이는 효과


꼭지점과 법선벡터를 배열 선언하여 사용할 경우 

- 다시 계산하지 않고 재사용하게 되기 때문에 메모리 양을 줄일 수 있고, 버텍스에 대한 변환도 줄일 수 있다.(시간 절약).

- 다음의 사각형을 Vertex와 Index 배열을 사용해서 그려보장




http://www.anandtech.com/show/391/6



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GLfloat RectVertex[]={
    -20.0f,  20.0f,  20.0f,//0
     20.0f,  20.0f,  20.0f,//1
     20.0f, -20.0f,  20.0f,//2
    -20.0f, -20.0f,  20.0f,//3
    -20.0f,  20.0f, -20.0f,//4
     20.0f,  20.0f, -20.0f,//5
     20.0f, -20.0f, -20.0f,//6
    -20.0f, -20.0f, -20.0f //7
};
 
GLubyte RectIndexes[]={
    0,1,2,3,//Front
    4,5,1,0,//Top
    3,2,6,7,//Bottom
    5,4,7,6,//Back
    1,5,6,2,//Right
    4,0,3,7 //Left
};


우선 사각형의 vertex 배열을 만들고 나서 각 인덱스 배열을 선언

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
void C3DScatterPlot::RenderScene(void)
{
    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
    glMatrixMode(GL_MODELVIEW);
 
    glPushMatrix();
            glTranslatef(0.0f, 0.0f, -350.0f);
            glRotatef(xRot, 1.0f, 0.0f, 0.0f); //x 
            glRotatef(yRot, 0.0f, 1.0f, 0.0f); //y
 
    //배열의 사용
    glEnableClientState(GL_VERTEX_ARRAY);
 
    glColor3f(0.0f, 1.0f, 0.0f); //색상
 
    //데이터 위치 
    glVertexPointer(3, GL_FLOAT, 0, RectVertex);
 
    //드로잉
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, RectIndexes);
 
    glPopMatrix();
}


glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);// 와이어 프레임으로 드로잉

인덱스 값은 바이트 포멧을 가진다. 

glVertexPointer(3, GL_FLOAT, 0, RectVertex); //버텍스 배열에서 3개씩 묵음으로 위치를 가져온다. 

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, RectIndexes);//

void glDrawElements(

GLenum   mode, //Specifies what kind of primitives to render

GLsizei   count, //Specifies the number of elements to be rendered.

GLenum   type,   //Specifies the type of the values in indices.

const GLvoid *   indices // Specifies a pointer to the location where the indices are stored.

);

여기서 모드는 다음과 같은 심볼을 써야 함

GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, 

GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS, and GL_POLYGON

type값은 다음과 같은 심볼을 써야 함

GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT.

http://www.opengl.org/sdk/docs/man2/xhtml/glDrawElements.xml








'OpenGL' 카테고리의 다른 글

OpenGL: Selection and Picking  (0) 2014.05.05
OpenGL: Normal Vector  (0) 2014.05.04
OpenGL: Geometric and Vertex  (0) 2014.05.04
OpenGL: gluPerspective, glFrustum  (0) 2014.04.20
OpenGL: Setting Viewport  (0) 2014.04.19
2014. 5. 4. 17:03

■ OpenGL: Geometric and Vertex


지오메트릭은 머 도형이라고 이해하면 좋다. 그리고 버텍스는 꼭지점이다. 즉 꼭지점을 알고 있으면 선으로 연결하여 도형을 만들 수 있는 관계가 성립된다. 


OpenGL에서 도형을 만들기 위한 방법으로 

 - 지원되는 함수 사용

 - glBegin - glEnd를 통해 그리기 

가 있는 것 같다. 하지만 이 함수보다 효율적으로 빠르게 도형을 만들기 위해서 버텍스 배열을 사용한다고 한다. 한번 알아 보자 어떻게 하는지


1. OpenGL에서 Vertex 사용 방법

step 1: 디스크 파일 또는 알고리즘을 통해 지오메트리 데이터를 읽어 배열에 저장

    - 위치 또는 도형에 대한 vertex 정보를 담은 vertex 배열을 선언한다. 


step 2: Vertex 배열 사용 설정 

    - OpenGL은 클라이언트(CPU)와 서버(그래픽 하드웨어)등 두가지 방법으로 동작함.

    - 클라이언드 모드에서 Vertex 배열 사용 설정 함수 

          - glEnableClientState(GL_VERTEX_ARRAY) / glDisableClientState(GL_VERTEX_ARRAY) : 활성함수와 비활설 함수 짝을 이룬다.

void glEnableClientState(GLenum  cap);

Specifies the capability to enable. Symbolic constants GL_COLOR_ARRAY, GL_EDGE_FLAG_ARRAY, GL_FOG_COORD_ARRAY, GL_INDEX_ARRAY, GL_NORMAL_ARRAY, GL_SECONDARY_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY, and GL_VERTEX_ARRAY are accepted.

http://www.opengl.org/sdk/docs/man2/xhtml/glEnableClientState.xml

step 3: 배열의 형태 지정(vertex, color, normal vector, etc.)

vertex 배열을 선언하고 사용하겠다라고 예기했으니 데이터를 얻을라면 어디 버텍스 정보를 가져다 써라라고 해줘야 함. 아래와 같은 여러 함수가 있는데 입맛에 따라서 골라서 써야 함. 복잡하지만 정리하면 다음과 같음

================================================================================================

- GLint size: 좌표 타입을 구성하는 요소(두개 -x,y 세개-x,y,z 내게-x,y,z,w) 

- CLenum Type: 실수 인지 정수인지 데이터 포멧(GLfloat)

- GLsizei stride: stride is the byte offset between consecutive vertexes. If stride is 0, the vertices are understood to be tightly packed in the array.(배열에서 가져올때 간격을 말하는듯, 0이면 배열 0,1,2..,N 이렇게 순차적으로 가져오고 만약 1이면 0, 2, 4, ...,N 요렇게? 가져 올듯)

- GLvoid *pointer: 데이터를 가져올 Vertex 배열 

================================================================================================

void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);

void glIndexPointer(GLenum type, GLsizei  stride, const GLvoid *pointer);

void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer);

void glTexCoordPointer(GLint size, GLenum type, GLsizei stride,  const GLvoid *pointer);

void glEdgeFlagPointer(GLsizei stride, const GLvoid *pointer);

void glVertexPointer(GLint size, GLenumtype, GLsizei stride, const GLvoid *pointer); //버텍스 위치 정보

Command

Sizes

Values for type Argument

glVertexPointer

2, 3, 4

GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

glNormalPointer

3

GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

glColorPointer

3, 4

GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_DOUBLE

glIndexPointer

1

GL_UNSIGNED_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

glTexCoordPointer

1, 2, 3, 4

GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

glEdgeFlagPointer

1

no type argument (type of data must be GLboolean)

http://www.felixgers.de/teaching/jogl/vertexArrayData.html


 glVertexPointer(2, GL_FLOAT, 0, Vertex);//좌표 타입 x,y로 구성, 데이터 포멧은 GLfloat, 데이터 간격은 0으로 Vertex 배열에 위치 지정 


step 4: 배열 정보 랜더링 

이제 마지막으로 꼭지점들의 정보를 받았으니 이 정보들을 랜덩링해서 보여주면 된다. 

glDrawArrays(GL_POINTS, 0, 10); // POINT 형식으로 처음 0 번째 부터 10개를 그려라 

glDrawArrays(CLenum 모드, GLint 처음, GLint 개수); 

GLenum 모드: OpenGL 의 Basic Model 중 하나가 되고

GLint 처음: 이전 지정한 vertex 배열에서 시작 주소

GLint 개수: 시작 지점으로 부터 읽을 vertex 의 개수가 됨


2. 예제 

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
void C3DScatterPlot::RenderScene(void)
{
   // Clear the window with current clearing color
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glTranslatef(0.0f, 0.0f, -350.0f); //원근 투영을 사용하고 있으므로 z좌표를 뒤로 350 이동하여 보기 
 
    GLfloat Vertex[10][2]; //꼭지점 정보 저장을 위한 2차원 배열 설정
 
    for(int i=0; i<10; i++){ //10개의 x, y 좌표를 랜덤하게 Vertex 배열에 저장
        Vertex[i][0]=(GLfloat)(rand()%50); // y 
        Vertex[i][1]=(GLfloat)(rand()%50); // x
    }
 
    //Vertex 배열 사용 활성화- 클라이언트 모드
    glEnableClientState(GL_VERTEX_ARRAY);
 
    //포인트를 그릴때 크기 지정
    glPointSize(10.0f);
 
  //색상 지정 
    glColor3f(0.0f, 1.0f, 0.0f);
 
    //Vertex 배열 위치 지정 
    glVertexPointer(2, GL_FLOAT, 0, Vertex);
    
    //드로잉
    glDrawArrays(GL_POINTS, 0, 10);
 
}


void glDrawArrays(

GLenum   mode,

GLint   first,

GLsizei   count

);

mode

Specifies what kind of primitives to render. Symbolic constants GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_LINE_STRIP_ADJACENCY, GL_LINES_ADJACENCY, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_TRIANGLE_STRIP_ADJACENCY and GL_TRIANGLES_ADJACENCY are accepted.


first

Specifies the starting index in the enabled arrays.


count

Specifies the number of indices to be rendered.




위에 보면 랜덤으로 x,y 를 저장하고 있는 꼭지점 배열의 정보를 가져와 10의 사이즈를 갖는 Point들이 드로잉 된것을 볼 수 있다. 


http://www.felixgers.de/teaching/jogl/vertexArrayData.html

'OpenGL' 카테고리의 다른 글

OpenGL: Normal Vector  (0) 2014.05.04
OpenGL: Index of Vertex Array  (0) 2014.05.04
OpenGL: gluPerspective, glFrustum  (0) 2014.04.20
OpenGL: Setting Viewport  (0) 2014.04.19
OpenGL: Setting Clipping region  (0) 2014.04.19
2014. 4. 25. 19:41

■ Neural Networks: Data normalization


http://www.cs.sunysb.edu/~cse634/ch6NN.pdf

뉴럴 네트워크에서는 입력과 출력 데이터의 정규화가 필요하다. 위 사이트에 보면 데이터 정규화 방법으로 두개가 나와 있다. 


All values of attributes in the dataset has to be changed to contain values in the interval [0,1], or [-1,1].

모든 데이터는 0~1, -1~1 사이 값에 포함되도록 바꿔야 한다. 


Two basic normalization techniques:

- Max-Min normalization

- Decimal Scaling normalization 


Max-Min normalization formula



Example: We want to normalize data to range of the interval [0,1].

We put: new_max A=1, new_min A  = 0


Say, max A was 100 and min A was 20(That means maximum and minimum values for the attribute A).


Now, if v=40(if for this particular pattern, attribute value is 40), v' will be calculated as, 

v'=(40-20)*(1-0)/(100-20)+0

   = (20 * 1)/80

   = 0.4(?) 아닌거 같은데... 0.25 아닌가?!!


Decimal Scaling Normalization formula


where j is the smallest integer such that max|v’|<1.


Example :

A–values range from -986 to 917. Max |v| = 986.

v = -986 normalize to v’= -986/1000 = -0.986

2014. 4. 23. 17:24

 The Basic Artificial Neuron: Bias neuron(Backpropagation)


역전파 알고리즘 - 바이어스 노드 


역전파 알고리즘은 각 뉴런의 출력 신호를 결정하기 위해서 입력(입력 신호와 연결 무게를 곱하고 나서 모두 합한값)에 활성화 함수(Activation Function)를 적용한다. 

- 활성화 함수의 임계값 변동을 흡수하기 위한 가중치를 바이어스(편견)이라고 하며, 항상 1의 값을 가진다. 



여러 활성화 함수 그림이다. 


여기서 질문이 생긴다. 활성화 함수의 임계값 변동을 흡수(?-책에서 이렇게 씀)하기 위한 가중치 바이어스 노드를 항상 1로 설정한다라고 되어 있는데 왜 1인가 그리고 구체적인 이유가 무엇인가?


우선 구글링 한 정보를 정리하면 다음과 같다. 


http://stackoverflow.com/questions/2480650/role-of-bias-in-neural-networks

http://stackoverflow.com/questions/8039313/why-is-a-bias-neuron-necessary-for-a-backpropagating-neural-network-that-recogni



답변에 보면 바이어스 값(bias value)는 성공적인 학습을 위해 활성화 함수를 좌우로 움직일 수 있게 해준다라고 한다. 단순한 예제를 보면 다음과 같다. 


Case 1 : 바이어스 없이 하나의 입력과 출력의 구성

simple network

출력은 입력 x와 가중치 w0의 곱을 활성화 함수에 넣어 계산할 수 있다. 

network output, given different w0 weights

위 그림은 활성화 함수를 sigmoid로 하고 가중치 w0의 값이 0.5, 1.0, 2.0으로 변화 할때 입력과 출력에 관한 결과 그래프 이다. 위 그래프에서 보면 가중치 값이 변화함에 따라 sigmoid 의 가파름(steepness) 정도가 변화는 것을 확인할 수 있다. 이 결과는 유용하지만 만약 입력이 2개이고 출력이 하나인 네트워크를 구성할때 변화하는 시그모이드 함수의 steepness는 동작하지 않는다고 한다. (먼 예기야?)


위 커브들을 오른쪽으로 모두 옴기길 원하면 바이어스를 사용해야 한다.


다음 case를 보고 차이점을 보자 

Case2: Case1 + Bias Neuron

simple network with a bias

그림에 보면 입력층에 Bias Neuron을 추가된 것을 확인할 수 있다. 그럼 출력은 sig(w0*x+w1*1.0)으로 계산될 수 있다. 아래 그림은 w1의 변화에 따른 네트워크 출력에 대한 그래프이다. (w0 = 1.0)

network output, given different w1 weights

그림에 보면 바이어스 뉴런을 하나 추가하여 가중치 w1의 변화에 따라 출력이 좌우로 움직이(shift)되는 것을 확인할 수 있다. 아하!!!(센스 있는 사람은 눈치 챘을 것이다.) 


@user1621769: The main function of a bias is to provide every node with a trainable constant value (in addition to the normal inputs that the node recieves). You can achieve that with a single bias node with connections to N nodes, or with N bias nodes each with a single connection; the result should be the same. –  Nate Kohl Mar 24 '13 at 13:24


위 빨간색을 보면 중요한 얘기를 하고 있다. 

바이어스의 중요한 기능은 훈련 가능한 상수 값을 가지는 모든 노드를 제공하는 것이다. 

즉 바이어스 노드 없이 훈련 가능한 것들도 있지만 아마 다른 경우에 sigmoid 임계 범위에 있지 않은 값들의 출력은 의미가 없어져 훈련이 되지 않을 수도 있다.

http://www.nnwj.de/backpropagation.html

위 사이트에서 보면 보다 이해하기 쉬울 것이다. 

http://www.mathworks.co.kr/kr/help/nnet/ug/perceptron-neural-networks.html

여기 사이트에서도 bias 의 역할을 설명하고 있다. 바이어스의 또 다른 역할은 기본 영역에서 항상 시프트하여 경계를 결정하게 해 줌 아래와 같이 점선에서 실선으로 바이어스를 적용하여 경계를 옴김



그럼 실제 뉴럴 계층에 bias neuron을 어떻게 적용시켜야 하나 문제다. 다음 그림을 보자.


http://ufldl.stanford.edu/wiki/index.php/Neural_Networks


Network331.png


왼쪽 부터 입력 레이어(L1), 히든 레이어(L2), 출력 레이어(L3)로 나타난다. 보면 bias neuron이 입력과 히든레이어에 존재한다. 

바이어스 뉴런은 다음 계층에 연결되지만 이전 계층에는 연결되지 않는 특징을 가진다. 


입력층: 입력 노드(d) + 바이어스 노드(1)

은닉층: 은닉 노드(p) + 바이어스 노드(1)

  은닉층의 노드 개수를 p라고 할때 하나의 바이어스 노드를 더해 은닉층의 총 노드 개수는 p+1개가 된다. 

출력층: 원하는 출력 노드 수(m)


그럼 입력층과 은닉층 사이 가중치는 몇개?

입력층: d+1

은닉층: p

입력층과 은닉층의 가중치: (d+1)*p 개


그럼 은닉층과 출력층의 가중치는 몇개?

은닉층: p+1

출력층: m

은닉층과 출력층의 가중치: (p+1)*m 




위 그림은 Basic Structure of an artificial neuron 그림이다. 맘에 들어서 가져 왔다. 자세한 설명은 

http://engineeronadisk.com/book_modeling/neural.html

에 있다.