2012-02-12 18 views
7

Đào tạo Trình mô tả OpenCV có thể tốn thời gian hoạt động nếu tập hợp hình ảnh đào tạo lớn. Vì vậy, có vẻ như tiết kiệm dữ liệu DescriptorMatcher được đào tạo vào đĩa để tải lại sau này sẽ là một điều khá rõ ràng để muốn làm.Lưu và tải FlannBasedMatcher

Rất tiếc, dường như không có giải pháp rõ ràng nào cho nhu cầu này.

Gần nhất tôi tìm thấy câu trả lời là this thread in the OpenCV discussion group. Chủ đề bắt đầu vào năm 2009 và mọi người vẫn đang tìm kiếm câu trả lời vào năm 2011!

Đoạn mã này được lấy từ chủ đề đó có vẻ như nó nên tải lại một chỉ số từ một tập tin:

FileStorage fs("data.xml",FileStorage::READ); 
Mat data; 
fs["mtx"] >> data; 
flann::Index idx(data,"index.bin"); 

Nhưng tôi đã không thể tìm ra từ này như thế nào để thực hiện hoàn chỉnh tiết kiệm năng/tải.

Chỉ trong trường hợp nó có liên quan, tôi đang sử dụng OpenCV 2.3.1.

Trả lời

5

Tôi không thấy câu trả lời cho điều này trên diễn đàn hoặc danh sách gửi thư. Tôi phải đào sâu vào mã nguồn OpenCV (2.4.5) để xem việc này cần được thực hiện như thế nào. Nó yêu cầu phân lớp để nhận được các thành viên được bảo vệ của FlannBasedMatcher.

Khóa đang đặt thuật toán thành FLANN_INDEX_SAVED và tên tệp trên indexParams.

Ngoài ra cần chú ý:

  • Các mô tả phải được thông qua để thêm() trước khi readIndex()

  • Đối với chỉ số được xây dựng, bạn phải làm một trận đấu vào nó trước, sau đó gọi write(). train() dường như không làm bất cứ điều gì ngoại trừ việc xây dựng các matcher (không ăn nó mô tả)

  • Điều này làm việc với các mô tả SURF. Để có giải pháp hoàn chỉnh, có thể cần phải lưu/khôi phục IndexParams và/hoặc SearchParams của trình ghép nối.

Điều tiếp theo cần làm là nén chỉ mục (bằng gzip), nó có thể nhỏ hơn 3-4 lần và chi phí để giải nén tương đối thấp. Điều này sẽ phải là một bản vá trong OpenCV.

class SaveableMatcher : public cv::FlannBasedMatcher 
{ 
public: 
SaveableMatcher() 
{ 
} 

virtual ~SaveableMatcher() 
{ 
} 

void printParams() 
{ 
    printf("SaveableMatcher::printParams: \n\t" 
     "addedDescCount=%d\n\t" 
     "flan distance_t=%d\n\t" 
     "flan algorithm_t=%d\n", 
     addedDescCount, 
     flannIndex->getDistance(), 
     flannIndex->getAlgorithm()); 

    vector<std::string> names; 
    vector<int> types; 
    vector<std::string> strValues; 
    vector<double> numValues; 

    indexParams->getAll(names, types, strValues, numValues); 

    for (size_t i = 0; i < names.size(); i++) 
     printf("\tindex param: %s:\t type=%d val=%s %.2f\n", 
       names[i].c_str(), types[i], 
       strValues[i].c_str(), numValues[i]); 

    names.clear(); 
    types.clear(); 
    strValues.clear(); 
    numValues.clear(); 
    searchParams->getAll(names, types, strValues, numValues); 

    for (size_t i = 0; i < names.size(); i++) 
     printf("\tsearch param: %s:\t type=%d val=%s %.2f\n", 
       names[i].c_str(), types[i], 
       strValues[i].c_str(), numValues[i]); 
} 

void readIndex(const char* filename) 
{ 
    indexParams->setAlgorithm(cvflann::FLANN_INDEX_SAVED); 
    indexParams->setString("filename", filename); 

    // construct flannIndex now, so printParams works 
    train(); 

    printParams(); 
} 

void writeIndex(const char* filename) 
{ 
    printParams(); 
    flannIndex->save(filename); 
} 
}; 
+0

Lưu ý: như tôi đã hiểu, bản thân các bộ mô tả phải được tuần tự hóa/deserialized riêng biệt. Khi tải, _prior_ để gọi readIndex, các descriptor phải được deserialized và thêm vào (tức là, với FlannBasedMatcher :: add). – sircolinton

3

Trong OpenCV 2.4.0 (mà còn ở 2.3.1a) có:

// Reads matcher object from a file node 
virtual void read(const FileNode&); 
// Writes matcher object to a file storage 
virtual void write(FileStorage&) const; 

được thực hiện ít nhất là trong FlannDescriptorMatcher nhưng việc thực hiện dường như tiết kiệm chỉ là IndexParams của khớp. Thay vì flann :: Index_ có một phương thức lưu và tải (trong 2.3.1 có thể lưu trong khi tải có vẻ sẵn sàng khi sử dụng SavedIndexParams

+0

Có, chức năng đọc và ghi chỉ lưu IndexParams. Tôi sẽ xem xét các chức năng khác mà bạn đã đề cập. –

3

Câu hỏi này đã được hỏi từ lâu rồi, vì vậy bạn có thể đã có câu trả lời, nhưng tôi Tôi đã không lưu DescriptorMatcher, nhưng tạo ra một tập tin descriptors.xml cho mỗi hình ảnh trong bộ sưu tập, và sau đó nạp tất cả những thứ này vào một Vector để được sử dụng làm đầu vào cho tàu() Điều này làm giảm thời gian chạy chương trình từ 2 phút xuống còn 5 giây, nhưng phải mất 3-4 giây để tải các bộ mô tả vào trong Vector Sẽ rất thuận tiện để tải toàn bộ chỉ mục được đào tạo. một cách để làm điều đó.

1

Tôi đã xem mã OpenCV 3.2.0 và thấy rằng hàm write()/read() của đối sánh dựa trên Flann vẫn không lưu/tải dữ liệu được đào tạo. Lấy cảm hứng từ câu trả lời của wally, tôi đã tạo ra một class matcher tương tự như được thừa kế từ FlannBasedMatcher. Lưu ý rằng trình kết hợp dễ hiểu này hiện chỉ hoạt động với các bộ mô tả SURF.

Lớp đáng tin cậy này FlannBasedSavableMatcher viết indexParams, searchParams và mô tả được đào tạo vào tệp xml/yml nhưng phải viết flannIndex thành tệp nhị phân riêng biệt vì phương thức save() của flannIndex chỉ hỗ trợ định dạng nhị phân thô.

Dưới đây là tiêu đề lớp.

#ifndef INCLUDES_FLANNBASEDSAVABLEMATCHER_H_ 
#define INCLUDES_FLANNBASEDSAVABLEMATCHER_H_ 

#include <string> 

#include <opencv2/core.hpp> 
#include <opencv2/features2d.hpp> 

namespace cv 
{ 

class FlannBasedSavableMatcher : public FlannBasedMatcher 
{ 
private: 
    std::vector<std::string> trainedImgFilenameList; 
    std::string flannIndexFileDir; 
    std::string flannIndexFilename; 

public: 
    FlannBasedSavableMatcher(); 
    virtual ~FlannBasedSavableMatcher(); 

    std::vector<std::string> getTrainedImgFilenameList(); 
    void setTrainedImgFilenameList(const std::vector<std::string>& imgFilenameList); 
    void setFlannIndexFileDir(const std::string& dir); 
    void setFlannIndexFilename(const std::string& filename); 

    virtual void read(const FileNode& fn); 
    virtual void write(FileStorage& fs) const; 

    static Ptr<FlannBasedSavableMatcher> create(); 
}; 

} 

#endif /* INCLUDES_FLANNBASEDSAVABLEMATCHER_H_ */ 

Các tập tin nguồn có thể được tìm thấy tại https://github.com/renweizhukov/LearningOpenCV/blob/master/FlannKnnSavableMatching1toN/src/FlannBasedSavableMatcher.cpp, trong khi một sử dụng mẫu có thể được tìm thấy tại https://github.com/renweizhukov/LearningOpenCV/blob/master/FlannKnnSavableMatching1toN/src/main.cpp.

Các vấn đề liên quan