MNIST – Modified National Institute of Standards and Technology is the crucible of a comprehensive computer vision database. Since its release in 1999, MNIST’s classic dataset of handwritten pictures has been accepted as the foundation for benchmarking classification algorithms.
Most of the time, learners start by classifying digits given by MNIST. So, today we will also start by classifying the digits using IDE Software with TensorFlow.
Table of Contents
What you can learn from this tutorial?
- Computer vision fundamentals including simple neural networks
- Classification methods
What is MNIST?
It is a dataset of 60,000 small square 28×28 pixel grayscale images of handwritten single digits within 0 and 9. Since it has been around for more than two decades, various top-performing models are deep learning convolutional neural networks that achieve a classification accuracy of above 99 percent.
How to recognize the hand-drawn numbers in an image?
TensorFlow is an open-source library developed by the Google Brain labs for deep learning research. Since there are already trained models for detecting objects, patterns, and more. It is easy to load the model and give inputs to it to get high results. Because you might need some time to train a new model for your project.
What is the TensorFlow Lite Model?
TensorFlow Lite model has given in a peculiar efficient portable format known as “FlatBuffers”. This TensorFlow Lite model is a collection of tools that enables on-device machine learning by assisting developers to run their models.
You can learn about TensorFlow Lite Model here.
For more posts on this blog about machine learning and TensorFlow click the following dynamic search link: https://blogs.embarcadero.com/?s=tensorflow
How to use TensorFlow with Delphi?
Well, we thanks to our wonderful community of Delphi and C++ developers TensorFlow Lite is available for Delphi right now. Go to the following link to the TensorFlow Lite Model for Delphi repository.
The TFLITE dynamic link library helps you to utilize TensorFlow Lite model functions. It contains common enums, types, and methods used throughout TensorFlow Lite. This includes everything from error codes, to the kernel and delegate APIs.
You can head over and download the entire project to test it. As you can see, you can draw a number and, the TensorFlow gets the data as a 28×28 pixel image which it translates and returns as a number from 0 to 9.
To reproduce the actual images, the input which is 28×28 pixels is flattened into a 1D vector 784 pixels in size. So, each of the 784 pixels delivering up the image is stored as a value within 0 and 255.. This can help to determine the grayscale of the pixel because our images are presented in black and white. A black pixel in the input image is expressed by 255, and a white pixel in the image is described by 0.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
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; // 28x28 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; |
Head on over to the following link to download the example code and try it for yourself: https://github.com/qq33095304/TensorFlow-Lite-Delphi
RAD Studio Delphi is a fast and efficient environment for creating robust applications which work natively on all platforms including Windows, macOS, Linux, iOS and Android. Why not download a free trial today and meet your customer’s needs no matter what device they choose to use?
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition