Commit f1f3728b72f9d6853b90595eb94b75e9952a430f
Merge branch 'fbi_ebts'
Showing
1 changed file
with
86 additions
and
1 deletions
openbr/plugins/format.cpp
| ... | ... | @@ -16,6 +16,7 @@ |
| 16 | 16 | |
| 17 | 17 | #include <QDate> |
| 18 | 18 | #include <QSize> |
| 19 | +#include <QChar> | |
| 19 | 20 | #ifndef BR_EMBEDDED |
| 20 | 21 | #include <QtXml> |
| 21 | 22 | #endif // BR_EMBEDDED |
| ... | ... | @@ -720,7 +721,7 @@ BR_REGISTER(Format, xmlFormat) |
| 720 | 721 | /*! |
| 721 | 722 | * \ingroup formats |
| 722 | 723 | * \brief Reads in scores or ground truth from a text table. |
| 723 | - * \author Josh Klontz | |
| 724 | + * \author Josh Klontz \cite jklontz | |
| 724 | 725 | * |
| 725 | 726 | * Example of the format: |
| 726 | 727 | * \code |
| ... | ... | @@ -769,6 +770,90 @@ class scoresFormat : public Format |
| 769 | 770 | |
| 770 | 771 | BR_REGISTER(Format, scoresFormat) |
| 771 | 772 | |
| 773 | +/*! | |
| 774 | + * \ingroup formats | |
| 775 | + * \brief Reads FBI EBTS transactions. | |
| 776 | + * \author Scott Klum \cite sklum | |
| 777 | + * https://www.fbibiospecs.org/ebts.html | |
| 778 | + * \note This will fail if a binary blob contains any of the fields attempt to locate within the file | |
| 779 | + */ | |
| 780 | +class ebtsFormat : public Format | |
| 781 | +{ | |
| 782 | + Q_OBJECT | |
| 783 | + | |
| 784 | + QString textFieldValue(const QByteArray &byteArray, const QString &fieldNumber, int from = 0) const | |
| 785 | + { | |
| 786 | + // Find the field, skip the number bytes, and account for the semicolon | |
| 787 | + int fieldPosition = byteArray.indexOf(fieldNumber, from) + fieldNumber.size() + 1; | |
| 788 | + int sepPosition = byteArray.indexOf(QChar(0x1D),fieldPosition); | |
| 789 | + | |
| 790 | + return byteArray.mid(fieldPosition,sepPosition-fieldPosition); | |
| 791 | + } | |
| 792 | + | |
| 793 | + Template read() const | |
| 794 | + { | |
| 795 | + QByteArray byteArray; | |
| 796 | + QtUtils::readFile(file, byteArray); | |
| 797 | + | |
| 798 | + Template t; | |
| 799 | + | |
| 800 | + Mat m; | |
| 801 | + | |
| 802 | + // Demographics | |
| 803 | + { | |
| 804 | + QString name = textFieldValue(byteArray, "2.018"); | |
| 805 | + QStringList names = name.split(','); | |
| 806 | + t.file.set("FIRSTNAME", names.at(1)); | |
| 807 | + t.file.set("LASTNAME", names.at(0)); | |
| 808 | + t.file.set("DOB", textFieldValue(byteArray, "2.022").toInt()); | |
| 809 | + t.file.set("GENDER", textFieldValue(byteArray, "2.024")); | |
| 810 | + t.file.set("RACE", textFieldValue(byteArray, "2.025")); | |
| 811 | + } | |
| 812 | + | |
| 813 | + // Mugshot (first in file used) | |
| 814 | + // Todo: Check for face designation | |
| 815 | + { | |
| 816 | + const QString imageRecord = "10.001:"; | |
| 817 | + const QString imageDataRecord = "10.999:"; | |
| 818 | + | |
| 819 | + int fieldPosition = byteArray.indexOf(imageRecord); | |
| 820 | + | |
| 821 | + if (fieldPosition != -1) { | |
| 822 | + int sepPosition = byteArray.indexOf(QChar(0x1D),fieldPosition); | |
| 823 | + int dataPosition = byteArray.indexOf(imageDataRecord,sepPosition); | |
| 824 | + | |
| 825 | + int recordBytes = byteArray.mid(fieldPosition,sepPosition-fieldPosition).toInt(); | |
| 826 | + int headerBytes = byteArray.mid(fieldPosition,dataPosition-fieldPosition).size() + imageDataRecord.size(); | |
| 827 | + | |
| 828 | + QByteArray data = byteArray.mid(dataPosition+imageRecord.size(),recordBytes-headerBytes); | |
| 829 | + | |
| 830 | + m = imdecode(Mat(3, data.size(), CV_8UC3, data.data()), CV_LOAD_IMAGE_COLOR); | |
| 831 | + if (!m.data) qWarning("ebtsFormat::read failed to decode image data."); | |
| 832 | + t.m() = m; | |
| 833 | + } else qWarning("ebtsFormat::cannot find image data within file."); | |
| 834 | + | |
| 835 | + } | |
| 836 | + | |
| 837 | + if (t.file.contains("DOB")) { | |
| 838 | + const QDate dob = QDate::fromString(t.file.get<QString>("DOB"), "yyyyMMdd"); | |
| 839 | + const QDate current = QDate::currentDate(); | |
| 840 | + int age = current.year() - dob.year(); | |
| 841 | + if (current.month() < dob.month()) age--; | |
| 842 | + t.file.set("Age", age); | |
| 843 | + } | |
| 844 | + | |
| 845 | + return t; | |
| 846 | + } | |
| 847 | + | |
| 848 | + void write(const Template &t) const | |
| 849 | + { | |
| 850 | + (void) t; | |
| 851 | + qFatal("Writing EBTS files is not supported."); | |
| 852 | + } | |
| 853 | +}; | |
| 854 | + | |
| 855 | +BR_REGISTER(Format, ebtsFormat) | |
| 856 | + | |
| 772 | 857 | } // namespace br |
| 773 | 858 | |
| 774 | 859 | #include "format.moc" | ... | ... |