Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 669
Marc.2377 Avatar asked Sep 26 '22 14:09

Marc.2377


2 Answers

From perusing the sample code and from doing some reading, it looks like your problem is one of two possible problems.

Either the image is not correct. I could not find much more information than the input image not being liked so try a few different input images of different sizes. This is why I ask what does GetImage() output into the test2 var? If that doesn't work properly, then it suggests that your input image isn't liked.

In all the sample code I read, the NFinger instance appears to be added to a subject before any operations is done on the NFinger instance. I'm not sure if this modifies the NFinger instance in some way as the documentation seems to be fairly light. Looking at NSubject.hpp, it suggests that the finger is added to a FingersCollection, but doesn't appear to do much more.

Before the "testing" section, add the finger code to a subject:

NSubject subject;
subject.SetId("Some Unique String");
subject.GetFingers().Add(finger);

Finally, failing this, look into the use of the m_biometricClient variable in the sample code, especially the initialization of it, m_biometricClient.SetFingersReturnProcessedImage(true) looks interesting doesn't it! There's quite a bit of initialisation code which you will see in the FingersSampleForm.cpp. When the finger is added, the client appears to be responsible for enrolling it via a task (see the void FingersSampleForm::OnEnroll) method with the operation of nboEnroll.

like image 200
user3791372 Avatar answered Sep 29 '22 16:09

user3791372


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.

like image 26
Marc.2377 Avatar answered Sep 29 '22 16:09

Marc.2377