Problem with kmeans in opencv

asked 2017-12-14 11:52:12 -0600

i32romer gravatar image

updated 2017-12-14 12:37:38 -0600

include <iostream>

#include <sstream>
#include <string>
#include <vector>
#include <tclap/CmdLine.h>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/ml/ml.hpp>
#include "common_code.hpp"

#define IMG_WIDTH 300

int
main(int argc, char * argv[])
{
TCLAP::CmdLine cmd("Trains and tests a BoVW model", ' ', "0.0");

TCLAP::ValueArg<std::string> basenameArg("b", "basename", "basename for the dataset.", false, "./data", "pathname");
cmd.add(basenameArg);
TCLAP::ValueArg<std::string> configFile("c", "config_file", "configuration file for the dataset.", false, "02_ObjectCategories_conf.txt", "pathname");
cmd.add(configFile);
TCLAP::ValueArg<int> n_runsArg("r", "n_runs", "Number of trials train/test to compute the recognition rate. Default 10.", false, 10, "int");
cmd.add(n_runsArg);
TCLAP::ValueArg<int> ndesc("", "ndesc", "[SIFT] Number of descriptors per image. Value 0 means extract all. Default 0.", false, 0, "int");
cmd.add(ndesc);
TCLAP::ValueArg<int> keywords("w", "keywords", "[KMEANS] Number of keywords generated. Default 100.", false, 100, "int");
cmd.add(keywords);
TCLAP::ValueArg<int> ntrain("", "ntrain", "Number of samples per class used to train. Default 15.", false, 15, "int");
cmd.add(ntrain);
TCLAP::ValueArg<int> ntest("", "ntest", "Number of samples per class used to test. Default 50.", false, 50, "int");
cmd.add(ntest);
TCLAP::ValueArg<int> k_nn("", "k_nn", "[KNN] Number k neighbours used to classify. Default 1.", false, 1, "int");
cmd.add(k_nn);

cmd.parse(argc, argv);

// --------------- MAIN BLOCK ---------------

std::vector<std::string> categories;
std::vector<int> samples_per_cat;

std::string dataset_desc_file = basenameArg.getValue() + "/" + configFile.getValue();

int retCode;
if ((retCode = load_dataset_information(dataset_desc_file, categories, samples_per_cat)) != 0)
{
    std::cerr << "Error: could not load dataset information from '"
        << dataset_desc_file
        << "' (" << retCode << ")." << std::endl;
    exit(-1);
}

std::cout << "Found " << categories.size() << " categories: ";
if (categories.size()<2)
{
    std::cerr << "Error: at least two categories are needed." << std::endl;
    return -1;
}

for (size_t i=0;i<categories.size();++i)
    std::cout << categories[i] << ' ';
std::cout << std::endl;

std::vector<float> rRates(n_runsArg.getValue(), 0.0);

// Repeat training+test
for (int trial=0; trial<n_runsArg.getValue(); trial++)
{
    std::clog << "######### TRIAL " << trial+1 << " ##########" << std::endl;

    std::vector<std::vector<int>> train_samples;
    std::vector<std::vector<int>> test_samples;
    create_train_test_datasets(samples_per_cat, ntrain.getValue(), ntest.getValue(), train_samples, test_samples);

    //-----------------------------------------------------
    //                  TRAINING
    //-----------------------------------------------------

    std::clog << "Training ..." << std::endl;
    std::clog << "\tCreating dictionary ... " << std::endl;
    std::clog << "\t\tComputing descriptors..." << std::endl;
    cv::Mat train_descs;
    cv::Mat1f totalmat;
    std::vector<int> ndescs_per_sample;
    ndescs_per_sample.resize(0);
    cv::Mat labels;
    cv::Mat1f centers;
    std::vector <cv::Mat> bovw;

      for (size_t c = 0; c < train_samples.size(); ++c)
    {
        std::clog << "  " << std::setfill(' ') << std::setw(3) << (c * 100) / train_samples.size() << " %   \015";
        for (size_t s = 0; s < train_samples[c].size(); ++s)
        {
            std::string filename = compute_sample_filename(basenameArg.getValue(), categories[c], train_samples[c][s]);
            cv::Mat img = cv::imread(filename, cv::IMREAD_GRAYSCALE);
            if (img.empty())
            {
                std::cerr << "Error: could not read image '" << filename << "'." << std::endl;
                exit(-1);
            }
            else
            {
               // Fix size:  width =300px
                //! \todo TO BE COMPLETED
                cv::Size size(300,300*img.rows/300*img.cols);
                resize(img,img,size);
                // Extract SIFT descriptors
                //-----------------------------------------------------
                cv::Mat1f descs ...
(more)
edit retag flag offensive close merge delete

Comments

would you be so nice, and replace the screenshot with a text version of the errormsg ? thank you !

berak gravatar imageberak ( 2017-12-14 12:12:54 -0600 )edit

you need at least 100 samples, to cluster 100 centers, that's what the error says.

check your totalmat, cout << totalmat.size();

can you explain, why there are 2 loops for the train_samples ?

have you seen, that opencv has builtin classes for BoW ?

berak gravatar imageberak ( 2017-12-14 12:19:49 -0600 )edit
1

Thank you so much for your time, I have replaced the screenshot for a text version. The size of Mat totalmat is 128*0.The function vconcat doesn't work right, I don't know why..

i32romer gravatar imagei32romer ( 2017-12-14 12:35:49 -0600 )edit
1

cv::Size size(300,300*img.rows/300*img.cols); <-- looks entirely broken. (missing braces?) right now, it's the same as Size(300, img.rows*img.cols) , clearly not what you wanted.

skip the whole resize (it's not nessecary), and check if there's something in your descs, before proceeding.

berak gravatar imageberak ( 2017-12-15 03:00:02 -0600 )edit

Thank you.

i32romer gravatar imagei32romer ( 2017-12-19 12:51:58 -0600 )edit