Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // TARGET THE DEBUG IMAGE BEFORE RUNNING
- // PRESS ENTER TO TEST
- // PRESS BACK TO RESET
- function BytesToInt32(Bytes: TByteArray; StartIndex: Integer): Integer;
- begin
- Result := (Bytes[StartIndex] shl 24) or (Bytes[StartIndex + 1] shl 16) or
- (Bytes[StartIndex + 2] shl 8) or Bytes[StartIndex + 3];
- end;
- function ParseMNISTFile(FileName: string): array of TSingleMatrix;
- var
- FileData: TByteArray;
- MagicNumber, NumImages, NumRows, NumCols: Integer;
- i, r, c, Offset: Integer;
- begin
- if not FileExists(FileName) then
- begin
- WriteLn('File not found: ', FileName);
- Exit;
- end;
- // Read the entire file into memory
- FileData := FileReadBytes(FileName);
- if Length(FileData) = 0 then
- begin
- WriteLn('Failed to read file or file is empty.');
- Exit;
- end;
- // Parse the header (16 bytes)
- MagicNumber := BytesToInt32(FileData, 0);
- NumImages := BytesToInt32(FileData, 4);
- NumRows := BytesToInt32(FileData, 8);
- NumCols := BytesToInt32(FileData, 12);
- if MagicNumber <> 2051 then
- begin
- WriteLn('Invalid magic number: ', MagicNumber);
- Exit;
- end;
- // Allocate memory for images
- SetLength(Result, NumImages);
- for i := 0 to NumImages - 1 do
- SetLength(Result[i], NumRows, NumCols);
- // Parse image data
- Offset := 16; // Image data starts after the header
- for i := 0 to NumImages - 1 do
- begin
- for r := 0 to NumRows - 1 do
- begin
- for c := 0 to NumCols - 1 do
- begin
- Result[i][r][c] := FileData[Offset];
- Inc(Offset);
- end;
- end;
- end;
- end;
- function ParseMNISTLabels(FileName: string): array of Byte;
- var
- FileData: TByteArray;
- MagicNumber, NumLabels, Offset: Integer;
- i: Integer;
- begin
- if not FileExists(FileName) then
- begin
- WriteLn('File not found: ', FileName);
- Exit;
- end;
- // Read the entire file into memory
- FileData := FileReadBytes(FileName);
- if Length(FileData) = 0 then
- begin
- WriteLn('Failed to read file or file is empty.');
- Exit;
- end;
- // Parse the header (8 bytes)
- MagicNumber := BytesToInt32(FileData, 0);
- NumLabels := BytesToInt32(FileData, 4);
- if MagicNumber <> 2049 then
- begin
- WriteLn('Invalid magic number: ', MagicNumber);
- Exit;
- end;
- // Allocate memory for labels
- SetLength(Result, NumLabels);
- // Parse labels (starting at offset 8)
- Offset := 8;
- for i := 0 to NumLabels - 1 do
- begin
- Result[i] := FileData[Offset];
- Inc(Offset);
- end;
- end;
- function VectorDataBlock(Img: TSingleMatrix): TSingleArray;
- var
- TPA: TPointArray;
- Bounds: TBoxArray;
- i: Int32;
- begin
- SetLength(Result, 16);
- TPA := Img.Indices(128, __GE__);
- Bounds := TPA.Bounds.Partition(4,4);
- for i:=0 to High(Bounds) do
- Result[i] := TPA.ExtractBox(Bounds[i]).Length / ((24*24) / (4*4));
- end;
- function ComputeVectors(Images: array of TSingleMatrix; Labels: TByteArray): TKDItems;
- var
- i: Int32;
- begin
- SetLength(Result, Length(Images));
- for i:=0 to High(Images) do
- begin
- Result[i].Ref := Labels[i];
- Result[i].Vector := VectorDataBlock(Images[i]);//VectorData(Images[i]);
- end;
- end;
- var
- Tree: TKDTree;
- x,y,i,j: Int32;
- Images,TrainImages: array of TSingleMatrix;
- Labels,TrainLabels: array of Byte;
- TrainingData, TestData: TKDItems;
- best,t: Double;
- accuracy,bidx: Int32;
- Raw: TSingleMatrix;
- Test: TSingleArray;
- Half, Temp, Image: TImage;
- begin
- TrainImages := ParseMNISTFile('Scripts\MNIST\train-images.idx3-ubyte');
- TrainLabels := ParseMNISTLabels('Scripts\MNIST\train-labels.idx1-ubyte');
- t := PerformanceTimer();
- TrainingData := ComputeVectors(TrainImages, TrainLabels);
- WriteLn PerformanceTimer() - t;
- WriteLn('Training on ', Length(TrainingData), ' samples');
- t := PerformanceTimer();
- Tree.Init(TrainingData);
- WriteLn PerformanceTimer() - t;
- Image := TImage.Create(700,256);
- DebugImageDisplay(700,256);
- Image.Show();
- Image.DrawColor := $FFFFFF;
- while True do
- begin
- if Target.MousePressed(EMouseButton.LEFT) then
- Image.DrawCircleFilled(Target.MouseXY,10);
- DebugImageUpdate(Image);
- if Target.KeyPressed(EKeyCode.RETURN) then
- begin
- Half := Image.Copy([0,0,255,255]);
- Temp := Half.Downsample(11);
- Temp.SetSize(24,24);
- Temp.ToMatrix();
- Raw.SetSize(24,24);
- for y:=0 to Temp.Height-1 do
- for x:=0 to Temp.Width-1 do
- Raw[y,x] := Temp.Pixel[x,y].ToHSL().L * 2.55;
- Temp.Show();
- Temp.Free();
- Half.Free();
- Test := VectorDataBlock(Raw);
- t := PerformanceTimer();
- bidx := Tree.KNearestClassify(Test, 7);
- Writeln(PerformanceTimer() - t, 'ms');
- Image.FontSize := 12;
- Image.DrawText('Predicted: ', [300, 30]);
- Image.FontSize := 90;
- Image.DrawText(ToStr(bidx), [300, 50]);
- Sleep(1000);
- DebugImageUpdate(Image);
- end;
- if Target.KeyPressed(EKeyCode.BACK) then
- Image.Clear();
- Sleep(10);
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement