The Wayback Machine - http://web.archive.org/web/20200822004603/https://github.com/justadudewhohacks/face-api.js/issues/231
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

Saving and Loading Descriptors for future use #231

Open
edwinlimlx opened this issue Mar 1, 2019 · 8 comments
Open

Saving and Loading Descriptors for future use #231

edwinlimlx opened this issue Mar 1, 2019 · 8 comments

Comments

@edwinlimlx
Copy link

@edwinlimlx edwinlimlx commented Mar 1, 2019

With ref https://github.com/justadudewhohacks/face-api.js#face-recognition-by-matching-descriptors

I've managed to train the faces and and saving the dataset with JSON.stringify(labelledDescriptors) to a static JSON.

Is there a way to quickly load this dataset, or do I have to load the raw JSON and reinit the dataset with each new faceapi.LabeledFaceDescriptors(name, descriptors)?

Is there method such as

const labelledDescriptors = await faceapi.fetchDescriptors('/files/labeledDescriptors.json');
const faceMatcher = new faceapi.FaceMatcher(labelledDescriptors);

Pardon, if I didn't explain myself well. But the objective is to quickly loaded a saved labeledDescriptors for usage.

@justadudewhohacks
Copy link
Owner

@justadudewhohacks justadudewhohacks commented Mar 1, 2019

I see what you mean, currently there is no way other than what you suggested. The FaceMatcher class could be extended with a toJSON method for serializing and a fromJSON method for deserializing the state. Contributions are highly appreciated. :)

@Bajajar
Copy link
Contributor

@Bajajar Bajajar commented Mar 3, 2019

This is not the bestway but it's working. Set faceMatcher as global variable then you can call faceMatcher.findBestMatch(newdata) to compare new data with your saved dataset.

// Global variable
var faceMatcher;

// Create Face Matcher
async function createFaceMatcher(data) {
  const labeledFaceDescriptors = await Promise.all(data._labeledDescriptors.map(className => {
    const descriptors = [];
    for (var i = 0; i < className._descriptors.length; i++) {
      descriptors.push(className._descriptors[i]);
    }
    return new faceapi.LabeledFaceDescriptors(className._label, descriptors);
  }))
  return new faceapi.FaceMatcher(labeledFaceDescriptors);
}

// Load json to backend
  fs.readFile('demo.json', async function(err, data) {
    if (err) {
      console.log(err);
    }
    var content = JSON.parse(data);
    for (var x = 0; x < content['_labeledDescriptors'].length; x++) {
      for (var y = 0; y < content['_labeledDescriptors'][x]['_descriptors'].length; y++) {
        var results = Object.values(content['_labeledDescriptors'][x]['_descriptors'][y]);
        content._labeledDescriptors[x]._descriptors[y] = new Float32Array(results);
      }
    }
    faceMatcher = await createFaceMatcher(content);
  });
@svfreitas
Copy link

@svfreitas svfreitas commented Mar 26, 2019

I will try to create it, but I am thinking to serialize the resultsRef :
resultsRef = await faceapi.detectAllFaces(referenceImage, faceDetectionOptions)

So we can detect faces in a batch process, store the information in a database (as json) and after recreate the objects from the information stored to run a specific comparation and so on.

@svfreitas
Copy link

@svfreitas svfreitas commented Mar 26, 2019

It is working for the descriptor object.

  • descriptor - OK
  • detection
  • landmarks
  • unshiftedLandMarks
  • alignedRect

code I used to test the serialization to JSon and back

` const jsonStr = JSON.stringify(resultsRef.map(res => res.descriptor ))

fs.writeFileSync('./descriptor.json',jsonStr)
const str = fs.readFileSync('./descriptor.json')

let obj = new Array(Object.values(JSON.parse(str.toString())))

let arrayDescriptor = new Array(obj[0].length)

let i = 0
obj[0].forEach(function(entry) {
arrayDescriptor[i++] = new Float32Array(Object.values(entry))
});

//const faceMatcher = new faceapi.FaceMatcher(resultsRef)
const faceMatcher = new faceapi.FaceMatcher(arrayDescriptor))
`

@jvkassi
Copy link

@jvkassi jvkassi commented May 31, 2019

@Mactacs
Copy link

@Mactacs Mactacs commented Jul 11, 2019

const labeledFaceDescriptors = await loadLabeledImages()
var json_str = "{"parent":" + JSON.stringify(labeledFaceDescriptors) + "}"
// save the json_str to json file

// Load json file and parse
var content = JSON.parse(json_str)

for (var x = 0; x < Object.keys(content.parent).length; x++) {
for (var y = 0; y < Object.keys(content.parent[x]._descriptors).length; y++) {
var results = Object.values(content.parent[x]._descriptors[y]);
content.parent[x]._descriptors[y] = new Float32Array(results);
}
}
const faceMatcher = await createFaceMatcher(content);

function loadLabeledImages() {
const labels = ['Black Widow', 'Captain America', 'Captain Marvel', 'Hawkeye', 'Jim Rhodes', 'Thor', 'Tony Stark']
return Promise.all(
labels.map(async label => {
const descriptions = []
for (let i = 1; i <= 2; i++) {
const img = await faceapi.fetchImage(https://raw.githubusercontent.com/WebDevSimplified/Face-Recognition-JavaScript/master/labeled_images/${label}/${i}.jpg)
const detections = await faceapi.detectSingleFace(img).withFaceLandmarks().withFaceDescriptor()
descriptions.push(detections.descriptor)
}
return new faceapi.LabeledFaceDescriptors(label, descriptions)
})
)
}

// Create Face Matcher
async function createFaceMatcher(data) {
const labeledFaceDescriptors = await Promise.all(data.parent.map(className => {
const descriptors = [];
for (var i = 0; i < className._descriptors.length; i++) {
descriptors.push(className._descriptors[i]);
}
return new faceapi.LabeledFaceDescriptors(className._label, descriptors);
}))
return new faceapi.FaceMatcher(labeledFaceDescriptors);
}

@jderrough
Copy link
Contributor

@jderrough jderrough commented Aug 28, 2019

Check out #397.

I added FaceMatcher.fromJSON() / .fromPOJO() and LabeledFaceDescriptors.fromJSON() / .fromPOJO().

.fromJSON() implementations take a JSON string and return a fully instantiated object.
.fromPOJO() implementations take a Plain Old JavaScript Object and return a fully instantiated object.

@agnoam
Copy link

@agnoam agnoam commented Apr 19, 2020

// Parsing matchers to json
for(let key of Object.keys(updatedFile)) {
      let matcher = updatedFile[key].matcher as FaceMatcher;
      updatedFile[key].matcher = matcher.toJSON();
}
fs.writeFileSync(this.paths.facesMatchers, JSON.stringify(updatedFile));

This code throwing me that exception:

Unhandled Promise rejection: matcher.toJSON is not a function ; Zone: <root> ; Task: Promise.then ; Value: TypeError: matcher.toJSON is not a function

Someone can explain to me why ?

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

Successfully merging a pull request may close this issue.

None yet
8 participants
You can’t perform that action at this time.