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:
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.
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
.
In order for the image saving to work, one must first:
define an object of type Client::NBiometricClient
call its member function SetFingersReturnProcessedImage()
using the true
as argument
define an object of type NSubject
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
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)
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
call its member function GetSubjects()
and call Add()
on the returned object, using as argument for Add()
the object defined at step 3
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With