cirocosta / gulp-converter-tjs

Converts old/new type of OpenCV HaarCascade xml data to trackingJs' internal format.
MIT License
37 stars 6 forks source link

Can't convert Banana classifier #9

Open leemartin opened 9 years ago

leemartin commented 9 years ago

Hey there, I'm trying to convert the banana classifier found here:

https://github.com/mrnugget/opencv-haar-classifier-training/blob/master/trained_classifiers/banana_classifier.xml

But I'm receiving:

"Error: Number of rects does not mach number of Nodes"

Any help is much appreciated!

leemartin commented 9 years ago

:( my poor banana bro

cirocosta commented 9 years ago

@leemartin wow, thanks for the ping, i din't see the notification!

hmmm, that's strange. I'd suggest you firstly verifying if this classifier does works on opencv but i'm pretty confident that it works (almost sure that it was generated using opencv ... ). This converter is somewhat a 'port' of what opencv does to convert the old format to the new (https://gist.github.com/cirocosta/8209125570b7a525f64c#file-cascadedetect_convert-cpp-L301-L303 - in the comment, weak == node), so i think the solution might be to take a deeper look at how this is actually handed by the opencv interpreter and not only the opencv converter. (just removing the error won't solve it as trackingjs needs the propert number of rects and nodes).

If you're up to take this i'd be glad to help you :))

leemartin commented 9 years ago

Hey there, I can definitely confirm that the classifier works on the opencv side:

https://vimeo.com/103969578

I was just hoping to convert to something trackingjs requires to move my logic to the client.

Let me know what I can do!

applesaucesome commented 9 years ago

Hi, if you run "_opencvtraincascade" with the "-baseFormatSave" flag, it will save it in the old format, which will allow "gulp-converter-tjs" to convert it successfully. To save it in the new format, just leave that flag out.

http://docs.opencv.org/doc/user_guide/ug_traincascade.html

===== Example export to old format =====

opencv_traincascade -data classifier -vec samples.vec -bg negatives.txt\ -numStages 20 -minHitRate 0.999 -maxFalseAlarmRate 0.5 -numPos 1000\ -numNeg 600 -w 80 -h 40 -mode ALL -precalcValBufSize 1024\ -precalcIdxBufSize 1024 -baseFormatSave

cirocosta commented 9 years ago

Actually the converter should work for both formats (old and new) as it converts ok for some classifiers :(

Also, thanks for pointing this @kleichtle !

leemartin commented 9 years ago

I'll give it a shot!

cirocosta commented 9 years ago

:+1: :+1:

snowytia commented 9 years ago

Hi, I'm having the same problem. As far as I see it only works with old formats, these ones satisfy #nodes==#rects (i.e. for each node there is a feature and only one), and it is not possible to declare more or less rects, even if they are not going to be used and vice versa (which is the case of the new formats of OpenCV, working properly). They are just referenced by a number.

Here there is a good example from the official OpenCV: http://docs.opencv.org/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.html It does work ok, but when trying to convert the haarcascade_eye_tree_eyeglasses.xml with gulp-converter-tjs it doesn't work.

Even when I commented lines 145, 146 in converter-tjs.js, undefined access errors appear through this piece of code, loop from 177 to 196:

// iterate through nodes
    for (var j = 0; j < stage.nnodes;) {
      // tilted, rectsLength
      var node = stage.nodes[j++];
      var rect = orig.rects[f++];

      results.push(rect.tilted);
      results.push(rect.data.length);

      // iterate through rects
      for (var k = 0, N = rect.data.length; k < N;) {
        // rectLeft, rectTop, rectWidth, rectHeight, rectWeight
        var R = rect.data[k++].split(' ');
        for (var l = 0, M = R.length; l < M; l++)
          results.push(+R[l]);
      }

      results.push(node.threshold);
      results.push(node.left_val);
      results.push(node.right_val);
    }

I think the problem is that as you are parsing the rects inside each node, in the new xml format this is a problem because you may have different amount of nodes and rects, so it tries to access to undefined objects. Of course with the old format it works ok because these numbers are the same.

You think it could be fixed if you use two different loops instead one inside the other? @cirocosta Or how could I fixed it in order to work with new format files?

Cheers! :wink:

leemartin commented 9 years ago

+1

odeniz commented 9 years ago

+1

gilles-yvetot commented 9 years ago

+1

mgattelli commented 8 years ago

+1

samucs commented 8 years ago

+1

leemartin commented 8 years ago

Still a dream of mine to see this adjusted.

p0wdrdotcom commented 7 years ago

+1

p0wdrdotcom commented 7 years ago

Hi, I sure opencv training will create new format classifiers that break this. if (g !== f)

I have one that has 40 stages. It works in opencv detectMultiScale fine but wont convert through this.

Are there any docs on the data structure and what the parts are used for. I'm sure there is a simple solution to this.

p0wdrdotcom commented 7 years ago

I've created a gist that is an attempt where I've modified your converter to support the JSFeat standard. https://gist.github.com/p0wdrdotcom/d6a145771a391405f445ae91a0c3ae5e

I think that the new opencv xml format tries to save space in the XML file by de-duplicating features. I assume that this is actually a index pointer to the feature for the node.
node.f = +internalNodes[2];

After the XML parsing is done, I marry them up like so...

haarStruct.complexClassifiers.forEach(function (stage) {
            stage.simpleClassifiers.forEach(function (weakClassifier) {
                var rects = features[weakClassifier.f].rects.map(function (rect) {
                    return rect.split(' ').map(function (numberString) {
                        return +numberString;
                    });
                });
                delete weakClassifier.f;
                weakClassifier.features = rects;
            });
        });

The structure is different but I think it gathers the right feature rects.

cirocosta commented 7 years ago

Hey @p0wdrdotcom , i really appreciate your efforts! I have literally no time to maintain this right now :/ As you said, it should not be hard, just a matter of getting the translation from cv to the right translation. By now, can't remember the format (and as i remember there's no real docs on this internals; just went through the code by that time).

@p0wdrdotcom , if you'd like to give continuity to this, feel free to do so; i can grant you the permissions 😁 It'd be an awesome addition to tracking.js as a whole!

Thx!

p0wdrdotcom commented 7 years ago

Okay, I'll attack it this properly. I'll get some opencv classifiers and setup some test cases. I''ll use tracking JS as it seems to be more maintained than JS feat. I don't have experience with Gulp but I can just work on the ConverterTJS unit

f138150 commented 7 years ago

@leemartin @cirocosta Hi, so did you found solution to your problem, I am stuck with the same problem, using a custom trained Har file (new format) and it gives me the same problem

"Error: Number of rects does not mach number of Nodes"

Any help is highly appreciated.

tiagokall commented 6 years ago

+1