Kagami/go-face

Test python result and golang

Closed this issue · 4 comments

Unit tests pass well against I have a lot of problem.

``
package main

import (
"fmt"
"io/ioutil"
"log"
"github.com/Kagami/go-face"
)

func main() {

    var samples []face.Descriptor
    var cats []int32
    var labels []string

    rec, err := face.NewRecognizer("../opencv-test-sample/train")
    if err != nil {
            log.Fatalf("Can't init face recognizer: %v", err)
    }


    folderNameOfPersons, err := ioutil.ReadDir("../opencv-test-sample/train")
    if err != nil {
            log.Fatal(err)
    }

    //GEt all Personn
    indexPerson:=0
    for _, folderNameOfPerson := range folderNameOfPersons {
            if folderNameOfPerson.IsDir(){
                    pathPerson:="../opencv-test-sample/train/"+folderNameOfPerson.Name()

                    personFiles, err := ioutil.ReadDir(pathPerson)
                    if err != nil {
                            log.Fatal(err)
                    }

                    labels = append(labels, folderNameOfPerson.Name())
                    for _, file := range personFiles {
                            fmt.Println("Load:",pathPerson+"/"+file.Name())
                            faces, err := rec.RecognizeFile(pathPerson+"/"+file.Name())
                            if err != nil {
                                    log.Fatalf("Can't get faces: %v", err)
                            }
                            numFaces := len(faces)
                            if numFaces == 1 {
                                    samples = append(samples, faces[0].Descriptor)
                                    cats = append(cats, int32(indexPerson))
                            }
                    }
                    indexPerson++
            }
    }
    rec.SetSamples(samples, cats)

    fmt.Println("list categories:",cats)
    fmt.Println("list labels:",labels)

    fileTests, err := ioutil.ReadDir("../opencv-test-sample/test")
    if err != nil {
            log.Fatal(err)
    }
    for _, fileTest:= range fileTests {
            faces,err:=rec.RecognizeFile("../opencv-test-sample/test/"+fileTest.Name())
            fmt.Println("../opencv-test-sample/test/"+fileTest.Name()+" ",err)
            // for
            for _,f:=range faces {
                    catID := rec.Classify(f.Descriptor)
                    if catID < 0 {
                            log.Fatalf("   ! Can't classify")
                    }else{
                            fmt.Println("  * ",labels[catID])
                    }
            }

    }

    return

}
``

The result is: ``

Load: ../opencv-test-sample/train/Pascal_Praud/photo2.jpg
Load: ../opencv-test-sample/train/Pascal_Praud/photo3.jpg
Load: ../opencv-test-sample/train/Pascal_Praud/photo4.jpg
Load: ../opencv-test-sample/train/alex_lacamoire/img1.jpg
Load: ../opencv-test-sample/train/biden/biden.jpg
Load: ../opencv-test-sample/train/biden/biden2.jpg
Load: ../opencv-test-sample/train/kit_harington/john1.jpeg
Load: ../opencv-test-sample/train/kit_harington/john2.jpeg
Load: ../opencv-test-sample/train/obama/obama.jpg
Load: ../opencv-test-sample/train/obama/obama2.jpg
Load: ../opencv-test-sample/train/rose_leslie/img1.jpg
Load: ../opencv-test-sample/train/rose_leslie/img2.jpg
list categories: [0 0 0 1 2 2 3 3 4 4 5 5]
list labels: [Pascal_Praud alex_lacamoire biden kit_harington obama rose_leslie]
../opencv-test-sample/test/alex_lacamoire1.jpg

  • Pascal_Praud
    ../opencv-test-sample/test/johnsnow_test1.jpg
  • Pascal_Praud
    ../opencv-test-sample/test/kit_with_rose.jpg
  • Pascal_Praud
  • Pascal_Praud
    ../opencv-test-sample/test/obama1.jpg
  • Pascal_Praud
    ../opencv-test-sample/test/obama_and_biden.jpg
  • Pascal_Praud
  • Pascal_Praud
  • Pascal_Praud
    ``

I don't see a issue ? Can you help me ?

OS: Linux unbutu 16.04 and 18.04

Thank you for the quick reply.

I read the code and I found the problem. In fact, I put an image of more than Pascal_Praud and the algorithm
` std::unordered_map<int, std::pair<int, float>> hits_by_cat;
for (int i = 0; i < len; i++) {
int idx = distances[i].first;
float dist = distances[i].second;
auto cat = cats.find(idx);
if (cat == cats.end())
continue;
int cat_idx = cat->second;
auto hit = hits_by_cat.find(cat_idx);
if (hit == hits_by_cat.end()) {
// printf("1 hit for %d (%d: %f)\n", cat_idx, idx, dist);
hits_by_cat[cat_idx] = {1, dist};
} else {
// printf("+1 hit for %d (%d: %f)\n", cat_idx, idx, dist);
hits_by_cat[cat_idx].first++;
}
}

auto hit = std::max_element(
	hits_by_cat.begin(), hits_by_cat.end(),
	[](const auto a, const auto b) {
		auto hits1 = a.second.first;
		auto hits2 = b.second.first;
		auto dist1 = a.second.second;
		auto dist2 = b.second.second;
		if (hits1 == hits2) return dist1 > dist2;
		return hits1 < hits2;
	}
);`

It only works if there is the same number of images in the training. If I do that, it works.

Would you have idea for improvement?

This algorithm tries to improve accuracy by counting number of hits for the same category in top 10 minimal distances. You can implement some modificaton of that method (e.g. choose just the minimal distance between descriptors) or provide more samples so result would be more accurate.

Maybe we should add support to go-face for few other classify algorithms. PR would be great.

Btw, I've tried Yuha's photo you linked with example from readme and it correctly prints Yuha for me.

Yes it great.

I modified classify.cc by :
`
if (hit == hits_by_cat.end()) {
printf("1 hit for %d (%d: %f)\n", cat_idx, idx, dist);
hits_by_cat[cat_idx] = {1, dist};
} else {
printf("+1 hit for %d (%d: %f)\n", cat_idx, idx, dist);
hits_by_cat[cat_idx].first++;
hits_by_cat[cat_idx].second+=dist;
}
}

auto hit = std::max_element(
	hits_by_cat.begin(), hits_by_cat.end(),
	[](const auto a, const auto b) {
		auto hits1 = a.second.first;
		auto hits2 = b.second.first;
		auto dist1 = a.second.second;
		auto dist2 = b.second.second;
		return float(hits1)/dist1 < float(hits2)/dist2;
	}
);

`
It is an average of the number of hits in the distance. But it depends on datasets ;).
I'm looking if I can do a knn classification.

Thanks you