Test python result and golang
Closed this issue · 4 comments
Unit tests pass well against I have a lot of problem.
-
I had download this picture for testing dataset.And I had testing this picture: http://images6.fanpop.com/image/photos/40600000/PRISTIN-WE-LIKE-Promotion-Yuha-pristin-40694231-2000-1331.jpg with exemple from README. The result is Roa. I think to the dataset is too poor.
-
I decided to compare goface with the python dataset.
``
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
Try these methods to improve accuracy: https://github.com/Kagami/go-face#how-to-improve-recognition-accuracy
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