Ask Your Question

Problem with knn

asked 2017-01-03 12:01:28 -0500

Dororo gravatar image

updated 2017-01-05 07:57:10 -0500

Hi there,

Im using OpenCV 2.4.12 with Visual Studio 2012. I am trying to classify facial image based 3 age groups. i have extracted the features using PCA in image form. Below is my PCA code. I need help to classify the images using the features extracted using knn.

#include "opencv2/contrib/contrib.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <fstream>
#include <sstream>

using namespace cv;
using namespace std;

static Mat norm_0_255(InputArray _src) {
    Mat src = _src.getMat();
    // Create and return normalized image:
    Mat dst;
    switch(src.channels()) {
    case 1:
        cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
    case 3:
        cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
    return dst;

static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') {
    std::ifstream file(filename.c_str(), ifstream::in);
    if (!file) {
        string error_message = "No valid input file was given, please check the given filename.";
        CV_Error(CV_StsBadArg, error_message);
    string line, path, classlabel;
    while (getline(file, line)) {
        stringstream liness(line);
        getline(liness, path, separator);
        getline(liness, classlabel);
        if(!path.empty() && !classlabel.empty()) {
            images.push_back(imread(path, 0));

int main(int argc, const char *argv[]) {
    // Check for valid command line arguments, print usage
    // if no arguments were given.
    if (argc < 2) {
        cout << "usage: " << argv[0] << " <csv.ext> <output_folder> " << endl;
    string output_folder = ".";
    if (argc == 3) {
        output_folder = string(argv[2]);
    // Get the path to your CSV.
    string fn_csv = string(argv[1]);
    // These vectors hold the images and corresponding labels.
    vector<Mat> images;
    vector<int> labels;
    // Read in the data. This can fail if no valid
    // input filename is given.
    try {
        read_csv(fn_csv, images, labels);
    } catch (cv::Exception& e) {
        cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl;
        // nothing more we can do
    // Quit if there are not enough images for this demo.
    if(images.size() <= 1) {
        string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
        CV_Error(CV_StsError, error_message);
    // Get the height from the first image. We'll need this
    // later in code to reshape the images to their original
    // size:
    int height = images[0].rows;
    // The following lines simply get the last images from
    // your dataset and remove it from the vector. This is
    // done, so that the training data (which we learn the
    // cv::FaceRecognizer on) and the test data we test
    // the model with, do not overlap.
    Mat testSample = images[images.size() - 1];
    int testLabel = labels[labels.size() - 1];
    // The following lines create an Eigenfaces model for
    // face recognition and train it with the images and
    // labels read from the given CSV file.
    // This here is a full PCA, if you just want to keep
    // 10 principal components (read Eigenfaces), then call
    // the factory method like this:
    //      cv::createEigenFaceRecognizer(10);
    // If you want to create a FaceRecognizer with a
    // confidence threshold (e.g. 123.0), call it with:
    //      cv::createEigenFaceRecognizer(10, 123 ...
edit retag flag offensive close merge delete



those 2 files look like they're the MNIST (handwritten letters, not faces at all) train data. you probably won't be able to use any of it for faces.

berak gravatar imageberak ( 2017-01-04 09:09:16 -0500 )edit

Can you suggest any source code that would be helpful for facial age classification using knn. I am totally new to image processing. Thank you.

Dororo gravatar imageDororo ( 2017-01-04 09:13:21 -0500 )edit

unfortunately, i'm no more at ease with the c-based api, you are using here

berak gravatar imageberak ( 2017-01-04 09:18:20 -0500 )edit

also, the combination of i am totally new to image processing and I need facial age classification using KNN does not make sense at all. How about starting with the basics?

StevenPuttemans gravatar imageStevenPuttemans ( 2017-01-05 02:50:41 -0500 )edit

@Dororo, maybe you want to restart (edit) your question - get rid of that unusable MNIST, CvMat based code, and instead show us, how far you got with the PCA. then we probably can help you, feeding that into KNN or similar.

berak gravatar imageberak ( 2017-01-05 02:59:32 -0500 )edit

@berak, I have edited the question. Please help with the classification. Thank you

Dororo gravatar imageDororo ( 2017-01-05 08:03:07 -0500 )edit

unfortunately, this is still not very helpful, it's just a literal copy of the 2.4 sample code.

do you understand, that you have to do your own PCA , if you want to change the builtin classification mechanism ?

i'm a bit afraid, this is way over your head, could you at least start to use above code as is ? switching the nearest-neighbour to aknn classification won't give you much gain anyway, imho.

berak gravatar imageberak ( 2017-01-07 04:22:02 -0500 )edit

I think you misunderstood me. I have done with my PCA. It works fine and i can get the eigenvalues. My question is, how do I use this output to classify face images according to age group.

Dororo gravatar imageDororo ( 2017-01-07 04:36:09 -0500 )edit

ohh, i actually hope, i misunderstood you !

(it would be impossible, to help you else.)

berak gravatar imageberak ( 2017-01-07 05:40:43 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2017-01-07 05:41:56 -0500

berak gravatar image

updated 2017-01-07 05:43:48 -0500

assuming, you've done your PCA, and projected your data to PCA space:

 PCA pca(data, Mat(), CV_PCA_DATA_AS_ROW, _num_components);
 Mat projected = pca.project(data);

you can now setup KNearest for training:

CvKNearest knn;   // assumes opencv2.4
Mat labels = ...  // nimages rows, 1 column, containing an integer per image with the resp. age group.
knn.train(projected, labels);

once this has finished, you can predict with new data. (you'll need to keep the PCA and the KNN objects):

Mat img = ... // convert to float, reshape to a single row.
Mat query = pca.project(img);
int K = 3;    // majority vote of K neighbours
int predicted = (int) knn.find_nearest(query, K);
// now, 'predicted' holds the age-group-id, you fed into the labels when training.
edit flag offensive delete link more

Question Tools

1 follower


Asked: 2017-01-03 12:01:28 -0500

Seen: 368 times

Last updated: Jan 07 '17