perpet

ttt

카테고리 없음2013. 4. 3. 10:32
ttt

Comment +1

스터디 할때 공부좀 한거. 


Comment +0

surf

스터디/C++,CLI,C#2011. 5. 14. 00:13

 

 http://en.wikipedia.org/wiki/SURF

 

여기서 설명하는 SURF 알고리즘 opencv 에 있는 find_obj 소스코드를 기반으로 만들어졌다.

 

1.특징점 추출

( octave , layer , wavelet, hessian 을 이용해 크기와 회전에 강한 특징점을 찾아낸다)

 

 1-1 소스 이미지 integral(적분) 한다.

 개요 : wavelet 정보를 뽑을때 적분영상이 있어야 빠른 wavelet 정보를 만들수있음

 참고자료 :

 http://www.codeproject.com/KB/audio-video/haar_detection.aspx

 http://aisitei.tistory.com/174

 입력 : 입력영상

 처리 : x 축 y 축을 증가시키면서 누적된 픽셀정보를 저장한다

 출력 : 적분을 표현(representation) 한 영상

 

1-2 wavelet 정보 추출

 개요: wavelet mask 를 이용해 wavelet 정보를 octave *  layer 갯수 만큼 만든다

 octave: 이미지의 샘풀링 갯수를 지정 : ( 참고자료 : sift 의 의도와 비슷한 뜻)

              만약 3 이라면

               원본이미지 -> 원본이미지/2 -> 원본이미지 /4   의 이미지를 가짐

 layer : 해당 octave 이미지에 몇개의 layer(size) 로 wavelet 정보를 만들지 결정

            만약 3이라면

             wavelet size   ->  wavelet size  / 2 -> wavelet size/4

 

참고자료:

 http://www.cs.ucf.edu/~mali/haar/

http://www.codeproject.com/KB/graphics/edge_detection.aspx?msg=2331630

 입력 :

적분 영상

Wavelet data

    const int dx_s[NX][5] = { {0, 2, 3, 7, 1}, {3, 2, 6, 7, -2}, {6, 2, 9, 7, 1} };
    const int dy_s[NY][5] = { {2, 0, 7, 3, 1}, {2, 3, 7, 6, -2}, {2, 6, 7, 9, 1} };
    const int dxy_s[NXY][5] = { {1, 1, 4, 4, 1}, {5, 1, 8, 4, -1}, {1, 5, 4, 8, -1}, {5, 5, 8, 8, 1} };

x                                                                     y                                                  xy

Wavelet(1).png 

 

 처리 :  

dx  = icvCalcHaarPattern( s_ptr, Dx, 3 );
dy  = icvCalcHaarPattern( s_ptr, Dy, 3 );
dxy = icvCalcHaarPattern( s_ptr, Dxy, 4 );


각각의 (x , y xy)  wavelet data 를 이용해 x,y,xy 값을 추출

출력 : layer 별 각각의 x,y,xy 정보를 추출

 

 1-3  헤시안 연산

 개요:  x,y,xy 의 wavelet 정보를 바탕으로 헤시안 연산을 하여 hessianThreshold 값이 넘으면 이웃 헤시안 값을 비교 하여 layer 을 포함한 이웃 26 개 정보와 비교후 가장 값이 크면 interpolation 후 특지점으로 추가한다

 입력 : layer 별 wavelet (x,y,xy) 정보

 처리 :

  *det_ptr++ = (float)(dx*dy - 0.81*dxy*dxy);
 *trace_ptr++ = (float)(dx + dy);

연산후 

 

 /* Non-maxima suppression. val0 is at N9[1][4]*/
                        if( val0 > N9[0][0] && val0 > N9[0][1] && val0 > N9[0][2] &&
                            val0 > N9[0][3] && val0 > N9[0][4] && val0 > N9[0][5] &&
                            val0 > N9[0][6] && val0 > N9[0][7] && val0 > N9[0][8] &&
                            val0 > N9[1][0] && val0 > N9[1][1] && val0 > N9[1][2] &&
                            val0 > N9[1][3]                    && val0 > N9[1][5] &&
                            val0 > N9[1][6] && val0 > N9[1][7] && val0 > N9[1][8] &&
                            val0 > N9[2][0] && val0 > N9[2][1] && val0 > N9[2][2] &&
                            val0 > N9[2][3] && val0 > N9[2][4] && val0 > N9[2][5] &&
                            val0 > N9[2][6] && val0 > N9[2][7] && val0 > N9[2][8] )

 

이웃중 가장 큰값인지 확인을 한후 보간을 통해 더 정확한 값을 얻어와서 특지점 리스트에 추가한다.

여기서 보간의 의미는 opencv 게시판에 누군가 잘설명한 것이 있는데 차후 주소를 알게되면 링크추가 예정

 

//////////////////////////////////////////////////////////////////////////////

 2.디스크립터 만들기

찾아낸 특징점에 고유영역을 표현할수있는 디스크립터를 만든다.

 

2-1 orientation 가우시안 웨이트를 만든다.

아래 링크에 있는 이미지와같은 정보를 얻음

http://retina.anatomy.upenn.edu/~lance/modelmath/gaussian.html

ORI_RADIUS = 6

ORI_RADIUS * ORI_RADIUS  방향에 따른 가우시안 웨이트 생성

 

2-2 patch 정보에 대한 가우시안 웨이트를 만든다.

 PATCH_SZ = 20

 PATCH_SZ * PATCH_SZ 영역에 대한 가우시안 웨이트 생성

 

2-3 각방향에 대한 orientation 정보 생성

 개요 : 특징점 주위 6 *6  사이즈안에 있는 모든 포인트에대해서 wavelet 수치를 얻는다.

입력 : 적분이미지

 

처리 :

                        

                 Untitled(3).png

 

black : 특징점

 red : ORI_RADIUS * ORI_RADIUS 방향 안에 있는 점들

green : PATCH_SZ 사이즈 박스 * 특지정에 포함된 사이즈 정보( 소스 100% 분석 안함)

 

green 박스와 아래 wavelet data  연산을 하여 orientation 정보를 만듬

 wavelet2.png

 

 각도에 따른 모든 wavelet 수치를 합산하여 가장 큰 각도 값을 얻는다. 가령 위에서는 파란색이 가장 큰 각도라 판단함

 

 출력 : 가장 수치가 높은 각도를 얻음( 회전에 강한 정보를 얻기위한 초기단계)

 

 2-4 디스크립터 생성

개요 : 크기와 회전에 강한 정보를 만듬

 입력 :  입력 이미지, 윗단계에서 얻은 가장 반응성있는 각도 정보

처리 :

descriptor2.png 

 입력된 방향정보를 기반으로 이미지정보의 gradients 값을 계산한다.

gradients 값을 기반으로 64bin 또는 128 bin  디스크립트 정보를 생성한다.

출력 :  디스크립터 정보 생성

 

3 정합 (matching)

새로운 이미지와 기존에 인식된 이미지정보의 디스크립터를 분석하여 같은 정보인지를 판별하는 작업

FLANN(Fast Library for Approximate Nearest Neighbors)

속도를 개선하기위해 정확도에 따라 근접하였다고 판단되면 해당 인덱스 값을 리턴한다.(내부적인 알고리즘 방식은 아직 분석안했음)

참고자료:

 http://people.cs.ubc.ca/~mariusm/

 http://people.cs.ubc.ca/~mariusm/index.php/FLANN/FLANN

입력 : 인식된 기술자 와 새로입력된 기술자 정보

처리 : 

 

cv::flann::Index flann_index(m_image, cv::flann::KDTreeIndexParams(4));  // using 4 randomized kdtrees

새로 들어온 이미지에대한 디스크립 정보를 kdtree 구조를 기반으로 인덱스를 만든다.

 

flann_index.knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const SearchParams& params);

 // queries 비교할 원본이지의 디스크립터 정보

//  indices  queries 요청한 정보와 가장 근사한 인덱스 정보를 뽑아준다.

//  dists       뽑아준 인덱스 정보(거리값)을 리턴해준다.

//  knn       가장 근사한 후보인덱스 갯수 요청

 

인식되여있는 기술자정보를 queries 값으로 주면 해당하는  가장 비슷하다고 판단된 새로운기술자정보의 인덱스를 knn  갯수만큼 

평가된 dits 정보와 같이 준다

여기서 knn 이 2 값을 사용하여 가장 가깝다고 생각하는 인덱스 2개를 뽑는다.

dists_ptr[2*i]<0.6*dists_ptr[2*i+1]

이두개의 인덱스 평가값이 거의 비슷한 수치가 나오면 같은 기술자정보로 인식한다.

이것이 의미하는것은 하나의 입력이미지에 octave 마다  기술자 정보가 있기 때문에 octave 갯수만큼 기술자가 검색되여지는 특징을 이용한 것이다.

 

출력 : 같은 기술자 정보라고 인식되여진 페어 정보

 

 cvFindHomography 이용하여 객체의 정확한 범위?를 측정

 

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

Comment +6

  • perpet 2011.05.14 00:17

    예전에 surf 를 분석했을때 정리하던 자료
    몇년전부터느끼지만 비젼처리 하는쪽 소스를 보면서 수학적지식뿐아니라
    문제를 푸는 사고가 넓어지는것 같다.

  • 좋은 자료 설명, 감사합니다.

  • ugg 2013.07.14 18:24

    창밖을 봐 바람에 나뭇가지가 살며시 흔들리면 네가 사랑하는 사람이 널 사랑하고 있는거야.

  • 창밖을 봐 바람에 나뭇가지가 살며시 흔들리면 네가 사랑하는 사람이 널 사랑하고 있는거야.

  • 좋으면 좋고 싫으면 싫은 거지, 뭐가 이렇게 어렵고 복잡하냐구

  • ama3208 2018.03.16 11:51

    opencv 에 있는 find_obj 소스코드를 기반으로 만들어졌다는 말씀은 opencv를 이용해서 짠 알고리즘이라는건가요 ??

몇일전 다른프로젝트 서버 파트에서 서로다른 디비끼리 트랜잭션을 걸면 부하가 심하다고 하여 게임서버가 이것을 직접 구현하기를 원한다는 요청이 들어왔다.
나도 최근까지 이 이슈를 직접 접하지 않았기 때문에 고민하지 않다가 언젠가는 나도 이문제를 해결해야할 솔루션을 찾아야해서 고민을 해봤다.

예를 들어 문제를 풀어보겠다.
유저끼리 아이템거래를 하려고 하고 a 유저가 b 유저에게 아이템을 주라는 명령어를 내렸다고 치자
이때 a 디비 테이블에  item 이    b 디비 테이블에 이동이 되야한다고 하고
 a디비와 b디비 는 서로 다른 회사라 디비안에서 스토어드 프로시저로 트랜잭션을 걸어 이동을 못시키고 프로그램으로
아이템을 옮겨야한다고 하자 억지스러워보이지만 하여간 중요한간 트랜잭션을 게임서버가 해결해줘야하는 이슈가 생긴다는 과정을 하는것이다.
이동중 서버가 다운이 되거나 오류가 있으면 롤백이 되거나 재부팅시 완료가 제대로 이뤄져야한다고 하자.

내가 생각한 방법은
1. a디비테이블에 아이템을 같은 디비에 sendTemp 테이블을 만들어 그곳에 이동시킨다.
2. b디비테이블에 receiveTemp테이블을 만들어서 아이템이 어느테이블에 들어갈지에대한 정보를 넣는다.
3. sendTemp 테이블에 이동할 그아이템을 지운다
4. b디비테이블에 receiveTemp 테이블을 해당유저테이블에 이동시킨다.

이과정을 거치면 중간에 다운이 되여도 다시 복구나 재실행이 가능하다고 본다.
게임서버가 다운이 되고 재실행되면 밑에 가,나 작업을 수행한다.

가.  a디비테이블에  sendTemp 에 이동할 아이템이 있는지 보고 있으면 위에 2번과정을 진행한다. receiveTemp에 이미 이동할 아이템정보가 있다해도 덮어버린후
      진행한다. (이경우는 위에서 1,2번이 작동한후 서버가 다운됬을때 끝나지 않은 작업을 마무리해줌)
나. b디비테이블에 receiveTemp 테이블에 이동해올 아이템정보가 있는지 본다. 있으면 위 4번과정을 진행한다. ( 이경우는 서버가 위에서 3번 과정을 거친후 다운되 였을때 작업을 마무리해줌)


 

Comment +2

LSTM

스터디2011. 3. 21. 17:20

 

 

Untitled.png 

 

lstm2.jpg lstm3.jpg lstm4.jpg lstm5.jpg lstm6.jpg lstm7.jpg lstm8.jpg lstm9.jpg lstm10.jpg  

 

 

 

 

http://www.felixgers.de/

 http://en.wikipedia.org/wiki/Recurrent_neural_network

http://www.bioinf.jku.at/software/  자바와 c 소스 있슴

 http://www.felixgers.de/papers/phd.pdf

http://www.idsia.ch/~juergen/lstm/sld001.htm

 

lstm2003igel.pdf 

 

하나의 메모리 블럭에

cell,input gate output gate,forget gate 존재

 

 기본적인 원리구조

 

이 글은 스프링노트에서 작성되었습니다.

Comment +4

 자신들이 만든 게임의 캐릭터 액션정보나 AI 스테이트 정보를 비주얼툴로 보거나 보여주고 싶을때가 있다.

간단한게 외부라이브러리를 이용해 하루만에 뷰어를 만들수있는 툴을 만들어보자.

 

작업프로세스는 이렇다.

게임 액션과 액션사이에 링크정보가 있다 이것은 특정 이벤트가 발생해야만 다른액션으로 이동을 하는 구조를 가질수있다.

가령 stand 액션에서 key_left 가 눌러지면 left_uun , key_right ,눌리면 right_run 이란 액션으로 넘어간다고 하고 이것을 텍스트 형식으로 저장을 하면

state : stand

link : key_left, left_run

link : key_right , right_run

state : left_run

state : right_run

 

이런식으로 기획자들이 자신들이 편한 방식으로 텍스트, 또는 xml 로 저장을 할것이다.

프로그래머가 자주 이 링크정보를 보고싶을때가 있는데 이정보가 일반적으로 한캐릭에 수십가지의 액션정보가 있어 텍스트로 보기로는 상당히 힘들다

 

 이런텍스트를 uml 툴같은 다이어그램으로 보고 싶을때가있는데 여기서 가장 손쉽고 빠르게 만드는 방법을 설명한다.

 

작업방식은 공개된 다이어그램 뷰어를 구해서 그포맷에 맞게 자신들의 콘텐츠정보를 컨버트 해주면된다.

여기서는 http://www.graphviz.org/ 를 사용했다. 우리가 해줄것은 이 공개소프트웨어가 인식가능한 포맷으로 나의 컨텐츠 정보를 읽어와 변경해주면된다.

 graphviz    에서 dot 포맷이 있는데 이것으로 직접 내가 포맷을 만들어줘도 되지만 이 컨버팅 작업또한 공개소스를 이용하면 간단하게 해결할수있다.

http://quickgraph.codeplex.com/ 에가면 쉽고 간단하게 dot 포맷으로 변경가능하다.

 

전체 작업방식은 내콘텐츠 정보를 읽어 QuickGraph  를 이용해 dot 포맷파일을 생성하고  graphviz 로 이파일을 가지고 원하는 다이어그램 이미지를 만들면된다.

 

 QuickGraph 로 dot 를 생성하면

 digraph G {
0 [label="stand"];
1 [label="left_run"];
2 [label="right_run"];
0 -> 1 [ label="key_left"];
0 -> 2 [ label="key_right"];
}

 

이 만들어지고

 

  graphviz  를 돌리면

 

command>  dot a.dot -Tjpg -o a.jpg

 

 

Throwing_Spirit_Grudge.gif 

 

 

 파일이 나온다.

 

 

 

 

 

 

 

 

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

Comment +1

  • ghd 2013.07.17 10:06

    눈을 감아봐 입가에 미소가 떠오르면 네가 사랑하는 그 사람이 널 사랑하고 있는거야.

사용자 삽입 이미지

Comment +2

소스요청하시는분들이 몇분계서서 올려요

설명은 http://blog.daum.net/hazzling/16781469
참고하시면됩니다.
HMM

Comment +0

1년동안 다른거 공부하랴 c# 게임서버에 신경을 못쓰고 있네요.

간단하게 제가 제시하는 코딩방식은 이렇습니다.

 

예를 들어 설명하자면 유저가 로그인하여 아이디와 패스워드를 검증하는 코딩을 짠다고 봅시다.

보통 디비쿼리시 디비에 쿼리를 날리는순간 블럭이 되여 이것을 비동기 처리합니다.

그래서 코드가 보통이렇게 되죠.

 

void login_packet(string id, string pass)

{

int x;

db.query_login(id,pass,query_resultLogin) ; // 쿼리 결과 핸들 등록

return;

}

 

void query_resultLogin(int ret)

{

   if( ret == 0)   // 결과에 따라 처리

 

   client.send_login_result(ret) ;

 

}

 

이걸 c# 에서 yield 를 이용한 코딩을 하면 간단하게

 

void login_packet(string id, string pass)

{

int x;

yield db.query_login(id,pass) ;

 

  if( ret == 0)   // 결과에 따라 처리

 

   client.send_login_result(ret) ;

}

 

이렇게 표현될수있다는겁니다.

이런구조의 장점을 들어보자면

  1.  함수하나의 스코프안에서 원하는 구현부위를 표현하여 직관적입니다.
  2. 원시적인 비동기콜방식으로 할경우 쿼리 전 변수가 쿼리결가후에도 필요하면 해당변수를 외부에 저장할 글로벌 변수로 만들어야합니다. 위에 x 라는 변수가 쿼리 결과에서도 참조가 필요한 케이스가 발생할경우..( yield 를 하면 필요가 없겠죠)
  3.  명시적인 리모트 함수선언을 할수있습니다. 지금까지는 일반적인 패킷함수를 표현하면 void login(id,pass)  를 표현하면 알아서 loing 패킷을 만들어주고 send 함수를 만들어주는 수준이지만 yield  구조를 갖으면 리턴받아야하는 패킷도 명시적으로 표현할수있습니다.  가령 int query_login(id,pass) 라고 패킷을 선언하면 컨텐츠코딩단에서 해당하는 query_login 결과값이 올때까지 다른핸들링이 작동을 안하도록 할수있습니다. 또한 요청을 수행하는 디비단이나 다른서버가 다른형식의 패킷을 보내면 시퀀스를 어겼다고 네트웍시스템이 감지할수있습니다.

     

구체적인 구조를다시 만들면

 

server 인터페이스 선언에

int login_packet(string id,string pass) ;  를 선언하고

 

int login_packet(string id, string pass)

{

int x;

yield db.query_login(id,pass) ; <= db 에 쿼리를 날리고 올때까지 알아서 기다려줌(그동안 다른 클라이언트핸들링은 처리됨)

 

  if( ret == 0)   // 결과에 따라 처리

 

yield return ret;  <= loing_packet 를 콜한 콜러에게 send 해줌 , 또한 함수 선언에 리턴값으로 int 를 준다고 했으므로 리턴이 없거나 다른형을날리면 네트웍 시스템이 인지하여 경고처리가 가능

}

 로 표현이 됩니다.  마치 일반 어플리케이션 코딩하듯이 하면된다는거죠

 

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

Comment +1

  • ghd 2013.07.13 13:18

    귀를 기울여봐 가슴이 뛰는 소리가 들리면 네가 사랑하는 그 사람 널 사랑하고 있는거야.

on intelligence 란 책을 읽었습니다.

http://www.yes24.com/24/goods/3794199

번역본이 나와 편하게 읽을수있었다.
인간의 인식에대한 하나의 이론을 설명하는데
매우 흥미가 있었다.
개인적으로 인공지능에 관심이 많아 책을보면서 저자가 설명하는 구체적인 인식방식에 대해 프로그래밍해보고
싶어 구글링을 통해 관련 코드를 찾아봤다.


http://en.wikipedia.org/wiki/On_Intelligence

마지막에 http://sourceforge.net/projects/neocortex/
링크가 걸려 분석을 해봤다.

대충 분석을 해봤지만 특정 문제해결에 한가지 방법이 될분 딱히 새로운 솔루션이라는 느낌이 오지 않았다.


다음은 소스 빌드 방식이다. 소스는 vs2010 버전에서 빌드가 되도록 수정해서 https://captig.googlecode.com/svn/trunk/Neocortex 에 올렸다 다음은 빌드에 필요한 몇가지 설명을 한다. 1.원본소스는 qt-toolkit 을 사용한다 gui 를 표현하기 위해 이 툴킷을 사용했다. 그러므로 http://qt.nokia.com/downloads 사이트에 들어가 윈도우용 버전을 다운받는다..
빌드 구성당시 내가 사용한 버전은 qt-win-opensource-4.6.3-vs2008.exe 이다..
2. 환경변수에 "QTDIR" = "C:\Qt\4.6.3\" 을 넣는다. 디폴트로 깔경우의 경로다..
2.https://captig.googlecode.com/svn/trunk/Neocortex 에 들어가서 소스를 다운받는다..
3.captig\Neocortex\Neocortex Minimal Source Code\Neo1.4.2c Source\MS Studio 20051.4.2c\Neo.sln 을 열어 neo 프로젝트를 실행하면 된다..
4.실행을 하면 관련 dll 이 없다고 한다. c:\qt\4.6.3\bin 에서 QtCore4.dll,QtCored4.dll,QtGui4.dll,QtGuid4.dll 를 실행폴더에 복사한다 디폴트이면 debug 폴더에 넣으면된다..
관련 분석 문서는 https://docs.google.com/document/edit?id=1sRWtPy_cfZ-WWn6ucq5Tr_THwQS2u5AOuT8UPnUPLMA&hl=en 참고

Comment +5