How To Build a Digit Classifier In Tensorflow

procedure TForm1.Button2Click(Sender: TObject);

var

  i, X, Y: DWORD;

 

  fLibrary: HMODULE;

  fModel: Pointer;

  fInterpreterOptions: Pointer;

  fInterpreter: Pointer;

  fStatus: TfLiteStatus;

  fInputTensorCount, fOutputTensorCount, fNumDims: Int32;

  fInputTensor, fOutputTensor: Pointer;

  fInputDims: Integer;

  fTensorName: PAnsiChar;

  fTensorType: TfLiteType;

  fTensorByteSize: SIZE_T;

 

  // 28×28 pixel image as input

  fInput: array [0 .. 28 * 28 1] of Float32;

 

  // output 0 to 9

  fOutput: array [0 .. 10 1] of Float32;

 

  fValue: Extended;

begin

  fLibrary := LoadLibrary(LibraryName);

 

  if fLibrary = 0 then

  begin

    ShowMessage(‘Error: Load tensorflow lite library ‘ + LibraryName + ‘ – ‘ +

      SysErrorMessage(GetLastError));

    Exit;

  end;

 

  try

    fModel := TfLiteModelCreateFromFile(PAnsiChar(AnsiString(Edit1.Text)));

 

    if fModel = nil then

    begin

      ShowMessage(‘Error: Create model from file – ‘ +

        SysErrorMessage(GetLastError));

      Exit;

    end;

 

    fInterpreterOptions := TfLiteInterpreterOptionsCreate;

 

    if fInterpreterOptions > nil then

    begin

      TfLiteInterpreterOptionsSetNumThreads(fInterpreterOptions, 2);

 

      fInterpreter := TfLiteInterpreterCreate(fModel, fInterpreterOptions);

 

      // parameters / model can be removed immediately after the interpreter is created

      TfLiteInterpreterOptionsDelete(fInterpreterOptions);

      TfLiteModelDelete(fModel);

 

      if fInterpreter > nil then

      begin

        fStatus := TfLiteInterpreterAllocateTensors(fInterpreter);

 

        fInputTensorCount := TfLiteInterpreterGetInputTensorCount(fInterpreter);

        fOutputTensorCount := TfLiteInterpreterGetOutputTensorCount

          (fInterpreter);

 

        // fLiteTensor* TfLiteInterpreterGetInputTensor(const TfLiteInterpreter* interpreter, int32_t input_index);

        // returned structure TfLiteTensor

        // an example is simple, there is no need to translate everything from the

        // in general, the source of the: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/c

        { typedef struct TfLiteTensor {

          TfLiteType type;

          TfLitePtrUnion data;

          TfLiteIntArray* dims;

          TfLiteQuantizationParams params;

          TfLiteAllocationType allocation_type;

          size_t bytes;

          const void* allocation;

          const char* name;

          struct TfLiteDelegate* delegate;

          TfLiteBufferHandle buffer_handle;

          bool data_is_stale;

          bool is_variable;

          TfLiteQuantization quantization;

          TfLiteSparsity* sparsity;

          const TfLiteIntArray* dims_signature; }

        fInputTensor := TfLiteInterpreterGetInputTensor(fInterpreter, 0);

        fOutputTensor := TfLiteInterpreterGetOutputTensor(fInterpreter, 0);

 

        if fInputTensor > nil then

        begin

          // info about tensor

          // fNumDims := TfLiteTensorNumDims(fInputTensor);

          // fTensorName := TfLiteTensorName(fInputTensor);

          // fTensorType := TfLiteTensorType(fInputTensor);

          fTensorByteSize := TfLiteTensorByteSize(fInputTensor);

 

          // writing pixels to fInput, top to bottom, left to right

          for Y := 0 to Image1.Picture.Bitmap.Height 1 do

          begin

            for X := 0 to Image1.Picture.Bitmap.Width 1 do

            begin

              if (Image1.Canvas.Pixels[X, Y] > 0) then

                fInput[X + (Y * Image1.Picture.Bitmap.Width)] := 1

              else

                fInput[X + (Y * Image1.Picture.Bitmap.Width)] := 0;

            end;

          end;

 

          // fTensorByteSize = Length(fInput) * SizeOf(Float32)

          fStatus := TfLiteTensorCopyFromBuffer(fInputTensor, @fInput,

            fTensorByteSize);

 

          fStatus := TfLiteInterpreterInvoke(fInterpreter);

 

          if fStatus = kTfLiteOk then

          begin

            for i := 0 to High(fOutput) do

              fOutput[i] := 0;

 

            fOutputTensor := TfLiteInterpreterGetOutputTensor(fInterpreter, 0);

 

            // info about tensor

            // fNumDims := TfLiteTensorNumDims(fOutputTensor);

            // fTensorName := TfLiteTensorName(fOutputTensor);

            // fTensorType := TfLiteTensorType(fOutputTensor);

            fTensorByteSize := TfLiteTensorByteSize(fOutputTensor);

 

            if fOutputTensor > nil then

            begin

              // fTensorByteSize = Length(fOutput) * SizeOf(Float32)

              fStatus := TfLiteTensorCopyToBuffer(fOutputTensor, @fOutput,

                fTensorByteSize);

 

              if fStatus = kTfLiteOk then

              begin

                ListView1.Items.Clear;

 

                for i := 0 to Length(fOutput) 1 do

                begin

                  // ingenious solution, coolest conversion

                  fValue := StrToFloat(Copy(FloatToStr(fOutput[i]), 1, 17));

 

                  if fValue = 1 then

                  begin

                    with ListView1.Items.Add do

                    begin

                      Caption := FloatToStrF(fValue, ffNumber, 17, 17);

                      SubItems.Add(IntToStr(i));

                    end;

                  end;

                end;

 

                ListView1.AlphaSort;

 

                Beep;

              end;

            end;

          end;

        end;

      end;

    end;

  finally

    FreeLibrary(fLibrary);

  end;

end;