しかし、SURFが抽出したkeypointを使って画像識別を行いたい場合は以下のようにいくつかの問題がある。
- 画像から抽出されるkeypointの数は一定でない。
- 統計処理を行うのに必要な数のkeypointが選ばれないことがある。
- コントラストが小さい画像の場合keypointが一つも選ばれないこともある。
ということで、あらかじめ決めておいたグリッド上の点をkeypointとして選ぶdense samplingという手法がよく使われるらしい。dense samplingで選んだ点に対してSURFでdescriptorを計算するということをやってみた。
ソースコード
#include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/nonfree/nonfree.hpp" using namespace cv; static void help() { printf("Usage:\n dense_sample <image> \n"); } int main(int argc, char** argv) { if(argc != 2) { help(); return -1; } Mat img = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); if(img.empty()) { printf("Can't read an image.x\n"); return -1; } DenseFeatureDetector detector( 4.0, // initFeatureScale (keypoints' diameter) 2, // featureScaleLevels (how many time apply detector with changing image scale) 0.5, // featureScaleMul (scale factor) 1, // initXyStep (distance between two keypoints) 0, // initImgBound (start axis of keypoints) false, // varyXyStepWithScale false // varyImgBoundWithScale ); // detecting keypoints vector<KeyPoint> keypoints; detector.detect(img, keypoints); // computing descriptors SurfDescriptorExtractor extractor; Mat descriptors; extractor.compute(img, keypoints, descriptors); // show info std::cout << "keypoints of img: " << keypoints.size() << std::endl; std::cout << "descriptors of img: " << descriptors.size() << std::endl; return 0; }
メモ書き
DenseFeatureDetectorというOpenCVのクラスを使うと簡単にdense samplingが出来た。keypointの半径が何を意味しているのかよく分かっていない。勾配ベクトルのヒストグラムを計算するときの領域サイズとかだろうか??SURFのアルゴリズムをもう少し詳しく調べないといけない気がする。とりあえず、これで同じサイズの画像からは同じサイズの特徴ベクトルを抽出できるようになった。descriptorをクラスタリングして、各クラスタに属するdescriptorの数をヒストグラムで表したものを特徴量として扱う手法が有名みたいなので今度はそれをやってみようと思う。
0 件のコメント:
コメントを投稿