차근차근/OpenCV

3 일에 만드는 고속 특정 물체 인식 시스템 (5) 물체 모델 데이터베이스 만들기

예쁜꽃이피었으면 2014. 7. 30. 10:13

http://aidiary.hatenablog.com/entry/20091114/1258172261

3 일에 만드는 고속 특정 물체 인식 시스템 (4) 특징점의 매칭 (2009/11/2)의 연속이다.

이번에는 고속 특정 물체 인식 시스템의 물체 모델 데이터베이스를 만들려고합니다. 쿼리로 준 이미지가 무언가는이 물체 모델 데이터베이스를 검색하여 인식 할 수 있습니다. 특정 물체 인식은 쿼리로 준 이미지가 물체 모델 데이터베이스에 미리 등록되어 있지 않으면 먼저 인식 할 수 없습니다 (국소 특징 량을 이용하기 때문에 다소의 규모 변화와 회전 등에는 대응할 수 있습니다 만). 잊어 버린 분은 물체 인식 시스템의 구성 (2009-10-18)를 참조하십시오.

이미지 데이 대용량 데이터 세트 준비

직접 촬영 한 사진을 등록 할 수 있도록해도 괜찮 습니다만, 대량의 사진을 촬영하는 것은 귀찮아서 친숙한Caltech101 이미지 세트를 사용하여 물체 모델을 만듭니다.

비슷한 이미지 검색 시스템을 만들자 (2009/10/3) 이미지 데이 대용량 데이터 세트 를 준비를 추천 caltech101 폴더에 이미지 파일 만 복사 한 데이터를 제공합니다. 조금 너무 많아 각 카테고리에서 10 장씩 이미지를 빼내고 (ID가 0001에서 0010까지) caltech101_10 는 데이터를 만듭니다. caltech101_10라는 폴더를 만들고 다음 스크립트를 실행하면 990 장의 사진 데이터가 있습니다.

# coding : utf-8 
import OS
 import shutil 

IMAGE_DIR = " caltech101 " 
OUT_DIR = " caltech101_10 " for file in os.listdir (IMAGE_DIR) : 
    id = int (file [-8 : -4]) IF ID <= 10 :
         print file 
        shutil.copy ( " % s / % s "% (IMAGE_DIR, file)" % s / % s "% (OUT_DIR, file))



    

물체 모델 데이터베이스 만들기

caltech101_10는 990 장의 사진에서 특징 량을 추출하여 물체 모델 데이터베이스에 저장하고 있습니다. 각 이미지에서 추출한 키포인트의 특징 량은 물체 ID 도비도 지어 저장해야합니다 . 그래서 물체 ID와 특징 량을 저장하는 테이블이 필요합니다.

물체 ID 테이블 : 물체 ID 이미지 파일 이름 
특징 량 테이블 : 물체 ID 라플라시안 키포인트의 특징 량

SQLite 등으로 데이터베이스를 만들어도 좋겠지 만, 코드가 복잡하기 때문에 여기에서는 편의상 파일에 텍스트 형식으로 데이터를 저장하여 보았습니다. 물체 ID 파일 (object.txt) 와 특징 량 파일 (description.txt) 입니다.

물체 ID 파일은 다음과 같은 탭으로 구분 된 형식입니다. 등록 순서대로 물체 ID가 자동으로 할당됩니다.

0 accordion_image_0001.jpg 
1 ant_image_0001.jpg 
2 bonsai_image_0001.jpg 
3 butterfly_image_0001.jpg 
4 dolphin_image_0001.jpg

특징 량 파일은 다음과 같은 탭으로 구분 된 형식입니다. 모든 이미지의 특징 량은 하나의 파일에 저장합니다. 각 물체는 여러 키포인트를 가진 점에주의가 필요합니다. 그래서 데이터베이스를 사용하는 경우는 물체 ID를 기본 키로 수 없습니다.

0 1 0.03 0.05 .... # 물체 ID = 0의 첫 번째 키포인트 
0 1 0.28 0.14 .... # 물체 ID = 0의 두 번째 키 포인트 
0 -1 0.31 0.01 .... # 물체 ID = 0의 세 번째 키 포인트 
.... 
1 -1 0.24 0.31 .... # 물체 ID = 1의 첫 번째 키포인트 
1 1 0.15 0.22 .... # 물체 ID = 1 두 번째 키 포인트 
1 0.01 0.03 .... # 물체 ID = 1의 세 번째 키 포인트 
....

caltech101_10의 모든 이미지 파일에서 위의 물체 ID 파일 및 특징 량 파일을 추출 프로그램입니다. 국소 특징 량에 SURF를 사용하고 있습니다. 자세한 내용은 SURF 추출 (2009-10-30)를 참조하십시오. 디렉토리의 파일 검색 opendir ()를 사용하고 있습니다. 이것은 MinGW 의 g+ +에서 사용할 수 있지만, 혹시 Visual C + + 에서는 사용할 수 없을지도 · · · 에러가 나오면 이 근처 를 추천 바꾼다.

위의 프로그램에서 990 장의 사진에서 물체 ID 파일 및 특징 량 파일 만들기에는 우리 환경에서 5 분 정도 걸

# include <cv.h> # include <highgui.h> # include <iostream> # include <fstream> # include <sys/types.h> # include <dirent.h> using namespace Std;

const char * IMAGE_DIR = " caltech101_10 " ; const char * OBJ_FILE = "object.txt" ;

// 물체 ID 저장 파일

const char * DESC_FILE = "description.txt" ;

// 특징 량 저장 파일

const Double SURF_PARAM = 400 ;

// SURF 매개 변수

const int DIM = 128 ;

// SURF 특징 량의 차원 수

/**

* SURF 특징 량을 추출하는 *

* @ param [in] filename 이미지 파일 이름

* @ param [out] imageKeypoints 키 포인트 (출력에 대한 참조로 전달)

* @ param [out] imageDescriptors 각 키 포인트 SURF 특징 량 (출력에 대한 참조로 전달)

* @ param [out] storage Memory Storage (출력에 대한 참조로 전달) *

* @ return 성공하면 0, 실패하면 1

*/

int extractSURF ( char * filename, CvSeq * & imageKeypoints, CvSeq * & imageDescriptors, CvMemStorage * & storage) { // 그레이 스케일 이미지를로드 IplImage * img = cvLoadImage (filename, CV_LOAD_IMAGE_GRAYSCALE); if (img == NULL ) { cerr << "cannot load image file :" << filename << endl; return 1 ; } storage = cvCreateMemStorage ( 0 ); CvSURFParams params = cvSURFParams (SURF_PARAM, 1 ); cvExtractSURF (img, 0 , & imageKeypoints & imageDescriptors, storage, params); return 0 ; }

/**

* 물체 모델을 파일에 저장 *

* @ param [in] objId 개체 ID

* @ param [in] filename 이미지 파일 이름

* @ param [in] imageKeypoints 키포인트

* @ param [in] imageDescriptors 각 키포인트의 특징 량

* @ param [in] objFile 물체 ID 파일 핸들러

* @ param [in] descFile 특징 량 파일 핸들러 *

* @ return 성공하면 0, 실패하면 1

*/

 

int saveFile ( int Objid, char * filename, CvSeq * imageKeypoints, CvSeq * imageDescriptors, ofstream & objFile, ofstream & descFile) { cout << objId << "" << filename << "" << imageDescriptors-> total << endl;

// 물체 ID 파일에 등록 objFile << objId << " \ t " << filename << endl;

// 개체 ID, 라플라시안 128 개의 숫자를 탭으로 구분 된 출력

for ( int I = 0 ; i <imageDescriptors-> total; i + +) {

// 각 키포인트의 특징 량에 대해

// 개체 ID descFile << objId << " \ t " ;

// 특징점의 라플라시안 (SURF 특징 량은 벡터를 비교할 때 사용)

const CvSURFPoint * kp = ( const CvSURFPoint *) cvGetSeqElem (imageKeypoints, i); int Laplacian = kp-> laplacian; descFile << laplacian << " \ t " ;

// 128 차원 벡터

const float * descriptor = ( const float *) cvGetSeqElem (imageDescriptors, i) ; for ( int D = 0 ; d <DIM; d +) { descFile << descriptor [d] << " \ t " ; } descFile << endl; } return 0 ; } int Main ( int argc, char ** argv ) { int ret;

// 물체 ID 파일을 열 ofstream objFile (OBJ_FILE); if (objFile.fail ()) { cerr << "cannot open file :" << OBJ_FILE << endl; return 1 ; }

// 특징 양 파일을 열 ofstream descFile (DESC_FILE); if (descFile.fail ()) { cerr << "cannot open file :" << DESC_FILE << endl; return 1 ; }

// IMAGE_DIR 이미지 파일 이름을 주사

DIR * dp = opendir (IMAGE_DIR); if (dp == NULL ) { cerr << "cannot open directory :" << IMAGE_DIR << endl; return 1 ; } int Objid = 0 ;

// 개체 ID

struct dirent * entry; while ( 1 ) { entry = readdir (dp); if (entry == NULL ) { break ; }

//와 .. 무시

if (strncmp (entry-> d_name, "" , 1 ) == 0 | | strncmp (entry-> d_name, ".." , 2 ) == 0 ) { continue ; } char * filename = entry-> d_name;

// SURF 추출

char buf [ 1024 ]; snprintf (buf, sizeof buf, " % s / % s " , IMAGE_DIR, filename); CvSeq * imageKeypoints = 0 ; CvSeq * imageDescriptors = 0 ; CvMemStorage * storage = 0 ; ret = extractSURF (buf, imageKeypoints, imageDescriptors, storage); if (ret! = 0 ) { cerr << "cannot extract surf description" << endl; return 1 ; } // 파일에 출력 ret = saveFile (objId, filename, imageKeypoints, imageDescriptors, objFile, descFile); if (ret! = 0 ) { cerr << "cannot save surf description" << endl; return 1 ; } // 뒤처리 cvClearSeq (imageKeypoints); cvClearSeq (imageDescriptors); cvReleaseMemStorage (& storage); objId + +; } objFile.close (); descFile.close (); closedir (dp); return 0 ; }

렸습니다. description.txt 상당히 커다 랗게하고 420MB 있습니다. 얼떨결에 메모장 등으로 열리지 않도록하지 않으면 (웃음) 사이즈가 큰 것은 부동 소수점 숫자 를 텍스트로 저장하고 있으니하지만 바이너리로 저장하면 더 작은 되는군요. 큰 이미지를 대상으로하는 경우는 궁리가 필요합니다. 990 장의 사진 총 키 포인트는 321932 개 있었습니다. 1 장당 평균 325 개 라는 계산입니다. Caltech101 이미지는 크기가 작기 때문에 적습니다.

물체 모델 데이터베이스를 특정 물체 인식에 어떻게 사용하나요?

이번 만든 object.txt과 description.txt 여기에서는 물체 모델 데이터베이스라고합니다. 이것을 특정 물체 인식 시스템에 어떻게 사용 할까하지만 아래의 그림과 같은 느낌입니다.

f : id : aidiary : 20091114125457p : plain

이번에는 990 장의 이미지를 저장 한 그림 오른쪽의 물체 모델 데이터베이스를 만들었습니다. 특정 물체 인식은 쿼리 이미지 (왼쪽 돌고래)를주고 이것이 물체 모델 데이터베이스의 어떤 이미지를 알아 맞추는하는 처리입니다. 위 예제의 경우 개체 ID = 4 인식 할 수 있으면 큰 정답입니다.

이 인식 방법은 이미 소개하는 특징점의 매칭 (2009/11/2)과 거의 동일한 방법입니다. 특징점의 매칭에서는 이미지 대 이미지 였지만, 특정 물체 인식은 이미지 대 물체 모델 데이터베이스 비교한다는 차이가있을뿐입니다.

물체 모델 데이터베이스에 대량의 키 포인트가 포함되어 있기 때문에 특징점의 매칭 빠른 최단 입점 계산 방법이 필요합니다. 특징점의 매칭에서는 이미지 1 키포인트 수가 800, 화상 2의 키포인트 수가 800이라고하면 전부 800x800 = 640,000 회 정도의 거리 계산에서 이미지 1의 각 키포인트 최근 방점을 찾을 수 있습니다. 여기서 이미지 2 물체 모델 데이터베이스로 대체하면 전체 800x321932 = 257545600 번 거리 계산됩니다. 비효율적 인 선형 탐색에서는 시간이 너무 걸리는 것입니다. 그렇다고는하지만 얼마나 걸리는지 확인하기 다음은 선형 탐색을 이용한 특정 물체 인식을 가고 있습니다.

3 일에 만드는 고속 특정 물체 인식 시스템 (6) 선형 탐색을 이용한 특정 물체 인식 에 따릅니다.

 

 

 

 

*파란글씨만 주석인게 맞겠지..?ㅜㅠ

 

* 저 맨위에 소스

# coding : utf-8
import
OS
import shutil


IMAGE_DIR = "
caltech101 "
OUT_DIR = "
caltech101_10 " for file in os.listdir (IMAGE_DIR) :
    id = int (file [-8 : -4])
IF ID <= 10 :
        

        shutil.copy ( "
% s / % s "% (IMAGE_DIR, file)" % s / % s "% (OUT_DIR, file)

파이선? 뭐 그건가보다.. 어떻게 하나..

*이미지 경로 아무리해도 안됨..노답​

반응형