Commit 5bc956a5ba88f276098af2245064f59956783e91

Authored by caotto
2 parents ac515819 dc61f619

Merge pull request #336 from biometrics/matlab_ut

Add a simple binary .ut format, add matlab scripts to write to it
openbr/plugins/gallery/binary.cpp
@@ -228,7 +228,41 @@ class utGallery : public BinaryGallery @@ -228,7 +228,41 @@ class utGallery : public BinaryGallery
228 dataSize -= sizeof(uint32_t)*4; 228 dataSize -= sizeof(uint32_t)*4;
229 t.file.set("First_Eye", QPointF(*rightEyeX, *rightEyeY)); 229 t.file.set("First_Eye", QPointF(*rightEyeX, *rightEyeY));
230 t.file.set("Second_Eye", QPointF(*leftEyeX, *leftEyeY)); 230 t.file.set("Second_Eye", QPointF(*leftEyeX, *leftEyeY));
231 - } else { 231 + }
  232 + else if (ut.algorithmID == 7) {
  233 + // binary data consisting of a single channel matrix, of a supported type.
  234 + // 4 element header:
  235 + // uint16 datatype (single channel opencv datatype code)
  236 + // uint32 matrix rows
  237 + // uint32 matrix cols
  238 + // uint16 matrix depth (max 512)
  239 + // Followed by serialized data, in row-major order (in r/c), with depth values
  240 + // for each layer listed in order (i.e. rgb, rgb etc.)
  241 + // #### NOTE! matlab's default order is col-major, so some work should
  242 + // be done on the matlab side to make sure that the initial serialization is correct.
  243 + uint16_t dataType = *reinterpret_cast<uint32_t*>(dataStart);
  244 + dataStart += sizeof(uint16_t);
  245 +
  246 + uint32_t matrixRows = *reinterpret_cast<uint32_t*>(dataStart);
  247 + dataStart += sizeof(uint32_t);
  248 +
  249 + uint32_t matrixCols = *reinterpret_cast<uint32_t*>(dataStart);
  250 + dataStart += sizeof(uint32_t);
  251 +
  252 + uint16_t matrixDepth= *reinterpret_cast<uint16_t*>(dataStart);
  253 + dataStart += sizeof(uint16_t);
  254 +
  255 + // Set metadata
  256 + t.file.set("Label", ut.label);
  257 + t.file.set("X", ut.x);
  258 + t.file.set("Y", ut.y);
  259 + t.file.set("Width", ut.width);
  260 + t.file.set("Height", ut.height);
  261 +
  262 + t.append(cv::Mat(matrixRows, matrixCols, CV_MAKETYPE(dataType, matrixDepth), dataStart).clone() /* We don't want a shallow copy! */);
  263 + return t;
  264 + }
  265 + else {
232 t.file.set("X", ut.x); 266 t.file.set("X", ut.x);
233 t.file.set("Y", ut.y); 267 t.file.set("Y", ut.y);
234 t.file.set("Width", ut.width); 268 t.file.set("Width", ut.width);
scripts/matlab/writeUT.m 0 → 100644
  1 +function writeUT(handle, matrix, imageID, roi_x, roi_y, roi_width, roi_height, label, url)
  2 +% write a single matrix of supported datatype (i.e. not int32) to the file
  3 +% handle in UT format, algorithmID 7
  4 +% inputs: file handle, single layer matrix, imageID (16 char md5 hash, can
  5 +% be empty, in which case we generated a null 16 byte string), roix, roiy,
  6 +% roiw, roih (bounding box of matrix roi), label (class label for training)
  7 +% and url (can be empty)
  8 +%
  9 +% computed values: fvSize, urlSize (url encoded as null-terminated 8-bit
  10 +% string, urlSize includes null terminator), a null terminator will be
  11 +% added to url by this function
  12 +%
  13 +% For performance reasons, handle should be opened in 'W', i.e. buffered
  14 +% mode.
  15 +
  16 +% 512 -- max supported channels in cv::Mat
  17 +if (size(matrix,3) > 512)
  18 + disp('Cannot serialize matrix, 512 is the max depth supported');
  19 + return;
  20 +end
  21 +
  22 +
  23 +% UT format;
  24 +% struct br_universal_template
  25 +% {
  26 +% unsigned char imageID[16]; /*!< MD5 hash of the undecoded origin file. */
  27 +% int32_t algorithmID; /*!< interpretation of _data_ after _urlSize_. */
  28 +% int32_t x; /*!< region of interest horizontal offset (pixels). */
  29 +% int32_t y; /*!< region of interest vertical offset (pixels). */
  30 +% uint32_t width; /*!< region of interest horizontal size (pixels). */
  31 +% uint32_t height; /*!< region of interest vertical size (pixels). */
  32 +% uint32_t label; /*!< supervised training class or manually annotated ground truth. */
  33 +% uint32_t urlSize; /*!< length of null-terminated URL at the beginning of _data_,
  34 +% including the null-terminator character. */
  35 +% uint32_t fvSize; /*!< length of the feature vector after the URL in _data_. */
  36 +% unsigned char data[]; /*!< (_urlSize_ + _fvSize_)-byte buffer.
  37 +% The first _urlSize_ bytes represent the URL.
  38 +% The remaining _fvSize_ bytes represent the feature vector. */
  39 +% };
  40 +
  41 +% algorithm 7 binary data format:
  42 +% uint16 datatype code (copied from opencv, base datatype codes, single
  43 +% channel is assumed)
  44 +% uint32 matrix rows
  45 +% uint32 matrix cols
  46 +% uint16 channel count (max valid is 512)
  47 +% channels->rows->columns
  48 +
  49 +% opencv data type definitions
  50 +% #define CV_8U 0
  51 +% #define CV_8S 1
  52 +% #define CV_16U 2
  53 +% #define CV_16S 3
  54 +% #define CV_32S 4
  55 +% #define CV_32F 5
  56 +% #define CV_64F 6
  57 +% #define CV_USRTYPE1 7
  58 +
  59 +if (numel(imageID) ~= 16)
  60 + imageID = uint8(zeros(16,1));
  61 +end
  62 +
  63 +% fixed for this function
  64 +algorithmID = 7;
  65 +
  66 +% append null terminator
  67 +url = [url, '\0'];
  68 +% calculate complete string length
  69 +urlSize = uint32(length(url));
  70 +
  71 +% figure out datatype code based on the input matrix's data type
  72 +matlab_type = class(matrix(1,1));
  73 +
  74 +type_code = uint32(0);
  75 +% bytes per element
  76 +typeSize = 1;
  77 +
  78 +switch(matlab_type)
  79 + case 'uint8'
  80 + type_code = 0;
  81 + typeSize = 1;
  82 + case 'int8'
  83 + type_code = 1;
  84 + typeSize = 1;
  85 + case 'uint16'
  86 + type_code = 2;
  87 + typeSize = 2;
  88 + case 'int16'
  89 + type_code = 3;
  90 + typeSize = 2;
  91 + case 'uint32'
  92 + disp(' uint32 datatype not supported, please try again');
  93 + return;
  94 + case 'int32'
  95 + type_code = 4;
  96 + typeSize = 4;
  97 +
  98 + case 'single'
  99 + type_code = 5;
  100 + typeSize = 4;
  101 + case 'double'
  102 + type_code = 6;
  103 + typeSize = 8;
  104 + otherwise
  105 + disp(['Unrecognized matlab datatype, ', matlab_type]);
  106 + return;
  107 +end
  108 +
  109 +% total size of feature vecotr in bytes, plus 12 byte header encoding
  110 +% [uint32 datatype, copied from opencv codes; uint32(matrix width);
  111 +% uint32(matrix height)]
  112 +fvSize = uint32(typeSize * numel(matrix) + 4*3);
  113 +
  114 +% imageID
  115 +fwrite(handle, imageID, 'uint8');
  116 +
  117 +% algorithmID
  118 +fwrite(handle, algorithmID, 'int32');
  119 +
  120 +% roi x
  121 +fwrite(handle, roi_x, 'uint32');
  122 +% roi y
  123 +fwrite(handle, roi_y, 'uint32');
  124 +% roi width
  125 +fwrite(handle, roi_width, 'uint32');
  126 +
  127 +% roi height
  128 +fwrite(handle, roi_height, 'uint32');
  129 +
  130 +% label
  131 +fwrite(handle, label, 'uint32');
  132 +
  133 +% url size
  134 +fwrite(handle, urlSize, 'uint32');
  135 +
  136 +% feature vector size
  137 +fwrite(handle, fvSize, 'uint32');
  138 +
  139 +% url (just writing a single null byte)
  140 +fwrite(handle, url, 'uint8');
  141 +
  142 +% binary data header -- datatype code, row count, col count, channel count
  143 +% (max 512). Datatype and channel count are uint16, dimensions are uint32
  144 +fwrite(handle, type_code,'uint16');
  145 +fwrite(handle, uint32(size(matrix,1)), 'uint32');
  146 +fwrite(handle, uint32(size(matrix,2)), 'uint32');
  147 +fwrite(handle, uint16(size(matrix,3)), 'uint16');
  148 +
  149 +% write data, explicit row-major enumeration, matrix(:) is col-major,
  150 +% followed by depth. By permuting the dimensions, we can put the bytes in
  151 +% an appropriate order:
  152 +permuted = permute(matrix,[3,2,1]);
  153 +
  154 +fwrite(handle, permuted(:), matlab_type);
scripts/matlab/writeUTFVectors.m 0 → 100644
  1 +function writeUTFVectors(handle, fvectors)
  2 +% write the rows of fvectors as separate ut format 7 templates. Dummy
  3 +% values will be used for roi settings/imageID/url/etc.
  4 +% handle will not be opened/closed by this function.
  5 +%
  6 +% see also writeUT
  7 +
  8 +dummy_ID = [];
  9 +roi_x = uint32(0);
  10 +roi_y = uint32(0);
  11 +roi_width = uint32(0);
  12 +roi_height = uint32(0);
  13 +label = uint32(0);
  14 +
  15 +urlTotal = '';
  16 +for i = 1:size(fvectors,1)
  17 + writeUT(handle, fvectors(i,:), dummy_ID, roi_x, roi_y, roi_width, roi_height, label, urlTotal);
  18 +end