Search code examples
c++image-processingfingerprint

Cannot save processed fingerprint image with VeriFinger


I'm trying to use an SDK called VeriFinger, from Neurotechnology, to process a BMP file containing a fingerprint capture (for enhancement), and save it to a new BMP file.

VeriFinger comes with a few tutorials and samples, the main one being called FingersSampleWX.

It looks like this:

FingersSampleWX screenshot

Following this application's source code as a guide, I was able to assemble this piece of code which should do what I want, or so I believe:

#include <iostream>
#include <NLicensing.hpp>
#include <NMedia.hpp>
#include <NBiometrics.hpp>

using namespace Neurotec::Biometrics;
using namespace Neurotec::Images;
using namespace Neurotec::Licensing;

int main()
{
    if (NLicense::ObtainComponents("/local", "5000", "Biometrics.FingerExtraction"))
        std::wcout << L"License OK\n";
    else
        std::wcout << L"License fail\n";

    NFinger finger;
    finger.SetFileName("F:\\input\\000001\\MDT1.BMP");
    finger.SetPosition(nfpUnknown);
    finger.SetImpressionType(nfitNonliveScanPlain);

    // testing
    auto test1 = finger.GetFileName();
    auto test2 = finger.GetImage();
    auto test3 = finger.GetProcessedImage();

    NImage image(NULL);
    if (finger.GetHandle())
    {
        image = finger.GetProcessedImage();

        if (image.GetHandle())
            image.Save("F:\\output\\000001\\MDT1_out.bmp");
    }   
    NLicense::ReleaseComponents("Biometrics.FingerExtraction");
}

However, the image won't save. For some reason, the line if (image.GetHandle()) returns false. That's why I added the testing section.

Checking the value of test2 and test3 using the debugger tells me:

handle=0x00000000 isDisposed=false

GetProcessedImage() returns NULL, which is very weird, because test1 returns the file name of the finger object correctly. I'm sure missing something... Been struggling with this for a few hours now.

VeriFinger is available as a 30-day trial (700MB). The SDK documentation is located in the Documentation folder in both CHM and PDF formats.

Thanks.


Solution

  • In order for the image saving to work, one must first:

    1. define an object of type Client::NBiometricClient

    2. call its member function SetFingersReturnProcessedImage() using the true as argument

    3. define an object of type NSubject

    4. call its member function SetId() which takes an argument of type NStringWrapper - this type has a default constructor for C-style strings (null-terminated char arrays), same as finger.SetFileName() from the example in the question

    5. call another of its member function, GetFingers(), and call Add() on the returned object, using as argument for Add() the object of type NFinger which was defined previously (it's called finger in the question body)

    6. define an object of type NBiometricTask and initialize it with a call to another member function from the object defined at step 1, which is CreateTask() and takes two arguments: nboEnroll (an enum) and NULL

    7. call its member function GetSubjects() and call Add() on the returned object, using as argument for Add() the object defined at step 3

    8. call another member function from the object defined at step 1, this one's PerformTask(), using as argument the object defined at step 6.

    It looks simpler in practice:

    // (previous code from question)
    NFinger finger;
    finger.SetFileName("F:\\input\\000001\\MDT1.BMP");
    finger.SetPosition(nfpUnknown);
    finger.SetImpressionType(nfitNonliveScanPlain);
    
    // Needed initializations:
    Client::NBiometricClient m_biometricClient;
    m_biometricClient.SetFingersReturnProcessedImage(true);
    NBiometricTask task = m_biometricClient.CreateTask(nboEnroll, NULL);
    
    NSubject subject;
    subject.SetId("F:\\input\\000001\\MDT1.BMP");   // I'm just using the filename as argument as its purpose is rather temporary
    subject.GetFingers().Add(finger);
    
    task.GetSubjects().Add(subject);
    m_biometricClient.PerformTask(task);
    // ok, everything should work now
    
    // (...)
    

    Thanks to user3791372 for pointing me in the right direction.