I'm using an R307 optical sensor, and I need a function in Arduino that can compare the fingerprint I introduce via the sensor with one that I upload from my PC. Later, it should give me a percentage of similarity between them.
In the dataset of the sensor i have this: "ImageBuffer serves for image storage and the image format is 256*288 pixels, form is BMP.
When transferring through UART, to quicken speed, only the upper 4 bits of the pixel is transferred(that is 16 grey degrees). And two adjacent pixels of the same row will form a byte before thetransferring. When uploaded to PC, the 16-grey-degree image will be extended to 256-grey-degree format. That’s 8-bit BMP format.When transferring through USB, the image is 8-bit pixel, that’s 256 grey degrees." but the image that i have in my PC is 113x115.
Does anyone know if there's a function implemented in Arduino that allows me to do this? How do I upload the image from my PC to proceed with the comparison?
It's unlikely that there is a function to do this within the Arduino standard libraries.
You might want to check the R307 library that you are using to see if that specific feature has been implemented.
Which Arduino are you using? Some have limited RAM - an UNO has 2K.
Your PC image at 113x115 pixels (assuming 1 byte per pixel) would require almost 13K of RAM to hold it all in memory.
If you could transfer the image from the PC 1 row at a time and synchronise that with reading the image from the sensor 1 row at a time, then you could cut down on the amount of RAM required.
I am using the Adafruit library in the Arduino IDE with the Arduino Uno. What I am having trouble understanding is how to implement the comparison function between these two datasets.
My issue lies in the fact that the data stored by my optical sensor consists of templates, whereas the fingerprint I have on my PC is an image in .jpg format. As far as I understand, the template and the image formats are not the same, so I am unsure if I can perform the comparison.
I realize that I may need to first convert my image into a format compatible with the template (although I am unsure of what format or how to do this), and then use the compare method.
I've not played with a fingerprint module, but looking at the various commands available, it seems that you need to be able to transfer an image from your PC into one of the CharBuffer areas. Then transfer one of the stored fingerprints into the other CharBuff. Then you can use the Match command to compare them.
The command LoadChar seems to be the one to use to get a stored fingerprint into one CharBuff.
The command DownChar seems to be the one to use to get a fingerprint file from your PC into the other CharBuff.
I would be guessing if I were to try and guide you further.
#include <SoftwareSerial.h>
#include <EEPROM.h>
/* Send a fingerprint image to a PC.
*
* This example should be executed alongside the Python script in the extras folder,
* which will run on the PC to receive and assemble the fingerprint image.
*/
/* pin #2 is Arduino RX <==> Sensor TX
* pin #3 is Arduino TX <==> Sensor RX
*/
SoftwareSerial fserial(2, 3);
FPM finger(&fserial);
FPMSystemParams params;
/* for convenience */
#define PRINTF_BUF_SZ 60
char printfBuf[PRINTF_BUF_SZ];
int eepromAddress = 0;
uint8_t fingerprintImageBytes[] = { };
int imageSize = sizeof(fingerprintImageBytes);
void setup()
{
Serial.begin(57600);
fserial.begin(57600);
Serial.println("IMAGE-TO-PC example");
if (finger.begin()) {
finger.readParams(¶ms);
Serial.println("Found fingerprint sensor!");
Serial.print("Capacity: "); Serial.println(params.capacity);
Serial.print("Packet length: "); Serial.println(FPM::packetLengths[static_cast<uint8_t>(params.packetLen)]);
}
else {
Serial.println("Did not find fingerprint sensor :(");
while (1) yield();
}
// Inicializa la EEPROM
if (!EEPROM.begin()) {
Serial.println("Failed to initialise EEPROM");
return;
}
// Escribe la imagen de la huella dactilar en la EEPROM
for (int i = 0; i < imageSize; i++) {
EEPROM.write(eepromAddress + i, fingerprintImageBytes[i]);
}
}
void loop()
{
//simageToPc();
compareFingerprints();
while (1) yield();
}
void compareFingerprints()
{
FPMStatus status;
uint16_t score;
// Load the fingerprint from the sensor
status = finger.downloadTemplate(1);
if (status != FPMStatus::OK) {
Serial.println("Failed to download fingerprint from sensor");
return;
}
// Load the fingerprint from the PC
status = finger.uploadTemplate(2, 0);
if (status != FPMStatus::OK) {
Serial.println("Failed to upload fingerprint from PC");
return;
}
// Compare the fingerprints
status = finger.matchTemplatePair(&score);
if (status == FPMStatus::OK) {
Serial.print("Fingerprints match with a score of ");
Serial.println(score);
} else {
Serial.println("Fingerprints do not match");
}
}
// uint32_t imageToPc(void)
// {
// FPMStatus status;
// /* Take a snapshot of the finger */
// Serial.println("\r\nPlace a finger.");
// do {
// status = finger.getImage();
// switch (status)
// {
// case FPMStatus::OK:
// Serial.println("Image taken.");
// break;
// case FPMStatus::NOFINGER:
// Serial.println(".");
// break;
// default:
// /* allow retries even when an error happens */
// snprintf(printfBuf, PRINTF_BUF_SZ, "getImage(): error 0x%X", static_cast<uint16_t>(status));
// Serial.println(printfBuf);
// break;
// }
// yield();
// }
// while (status != FPMStatus::OK);
// /* Initiate the image transfer */
// status = finger.downloadImage();
// switch (status)
// {
// case FPMStatus::OK:
// Serial.println("Starting image stream...");
// break;
// default:
// snprintf(printfBuf, PRINTF_BUF_SZ, "downloadImage(): error 0x%X", static_cast<uint16_t>(status));
// Serial.println(printfBuf);
// return 0;
// }
// /* Send some arbitrary signature to the PC, to indicate the start of the image stream */
// Serial.write(0xAA);
// uint32_t totalRead = 0;
// uint16_t readLen = 0;
// /* Now, the sensor will send us the image from its image buffer, one packet at a time.
// * We will stream it directly to Serial. */
// bool readComplete = false;
// while (!readComplete)
// {
// bool ret = finger.readDataPacket(NULL, &Serial, &readLen, &readComplete);
// if (!ret)
// {
// snprintf_P(printfBuf, PRINTF_BUF_SZ, PSTR("readDataPacket(): failed after reading %u bytes"), totalRead);
// Serial.println(printfBuf);
// return 0;
// }
// totalRead += readLen;
// yield();
// }
// Serial.println();
// Serial.print(totalRead); Serial.println(" bytes transferred.");
// return totalRead;
// }
However, I have encountered several problems:
It is impossible to use fopen as in C/C++ in the Arduino IDE.
I dont have any SD keyhole on my PC
I tried the EEPROM option, but the Arduino Uno has only 1kb of memory, and my image is 50kb (and I cannot reduce it to less than 9kb).
Therefore, I am going to try to communicate directly with the sensor or, instead of using Arduino, I will try with the ESP32. I am not sure which of these options is better or easier.