차근차근/OpenCV

Visual Words를 이용한 유사 이미지 검색

예쁜꽃이피었으면 2014. 8. 11. 09:04

http://aidiary.hatenablog.com/entry/20100227/1267277731



Visual Words를 이용한 유사 이미지 검색

에 계속 OpenCV 프로젝트 셋째 탄입니다. 이번에는 위 두 가지를 근거로 컬러 히스토그램이 아닌 국소 특징 량 (SIFT와 SURF)을 이용한 유사 이미지 검색을 시도합니다. 국소 특징 량은 그레이 스케일 이미지에서 추출하는 컬러 히스토그램과 달리 색상은 보이지 않습니다. 이미지의 모양 (텍스처)에서 유사성을 판정합니다.

실험 환경은 Windows 7 MinGW C + + 컴파일러, OpenCV2.0, Python 2.5입니다. Eclipse에서 MinGW를 사용하는 방법은 Eclipse에서 OpenCV (2009-10-16)를 참조하십시오. Visual C + +에는없는 디렉토리 검색 기능을 일부 사용하고 있기 때문에 Visual C + +을 사용하는 경우 약간의 수정이 필요합니다.

Bag-of-Visual Words

먼저 이미지 Bag-of-Visual Words 표현에 대해 간단하게 정리해 둡니다. Bag-of-Visual Words를 이용하면 이미지를 하나의 특징 벡터로 표현할 수 있습니다 . Bag-of-Visual Words 별명으로 Bag-of-Features 이나 Bag-of-Keypoints 라는 호칭도 있습니다. Google에서 알아 보았는데

  • Bag-of-Features (1,660,000 건)
  • Bag-of-Visual Words (113,000 건)
  • Bag-of-Keypoints (58,400 건)

이 때문에 Bag-of-Features라는 호칭이 가장 많은가요? 나 자신 Bag-of-Visual Words라는 호칭이 가장 좋아합니다. 이 기술은 원래 자연 언어 처리에서 자주 사용되는 Bag-of-Words 비유로 이미지에 응용 한 방법이기 때문입니다.

Bag-of-Words 문서를 벡터로 표현하는 방법으로 자연 언어 처리 분야에서는 당연한 듯이 사용합니다. 쉽게 말하면, 문서를 일련의 단어로 취급합니다. 실제로, 대상 문서 집합에서 TF-IDF에서 특징 어를 추출하여 문서 벡터의 차원으로, TF-IDF 가중치를 문서 벡터의 값으로하는 방법이 자주 사용됩니다. 나중에 나이브 베이 즈를 이용한 문서 분류를 소개 할 예정이지만 그 때 사용해보십시오.

f : id : aidiary : 20100227224223p : plain

는 이미지의 단어는 무엇인가? 라는 이야기가 있지만, 지금까지 사용해 온 국소 특징 량 입니다. Bag-of-Visual Words 텍스트 단어 ⇔ 이미지의 국소 특징 량과 대응시키는 방법입니다. 위 그림과 같이 먼저 Visual Words를 구축하는 이미지 집합을 제공합니다. 그리고 각각의 사진에서 국소 특징 량을 추출합니다. 그림은 이해를 돕기 위해 국소 특징 량을 작은 이미지로 표현하고 있지만, 실제로는 128 차원의 SIFT와 SURF 특징 벡터입니다. 그리고 모든 특징 벡터를 K 개의 클러스터로 클러스터링합니다. 클러스터링은 K-means 하는 수법이 자주 사용됩니다. 그리고 K 개의 클러스터의 각 센트 로이드 (핵심 벡터)를 각각 Visual Word합니다 . 세인트 로이드 것도 특징 벡터와 마찬가지로 128 차원 벡터로 표현됩니다. 즉, K 개의 클러스터로 클러스터링하면 K 개의 Visual Words 수 있습니다.이 예에서는 K = 7이므로 7 개의 Visual Word를 얻을 수 있습니다.

f : id : aidiary : 20100227224224p : plain

다음은 위 그림처럼 이미지 데이터베이스의 전체 이미지 (Visual Words를 구한 것도 포함)을 Visual Words를 차원과 히스토그램으로 변환합니다. 이것은 이미지의 각 국소 특징 량에 대해 가장 가까운 Visual Word를 검색하고 Visual Word에 투표하는 것으로합니다. 결국이 히스토그램이 이미지의 특징 벡터입니다 . 이 예에서는 7 차원의 특징 벡터입니다. 실제로, Visual Word는 수백에서 수천 개의 선택하기 때문에 수백에서 수천 차원 벡터입니다.Visual Words를 사용하면 한 장의 사진을 수백 차원 벡터 하나로 나타낼 수 있습니다. 이미지를 하나의 벡터로 나타낼 때, Support Vector Machine 등의 분류기를 사용하기 쉽게되어 기쁘 네요. 이 히스토그램의 모양은 비슷한 이미지만큼 닮은 것입니다. 예를 들어, 위의 그림이라고 아코디언끼리의 히스토그램은 비슷하네요. 히스토그램끼리의 유사성은 비슷한 이미지 검색 시스템을 만들자 (2009/10/3)에서 사용한 히스토그램 인터 섹션 등을 사용할 수 있습니다.

설명이 길어졌습니다 만, 실제로 시도합니다. 좀 더 자세한 설명은 참고 자료를 참조하십시오.

이미지 데이터 세트를 준비

실험에 사용되는 이미지 데이터 세트를 제공합니다. 이번에는 유사 이미지 검색 시스템을 만들자 (2009/10/3)에서 사용한 Caltech101 를 또한 사용합니다. 다운로드 한 데이터의 압축을 풀면 101_ObjectCategories라는 폴더에 101 개의 카테고리 폴더 (102 개 있지만 BACKGROUND_Google이 쓸데?)가 그 안에 이미지가 많이 있습니다. 예를 들어, airplanes 폴더 (카테고리)는 비행기의 사진이 많이 들어 있습니다.

먼저 BACKGROUND_Google, Faces, Faces_easy 조금 특별한 이미지이므로 폴더마다 삭제합니다. 다음 폴더마다 이미지 파일이 분산되고 있기 때문에 일괄 처리 할 수 있도록 caltech101라는 폴더에 이미지 파일 만 정리합니다. 또한 각 카테고리 폴더에있는 이미지 파일 이름은 image_0001.jpg 라든지 붙어 있습니다. airplanes (비행기)에 dolphin (돌고래)에도 같은 파일 이름이 붙어 있으므로 구분 못하고 귀찮습니다. 그래서 아래와 같이 카테고리 이름 - 숫자 .jpg 라는 파일명으로 변환합니다.

    airplanes / image_0001.jpg -> caltech101 / airplanes-0001.jpg
    dolphin / image_0001.jpg -> caltech101 / dolphin-0001.jpg

일괄 변환 python 스크립트입니다.

#coding : utf-8 
import 코덱
 import OS
 import os.path
 import shutil

TARGET = "101_ObjectCategories" 
OUTDIR = "caltech101"

# 출력 디렉토리가 없으면 만들 
IF  not os.path.exists (OUTDIR) :
    os.mkdir (O​​UTDIR)

for Category in os.listdir (TARGET) :
     for  file  in os.listdir ( "% s / % s" % (TARGET, category)) :
         # 101_ObjectCategories / airplanes / image_0001.jpg 
        image_file = "% s / % s / % s " % (TARGET, category, file )
         # caltech101 / airplanes-0001.jpg 
        rename_file = "% s / % s- % s" % (OUTDIR, category, file .replace ( "image_" , "" ))
         # 파일 복사 
        print  "% s -> % s" % (image_file, rename_file)
        shutil.copyfile (image_file, rename_file)

이제 9145 장의 이미지 파일 만 caltech101 폴더에 리네이무 복사됩니다. 이제 히스토그램 추출 처리 등 쉬워집니다. 다음 이번 실험은 매우 계산량이 크기 때문에 accordion, bonsai, cougar_face, dalmatian, dollar_bill, euphonium, hedgehog, grand_piano, Motorbikes, yin_yang 10 카테고리 1 번째에서 50 번째 이미지 만 추출하여 caltech 10 라는 500 장의 사진으로 구성된 집합 데이터 집합을 만듭니다.

#coding : utf-8 
import os.path
 import shutil

IMAGE_DIR = "caltech101" 
SUBSET_DIR = "caltech10"

# 대상 카테고리 
TARGET_CATEGORY = "accordion" , "bonsai" , "cougar_face" , "dalmatian" , "dollar_bill" ,
                    "euphonium" , "hedgehog" , "grand_piano" , "Motorbikes" , "yin_yang" ,]

# 파일 번호가 50 이하의 이미지 만 대상 
TOP = 50

# 출력 디렉토리가 없으면 만들 
IF  not os.path.exists (SUBSET_DIR) :
    os.mkdir (SUBSET_DIR)

for  file  in os.listdir (IMAGE_DIR) :
     try :
        cat = file .split ( "-" ) [ 0 ]             # 파일의 카테고리 이름을 가져 
        num = int ( file .split ( "-" ) [ 1 ] [ 0 : 4 )   # 파일 번호를 가져 
    except :
         continue
    
    # 대상 범주에서 숫자가 TOP 이하인 파일 만 복사 
    IF cat in TARGET_CATEGORY and num <= TOP :   # 대상 범주의 경우 
        source_image = "% s / % s" % (IMAGE_DIR, file )
        dest_image = "% s / % s" % (SUBSET_DIR, file )
        shutil.copyfile (source_image, dest_image)

전체의 흐름

이미지 데이터 세트가 준비했기 때문에, C + +와 OpenCV를 사용하여 Visual Words를 이용한 유사 이미지 검색을 구현​​하고 있습니다. 전체적인 흐름을 정리하면

  1. 전체 이미지에서 SURF 국소 특징 량을 추출
  2. 전체 이미지 SURF 벡터를 K-means에서 K 개의 클러스터로 클러스터링하여 각 클러스터 센트 로이드 (Visual Word)를 요구
  3. 전체 이미지를 히스토그램으로 변환

입니다. 히스토그램은 나중에 사용할 수 있도록 파일에 출력합니다.

visual_words.cpp

먼저 메인 함수에서.

#include <cv.h> 
#include <highgui.h> 
#include <iostream> 
#include <fstream> 
#include <dirent.h>

using  namespace Std;

const  char * IMAGE_DIR = "caltech10" ;
 const  int DIM = 128 ;
 const  int SURF_PARAM = 400 ;
 const  int MAX_CLUSTER = 500 ;   // 클러스터 수 = Visual Words의 차원

int Main () {
     int ret;

    // IMAGE_DIR 각 이미지에서 국소 특징 량을 추출 
    cout << "Load Descriptors ..." << endl;
    CvMat samples;
    vector < float > data;
    ret = loadDescriptors (samples, data);

    // 국소 특징 량을 클러스터링하여 각 클러스터 센트 로이드를 계산 
    cout << "Clustering ..." << endl;
    CvMat * labels = cvCreateMat (samples.rows, 1 , CV_32S);         // 각 샘플 포인트가 할당 된 클러스터 레이블 
    CvMat * centroids = cvCreateMat (MAX_CLUSTER, DIM, CV_32FC1);   // 각 클러스터의 중심 (센트 로이드) DIM 차원 벡터 
    cvKMeans2 (& samples, MAX_CLUSTER, labels, cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10 , 1.0 ), 1 , 0 , 0 , centroids, 0 );
    cvReleaseMat (& labels);   // 레이블은 사용하지

    // 각 이미지를 Visual Words 히스토그램으로 변환하는 
    // 각 클러스터의 중심 벡터, centroids가 각각 Visual Words된다 
    cout << "Calc Histograms ..." << endl;
    calcHistograms (centroids);
    cvReleaseMat (& centroids);

    return  0 ;
}

(1) 국소 특징 량 추출 및 (3) 히스토그램 추출이 길기 때문에 각각 loadDescriptors () calcHistograms () 함수에 요약되어 있습니다. 클러스터링은 함수를 만들 정도로 오래 않기 때문에 그대로입니다. K-means 클러스터링은 cvKMeans2 ()라는 OpenCV 함수에서 쉽게 할 수 있습니다. samples은 전체 이미지의 국소 특징 량 행렬 (특징 벡터 몇 x128 차원)입니다. MAX_CLUSTER는 클러스터 단위로 적당히 500으로하고 있습니다. 즉, Visual Words 500 개 있습니다. labels은 이번에는 사용하지 않지만 각 특징 벡터가 어떤 클러스터에 할당했는지를 나타냅니다.centroid는 각 클러스터 센트 로이드 벡터가 포함 된 500 클러스터 x128 차원의 행렬입니다.

국소 특징 량을 추출

caltech10 500 매의 이미지에서 국소 특징 량 SURF를 추출합니다. SURF 추출 방법은 SURF 추출 (2009-10-30)를 참조하십시오.

/ ** 
* 이미지 파일에서 SURF 특징 량을 추출하는 
* @param [in] filename 이미지 파일 이름 
* @param [out] imageKeypoints 키 포인트 
* @param [out] imageDescriptors 각 키 포인트 SURF 특징 량 
* @param [ out] storage 메모리 영역 
* @return 성공이면 0, 실패하는 1 
* / 
int extractSURF ( const  char * filename, CvSeq ** keypoints, CvSeq ** descriptors, CvMemStorage ** storage) {
     // 그레이 스케일로 이미지를로드하는
    IplImage * img = cvLoadImage (filename, CV_LOAD_IMAGE_GRAYSCALE);
    if (img == NULL ) {
        cerr << "can not load image :" << filename << endl;
         return  1 ;
    }

    * storage = cvCreateMemStorage ( 0 );
    CvSURFParams params = cvSURFParams (SURF_PARAM, 1 );
    cvExtractSURF (img, 0 , keypoints, descriptors * storage, params);

    return  0 ;
}

/ ** 
* IMAGE_DIR에있는 모든 사진에서 국소 특징 량을 추출 행렬에 저장 
* @param [out] samples 국소 특징 량의 행렬 
* @param [out] data samples 데이터 영역 
* @return 성공이면 0, 실패하는 1 
* / 
int loadDescriptors (CvMat & samples, vector < float > & data) {
     // IMAGE_DIR을 열 
    DIR * dp;
     if ((dp = opendir (IMAGE_DIR)) == NULL ) {
        cerr << "can not open directory :" << IMAGE_DIR << endl;
         return  1 ;
    }

    // IMAGE_DIR 이미지 파일 이름을 주사 
    struct dirent * entry;
     while ((entry = readdir (dp))! = NULL ) {
         char * filename = entry-> d_name;
         if (strcmp (filename, "" ) == 0 || strcmp (filename, ".." ) == 0 ) {
             continue ;
        }

        // 경로명으로 변환 
        // XXX .jpg -> IMAGE_DIR / XXX .jpg 
        char filepath [ 256 ];
        snprintf (filepath, sizeof filepath, " % s / % s " , IMAGE_DIR, filename);

        // SURF를 추출 
        CvSeq * keypoints = NULL ;
        CvSeq * descriptors = NULL ;
        CvMemStorage * storage = NULL ;
         int ret = extractSURF (filepath & keypoints & descriptors & storage);
         if (ret! = 0 ) {
            cerr << "error in extractSURF" << endl;
             return  1 ;
        }

        // 파일 이름과 국소 특징점의 수를 표시 
        cout << filepath << " \ t " << descriptors-> total << endl;

        // 특징 량을 구조화하지 않고 data에 추가 
        for ( int I = 0 ; i <descriptors-> total; i + +) {
             float * d = ( float *) cvGetSeqElem (descriptors, i);   // 128 차원 벡터 
            for ( int J = 0 ; j <DIM; j + +) {
                data.push_back (d [j]);
            }
        }

        cvClearSeq (keypoints);
        cvClearSeq (descriptors);
        cvReleaseMemStorage (& storage);
    }

    // data를 CvMat 형식으로 변환 
    // CvMat는 data를 참조하는 data가 해제되지 않기 때문에주의 
    int rows = data.size () / DIM;   // CvMat의 행수 (= DIM 차원 특징 벡터의 갯수) 
    cvInitMatHeader (& samples, rows, DIM, CV_32FC1 & data [ 0 ]);

    return  0 ;
}

loadDescriptors ()에서 디렉토리 검색 기능을 사용하고 있습니다 만, 이것은 Visual C + +는 없다고 생각합니다. 비슷한 함수가있을 것이므로 수정하십시오.

이미지를 히스토그램으로 변환

다음 500 장의 사진을 Visual Words를 차원으로 한 히스토그램으로 변환하는 함수입니다. 히스토그램은 탭 구분 형식으로 histograms.txt에 출력됩니다. 이미지의 각 국소 특징 량에 가장 유사한 (최근 옆의) Visual Word를 찾을 썼습니다 만, Visual Words를 kd-tree에서 인덱싱하여 검색 속도를 올리고 있습니다. kd-tree를 이용한 속도는 가장 가까운 이웃 탐색의 고속화 (2009-12-12)를 참조하십시오.

/ ** 
* IMAEG_DIR의 전체 이미지를 히스토그램으로 변환하여 출력 
* 각 이미지의 각 국소 특징 량을 가장 가까운 Visual Words에 투표하여 히스토그램을 만드는 
* @param [in] visualWords Visual Words 
* @return 성공 그렇다면 0 실패하는 1 
* / 
int calcHistograms (CvMat * visualWords) {
     // 가장 가까운 Visual Words 속도 검색 할 수 있도록 visualWords을 kd-tree에서 인덱싱
    CvFeatureTree * ft = cvCreateKDTree (visualWords);

    // 각 이미지의 히스토그램을 출력 파일을 열
    fstream fout;
    fout.open ( "histograms.txt" , ios :: out);
     if (! fout.is_open ()) {
        cerr << "can not open file : histograms.txt" << endl;
         return  1 ;
    }

    // IMAGE_DIR 각 이미지를 히스토그램으로 변환 
    DIR * dp;
     if ((dp = opendir (IMAGE_DIR)) == NULL ) {
        cerr << "can not open directory :" << IMAGE_DIR << endl;
         return  1 ;
    }

    struct dirent * entry;
     while ((entry = readdir (dp))! = NULL ) {
         char * filename = entry-> d_name;
         if (strcmp (filename, "" ) == 0 || strcmp (filename, ". " ) == 0 ) {
             continue ;
        }

        char filepath [ 256 ];
        snprintf (filepath, sizeof filepath, " % s / % s " , IMAGE_DIR, filename);

        // 히스토그램을 초기화 
        int * histogram = new  int [visualWords-> rows];
         for ( int I = 0 ; i <visualWords-> rows; i + +) {
            histogram [i] = 0 ;
        }

        // SURF를 추출 
        CvSeq * keypoints = NULL ;
        CvSeq * descriptors = NULL ;
        CvMemStorage * storage = NULL ;
         int ret = extractSURF (filepath & keypoints & descriptors & storage);
         if (ret! = 0 ) {
            cerr << "error in extractSURF" << endl;
             return  1 ;
        }

        // kd-tree 빠른 검색 같은 특징 벡터를 CvMat 확장
        CvMat * mat = cvCreateMat (descriptors-> total, DIM, CV_32FC1);
        CvSeqReader reader;
        float * ptr = mat-> data.fl;
        cvStartReadSeq (descriptors & reader);
        for ( int I = 0 ; i <descriptors-> total; i + +) {
             float * desc = ( float *) reader.ptr;
            CV_NEXT_SEQ_ELEM (reader.seq-> elem_size, reader);
            memcpy (ptr, desc, DIM * sizeof ( float ));
            ptr + = DIM;
        }

        // 각 국소 특징점에 대해 가장 유사한 Visual Words를 찾아 투표 
        int K = 1 ;   // 1-NN 
        CvMat * indices = cvCreateMat (keypoints-> total, k, CV_32SC1);   // 가장 가까운 Visual Words 인덱스 
        CvMat * dists = cvCreateMat (keypoints-> total, k, CV_64FC1);     // 그 거리 
        cvFindFeatures (ft, mat, indices, dists, k, 250 );
         for ( int I = 0 ; i <indices-> rows; i + ) {
             int idx = CV_MAT_ELEM (* indices, int , i, 0 );
            histogram [idx + = 1 ;
        }

        // 히스토그램을 파일에 출력 
        fout << filepath << " \ t " ;
         for ( int I = 0 ; i <visualWords-> rows; i + +) {
            fout << float (histogram [i]) / float (descriptors-> total) << " \ t " ;
        }
        fout << endl;

        // 뒤처리 
        delete [] histogram;
        cvClearSeq (keypoints);
        cvClearSeq (descriptors);
        cvReleaseMemStorage (& storage);
        cvReleaseMat (& mat);
        cvReleaseMat (& indices);
        cvReleaseMat (& dists);
    }

    fout.close ();
    cvReleaseFeatureTree (ft);

    return  0 ;
}

작성된 히스토그램 파일을はとき입니다. histograms.txt

Visual Words 히스토그램을 이용한 유사 이미지 검색

는 histograms.txt을 사용하여 비슷한 이미지 검색 프로그램을 써 봅시다. 또 OpenCV는 사용하지 않기 때문에 이런 귀찮은 C + +를 사용할 필요 없네요 (웃음) Python으로갑니다.

이미지의 유사성에 Histogram Intersection을 사용합니다. Histogram Intersection은 유사 이미지 검색 시스템을 만들자 (2009/10/3)를 참조하십시오. 다음 스크립트는 쿼리로 준 이미지와 기타 모든 이미지와 Histogram Intersection을 계산하고 유사도가 높은 순서로 상위 10 위를 반환 Python 스크립트입니다. Python의 이미지 처리 라이브러리 PIL (Python Image Library)을 사용하기 때문에 별도 설치하십시오. 모든 이미지의 히스토그램은 미리 메모리에로드 해 둡니다 .

#coding : utf-8 
import 코덱
 import OS
 import sys
 from PIL import Image

IMAGE_DIR = "caltech10" 
HIST_DIR = "hist"

# 히스토그램을로드하는 
def  load_hist () :
    hist = {}
    fp = open ( "histograms.txt" , "r" )
     for line in FP :
        line = line.rstrip ()
        data = line.split ( " \ t " )
         file = data [ 0 ]
        h = float (x) for x in data [ 1 :]]
        hist [ file ] = h
    fp.close ()
    return hist

# 정규화 Histogram Intersection을 계산하는 
def  calc_hist_intersection (hist1, hist2) :
    total = 0 
    for I in  Range ( len (hist1)) :
        total + = min (hist1 [i], hist2 [i])
     return  float (total) / sum (hist1)

def  Main () :
    hist = load_hist ()

    while  True :
         # 쿼리가되는 히스토그램 파일 이름을 입력 
        query_file = raw_input ( "query?>" )
        
        # 종료 
        IF query_file == "quit" :
             break
        
        # 경로로 변환 
        query_file = IMAGE_DIR + "/" + query_file
        
        # 존재하지 않는 히스토그램 파일 이름의 경우 다시 
        IF  not hist.has_key (query_file) :
             print  "no histogram" 
            continue
        
        # 쿼리와 다른 모든 이미지 사이에서 유사성을 계산
        result = []
        query_hist = hist [query_file]
        for target_file in hist.keys () :
            target_hist = hist [target_file]
            d = calc_hist_intersection (query_hist, target_hist)
            result.append ((d, target_file))
        
        # 유사도 큰 순으로 정렬 
        result.sort (reverse = True )
        
        # 상위 10 위까지 (1 위는 쿼리 이미지) 
        # PIL을 사용하여 300x300를 1 단위로 2 행 5 열 10 개의 이미지를 나란히 그리기 
        p = 0 
        canvas = Image.new ( "RGB" ( 1500 , 600 ), ( 255 , 255 , 255 ))   # 흰 캔버스 
        for score, filename in result [ 0 : 10 :
             print  "% f \ t % s " % (score, filename)
            img = Image. open (filename)
            pos = ( 300 * (p % 5 ), 300 * (p / 5 ))
            canvas.paste (img, pos)
            p + = 1 
        canvas.resize (( 1500 / 2 , 600 / 2 ))
        canvas.show ()
        canvas.save ( "result.jpg" , "JPEG" )

IF __name__ == "__main__" :
    main ()

실행하면 query? 듣고 오므 caltech10 폴더의 이미지 파일 이름을 쿼리로 제공합니다. 이 결과로 쿼리와 유사한 상위 10 개의 이미지가 표시되고 result.jpg에 저장합니다.

query?> accordion-0001.jpg
1.000000 caltech10 / accordion-0001.jpg
0.762976 caltech10 / accordion-0049.jpg
0.757379 caltech10 / accordion-0025.jpg
0.753379 caltech10 / accordion-0036.jpg
0.748672 caltech10 / accordion-0042.jpg
0.739771 caltech10 / accordion-0022.jpg
0.737838 caltech10 / accordion-0002.jpg
0.734934 caltech10 / cougar_face-0044.jpg
0.733918 caltech10 / accordion-0037.jpg
0.733821 caltech10 / accordion-0010.jpg

실험 결과

는 일부 쿼리 이미지를주고 시도합니다. 왼쪽에있는 것이 쿼리 이미지입니다.

  • 아코디언

f : id : aidiary : 20100227210336j : plain

오, 1 개 이상한 들어 있기는하지만 제대로 찾을 수 있네요. 특정 물체 인식과 달리, 완전히 같은 이미지가 아니라도 (특정 물체 인식에서도 회전, 크기 변화 등에 대응할 수 있지만) 제대로 유사 검색 할 수 있다는 것이 Visual Words를 사용하는 이점 네요. 그럼 다른 예도 몇 가지.

  • 분재

f : id : aidiary : 20100227210337j : plain

  • 쿠거

f : id : aidiary : 20100227210338j : plain

  • 달마 시안

f : id : aidiary : 20100227210339j : plain

  • 지폐

f : id : aidiary : 20100227210340j : plain

  • 유포니 암

f : id : aidiary : 20100227210341j : plain

  • 그랜드 피아노

f : id : aidiary : 20100227210342j : plain

  • 고슴도치

f : id : aidiary : 20100227210343j : plain

  • 자전거

f : id : aidiary : 20100227210344j : plain

  • 음양

f : id : aidiary : 20100227210345j : plain

음양의 결과를 보면 알 수 있듯이 Visual Words 색상의 유사성은 보지 않기 때문에주의하십시오. 쿠거이나 달마 시안 만화 같은 그림에서도 비슷한 판정 할 수있는 것은 대단합니다. 지폐 액수는 다른데 제대로 유사 확인할 수 있습니다. 고슴도치 속의 음양도 어딘지 모르게 알 수 있습니다 (웃음)

(주) Visual Words 학습에 사용 된 이미지 및 테스트 이미지가 같은 것은 평가로는 좀 곤란하다고 생각합니다. 제대로 평가하고 싶은 사람은 학습용 이미지 설정 및 테스트 이미지 세트는 나눕시다.

정리

이번에는 국소 특징 량을 이용한 유사 이미지 검색을 만들었습니다.

위 결과를 보면 뭔가 대단해 생각하지만 실제로는 전혀 안돼 쿼리 이미지도있었습니다. 어떤 때 잘못되는지는 좀 더 조사가 필요합니다. 그리고 Visual Words 학습에 사용하지 않았던 카테고리 예를 들어 돌고래 쿼리 이미지를 주어서 비슷한 이미지는 찾을 수 없을 것입니다. Visual Words 돌고래의 특징이 포함되지 않고 히스토그램이 잘 만들 수없는 것입니다 (아직 시도하지 않았기 때문에 일을보십시오).

그런 이유로 Visual Words에서 일반적인 비슷한 이미지 검색 시스템을 구성하는 것은 어려운 것이 아닌가? 라고 추측하고 있습니다. 실제로, Visual Words를 비슷한 이미지 검색에 적용하는 연구는 적은 것 같습니다. Visual Words는 주로 일반 물체 인식 에 사용되는 것 같습니다. 쿼리로 준 이미지 카테고리 (아코디언이나 고슴도치 라든지)를 분류하는 작업입니다. Support Vector Machine을 적용한 연구를 잘 볼 수 있습니다. 중 일반 물체 인식을 시도해 같네요.

Visual Words는 국소 특징 량의 클러스터링이 필요한 것입니다 만, 분명히 말해 K-means가 넥입니다. K-means는 매우 느립니다입니다. bayon를 사용하여 이미지에서 bag-of-keypoints을 요구 (이 사람의 블로그 애독하고 있습니다)를 참고 CLUTO 및 bayon 도 검토하고있었습니다 만, 조금 모자 름 데이터를 만드는 방법을 알 수 없습니다 .. · bayon 문서 단어 행렬과 같은 희소 행렬의 클러스터링 알고리즘이라고 이해 했습니다만, 국소 특징 량 행렬과 같은 조밀 한 실수 벡터에 적용 할 수 있을까요? bayon 좀 더 자세히 조사해볼 예정입니다.

참고 문헌






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

일단 실행은 됨. 



cvCreateKDTree

cvFindFeatures

cvReleaseFeatureTree

의 식별자를 찾을 수 없다고 하면 (http://fossies.org/dox/opencv-2.4.9/)

precomp.hpp 추가


혹시.._featruetree.h 이것도 추가해보기..안해도 되긴하던데..




-----------------------------------------------------------------

[ 카테고리 이름 - 숫자 .jpg 라는 파일명으로 변환 ]

1.이 소스를 메모장에 붙여 넣고 저장. 이름 마음대로.(경로는 환경설정 안했으면 파이썬 깔려있는 곳)

TARGET 은 이미지들이 있는 경로

OUTDIR 은 새로 이름을 붙일 파일 경로


#coding : utf-8 

import codecs

import os

import os.path

import shutil


#TARGET = "101_ObjectCategories" 

TARGET = "C:/opencv/build/doc/Visual Words" 

OUTDIR = "C:/opencv/build/doc/Visual Words_rename"


if not os.path.exists (OUTDIR) :

    os.mkdir (OUTDIR)


for category in os.listdir (TARGET) :

     for  file  in os.listdir ( "%s/%s" % (TARGET, category)) :

        image_file = "% s/%s/%s" % (TARGET, category, file )

        rename_file = "%s/%s-%s" % (OUTDIR, category, file .replace( "image_" , "" ))

        print  "%s->%s" % (image_file, rename_file)

        shutil.copyfile (image_file, rename_file)


2.cmd창열어서 

2-1. 

cd C:\Python27

2-2.

python 파일명.py








[카테고리 1 번째에서 50 번째 이미지 만 추출]

1.이 소스를 메모장에 붙여 넣고 저장. 이름 마음대로.(경로는 환경설정 안했으면 파이썬 깔려있는 곳)

IMAGE_DIR  = OUTDIR 

SUBSET_DIR  새폴더 


#coding:utf-8

import os.path

import shutil


IMAGE_DIR = "C:/opencv/build/doc/Visual Words_rename"

SUBSET_DIR = "C:/opencv/build/doc/rename"


# ?象カテゴリ

TARGET_CATEGORY = ["accordion", "bonsai", "cougar_face", "dalmatian", "dollar_bill",

                   "euphonium", "hedgehog", "grand_piano", "Motorbikes", "yin_yang", ]


# ファイル番?が50以下の?像のみ?象

TOP = 50


# 出力ディレクトリがなければ作る

if not os.path.exists(SUBSET_DIR):

    os.mkdir(SUBSET_DIR)


for file in os.listdir(IMAGE_DIR):

    try:

        cat = file.split("-")[0]            # ファイルのカテゴリ名を取得

        num = int(file.split("-")[1][0:4])  # ファイル番?を取得

    except:

        continue

    

    # ?象カテゴリで?字がTOP以下のファイルのみコピ?

    if cat in TARGET_CATEGORY and num <= TOP:  # ?象カテゴリの場合

        source_image = "%s/%s" % (IMAGE_DIR, file)

        dest_image = "%s/%s" % (SUBSET_DIR, file)

        shutil.copyfile(source_image, dest_image)



2.cmd창열어서 

2-1. 

cd C:\Python27

2-2.

python 파일명.py

반응형