Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unvalid xml file and other basic questions about SVM trainers #463

Open
CARL-Bouvet opened this issue Nov 27, 2018 · 8 comments
Open

unvalid xml file and other basic questions about SVM trainers #463

CARL-Bouvet opened this issue Nov 27, 2018 · 8 comments

Comments

@CARL-Bouvet
Copy link

Hello guys, hello Vincent,
I ask noob questions, sorry about that.

My xml file for a very simple detection set return that common error :

terminate called after throwing an instance of 'std::runtime_error'
  what():  OpenCV Error: (The node does not represent a user object (unknown type?)) in cvRead, in file /home/.../node_modules/opencv-build/opencv/ope
ncv/modules/core/src/persistence_c.cpp, line 1426, status -2
Abandon (core dumped)

It is probably the SVM trainer that gets me an invalid XML file.
So, I have a lot of questions before I can to be on my own:

At first; how to get settings chosen by the computer if we use the trainauto mode ?
Is there a command for console.log theme? even in python, this command is hard to find.

The code of my SVM trainer is almost the same as @justadudewhohacks 's one.

Thank you all.

@justadudewhohacks
Copy link
Owner

Hm not sure if the actual error is related to this package, rather then being an issue with OpenCV not being able to load your xml file.

To your second question, when using trainAuto, shouldn't you be able to get all the updated properties by logging the svm object: console.log(svm)?

@CARL-Bouvet
Copy link
Author

thank you for your answer.

console.log(svm)

it's as simple as that!? shame on me...
ok, that command works:

SVM {
  isTrained: true,
  varCount: 10404,

  classWeights:
   Mat {
     step: 0,
     elemSize: 0,
     sizes: [],
     empty: true,
     depth: 0,
     dims: 0,
     channels: 1,
     type: 0,
     cols: 0,
     rows: 0 },
  kernelType: 2,
  p: 0,
  nu: 0,
  gamma: 0.00015000000000000001,
  degree: 0,
  coef0: 0,
  c: 312.5 }

But average prediction results with test datas is 0.8208955223880597 so WTF*$#?!
My trainData mats are not empty so my problême is probably my HOG paramêtres, or letters in train pictures are too small or I don t know ...

const hog = new cv.HOGDescriptor({
  winSize: new cv.Size(90, 90),
  blockSize: new cv.Size(10, 10),
  blockStride: new cv.Size(5, 5),
  cellSize: new cv.Size(5, 5),
  L2HysThreshold: 0.2,
  nbins: 9, 
  gammaCorrection: true,
  signedGradient: true 
});

If you see something wrong, please tell me. I continue my investigation.
I will probably ask other questions soon so don't close that tread please. and thank you again.

@justadudewhohacks
Copy link
Owner

Uhm 0.82 is pretty good, that's overall about what I achieved in the example, isn't it?

@CARL-Bouvet
Copy link
Author

yes. but with my own data.

const arrayDAlphabetMinus = Array(26).fill(97).map((v, i) => v + i).map(ascii => String.fromCharCode(ascii));
const arrayDAlphabetMajus = Array(26).fill(65).map((v, i) => v + i).map(ascii => String.fromCharCode(ascii));
const arrayNombre = Array(10).fill(48).map((v, i) => v + i).map(ascii => String.fromCharCode(ascii));
const arrayPonct = ([33, 39, 44, 45, 63]).map(ascii => String.fromCharCode(ascii));
const arrayDeToutLesCaracteres = ((arrayDAlphabetMinus.concat(arrayDAlphabetMajus)).concat(arrayNombre)).concat(arrayPonct);

const data = arrayDeToutLesCaracteres.map((char) => {
  const trainDataDir = `${trainDataPath}/${char}`;
  const testDataDir = `${testDataPath}/${char}`;
  const train = fs.readdirSync(trainDataDir).map(file => `${trainDataDir}/${file}`);
  const test = fs.readdirSync(testDataDir).map(file => `${testDataDir}/${file}`);
  return ({ train, test });
});

I think i find my mistake: our train pictures must be on THRESH_BINARY (or THRESH_BINARY_INV) for to be readable by the HOG?

@CARL-Bouvet
Copy link
Author

no, it still does not work. I'm stalling!

(function main(){
  const img = './testpourSVMtraining.png';
  const xmlFilePath = ('./SVMdetest.xml');
  const classifier = new cv.CascadeClassifier(xmlFilePath); /* it doesn t want to use this xml file. */

  const src = cv.imread(img);
  const letterRects = classifier.detectMultiScale(src).objects;
  if (!letterRects.length){
    throw new Error("nothing detected.");
  }
  const result1 = img.getRegion(letterRects[0]);
  console.log(result1);
 })();
terminate called after throwing an instance of 'std::runtime_error'
  what():  OpenCV Error: (The node does not represent a user object (unknown type?)) in cvRead, in file /home/.../node_modules/opencv-build/opencv/opencv/modu
les/core/src/persistence_c.cpp, line 1426, status -2
Abandon (core dumped)

some train images:
a_arimakoshi-medium a_arsenal-regular a_acme-regular a_arimamadurai-extrabold

and My HOGAndSVMTrainer.js

const fs = require('fs');
const cv = require('./node_modules/opencv4nodejs');
const path = require('path')
const trainDataPath = './trainData';
const testDataPath = './testData';
const outPath = './';
const SVMFile = 'SVMdetest.xml';

const hog = new cv.HOGDescriptor({
  winSize: new cv.Size(90, 90),
  blockSize: new cv.Size(60, 60),
  blockStride: new cv.Size(30, 30),
  cellSize: new cv.Size(30, 30),
  L2HysThreshold: 0.2,
  nbins: 9, 
  gammaCorrection: true,
  signedGradient: true 
});
const svm = new cv.SVM({
  kernelType: cv.ml.SVM.RBF,
  c: 12.5,
  gamma: 0.50625 
});

const arrayDAlphabetMinus = Array(26).fill(97).map((v, i) => v + i).map(ascii => String.fromCharCode(ascii));
const arrayDAlphabetMajus = Array(26).fill(65).map((v, i) => v + i).map(ascii => String.fromCharCode(ascii));
const arrayNombre = Array(10).fill(48).map((v, i) => v + i).map(ascii => String.fromCharCode(ascii));
const arrayPonct = ([33, 39, 44, 45, 63]).map(ascii => String.fromCharCode(ascii));
const arrayDeToutLesCaracteres = ((arrayDAlphabetMinus.concat(arrayDAlphabetMajus)).concat(arrayNombre)).concat(arrayPonct);
const data = arrayDeToutLesCaracteres.map((char) => {
  const trainDataDir = `${trainDataPath}/${char}`;
  const testDataDir = `${testDataPath}/${char}`;
  const train = fs.readdirSync(trainDataDir).map(file => `${trainDataDir}/${file}`);
  const test = fs.readdirSync(testDataDir).map(file => `${testDataDir}/${file}`);
  return ({ train, test });
});

const computeHOGDescriptorFromImage = (img) => {
 if (img.rows !== 90 || img.cols !== 90) {
    console.log(`l image ${img} n est pas au bon format ?! \n elle fait ${img.rows}x${img.cols}`);
    return 0;
  }
  return hog.compute(img);
};

const trainSVM = (trainDataFiles) => {
  console.log('constitution des données du HOG et étiquetage');
  const échantillonDImages = [];
  const étiquettes = [];
  trainDataFiles.forEach((files, label) => {
    files.forEach((file) => {
      const img = cv.imread(file);
      const desc = computeHOGDescriptorFromImage(img);
            if (!desc) {
        return;
      }

      échantillonDImages.push(desc);
      étiquettes.push(label);
    });
  });

  console.log('entrainement');
  const trainData = new cv.TrainData(
    new cv.Mat(échantillonDImages, cv.CV_32F),
    0,
    new cv.Mat([étiquettes], cv.CV_32S)
  );
  svm['trainAuto'](trainData);
  console.log(svm);
};

const trainDataFiles = data.map(classData => classData.train); /*data l35 */
const testDataFiles = data.map(classData => classData.test);

const numTrainImagesPerClass = trainDataFiles[0].length;
const numTestImagesPerClass = testDataFiles[0].length;
console.log('train data per class:', numTrainImagesPerClass);
console.log('test data per class:', numTestImagesPerClass);

trainSVM(trainDataFiles, true);
svm.save(`${outPath}/${SVMFile}`);
svm.load(`${outPath}/${SVMFile}`);

... without errs module, saveConfusionMatrix etc...
because I m not familiar with xml file, I look for in that direction now but if you see something, have a suggestion, I m all ears.

@justadudewhohacks
Copy link
Owner

Odd, could you upload the xml file here, which is being produced from svm.save?

@CARL-Bouvet
Copy link
Author

sure!
upload link

or

SVMdetest.zip

@CARL-Bouvet
Copy link
Author

I just tryed with a copy/paste of haarcascade_eye.xml and it's work perfectly.
So my problem is my code or my config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants