Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
be5eedc
fix output
Semyon1104 Sep 6, 2025
6b0d71f
Merge remote-tracking branch 'origin/main' into Semyon1104/BuildGraph…
Semyon1104 Sep 6, 2025
f1446f9
read and connect googlenet
Semyon1104 Sep 9, 2025
fd3a6f3
add MatmulLayer
Semyon1104 Sep 11, 2025
4e5457a
add reshapeLayer
Semyon1104 Sep 11, 2025
fa7e841
add softmaxlayer
Semyon1104 Sep 11, 2025
d83702d
update pooling, not working some tests
Semyon1104 Sep 11, 2025
878f450
fix reduce, tensor, implement ghost constant layer in build.cpp
Semyon1104 Sep 12, 2025
7e057ec
add batchnormalization_layer
Semyon1104 Sep 12, 2025
8778194
fix parser for batch, build densenet
Semyon1104 Sep 12, 2025
ae55576
build yolo ??\
Semyon1104 Sep 13, 2025
bcec666
build yolo and start inference -> 250~
Semyon1104 Sep 17, 2025
58ad832
inference yolo and fix conv
Semyon1104 Sep 18, 2025
b576bc9
build dens,resn, yolo, google/ res&dens - perfect
Semyon1104 Sep 19, 2025
dc3e3e9
fix time-statistics, add imagenet labels
Semyon1104 Sep 21, 2025
ec525fa
fix mul with constant layer for yolo
Semyon1104 Sep 21, 2025
3d74386
fix json for yolo, fix split, check concats
Semyon1104 Sep 22, 2025
22dec95
yolo&google done
Semyon1104 Sep 23, 2025
93bf302
ALL DONE
Semyon1104 Sep 25, 2025
280293b
fix tests
Semyon1104 Sep 27, 2025
411263e
clang
Semyon1104 Sep 27, 2025
47dc937
utf
Semyon1104 Sep 27, 2025
9f73bd9
clang
Semyon1104 Sep 27, 2025
6fa0843
fix cout
Semyon1104 Sep 27, 2025
a03d2ea
add accuracy
Semyon1104 Sep 29, 2025
be65a06
fix add accuracy
Semyon1104 Sep 29, 2025
bca6201
fix flatten and unused vars
Semyon1104 Sep 29, 2025
2810d61
fix flatten tests
Semyon1104 Sep 29, 2025
711feed
linux again
Semyon1104 Sep 29, 2025
87d8ee2
fix unused build.cpp
Semyon1104 Sep 30, 2025
ab2b5a0
fix pooling test
Semyon1104 Sep 30, 2025
228b175
fix parallelism in polling, fix and modify parallelism in convolution
Semyon1104 Sep 30, 2025
d26f375
static analyzis
Semyon1104 Oct 1, 2025
97bae55
codecov
Semyon1104 Oct 1, 2025
d1945b6
Update ci.yml
Semyon1104 Oct 1, 2025
2a49ff5
Update ci.yml
Semyon1104 Oct 1, 2025
5075d25
Merge branch 'main' into Semyon1104/BuildGraph_branching
Semyon1104 Oct 1, 2025
2afdd8d
add conv and flatten tests
Semyon1104 Oct 1, 2025
bf6ff72
codecov
Semyon1104 Oct 1, 2025
789abc6
Update ci.yml
Semyon1104 Oct 2, 2025
634a206
fc conv concat tests
Semyon1104 Oct 2, 2025
3202dc3
Merge branch 'Semyon1104/BuildGraph_branching' of https://github.com/…
Semyon1104 Oct 2, 2025
c06e0cd
conv fc tests
Semyon1104 Oct 2, 2025
349729a
tests
Semyon1104 Oct 3, 2025
d905435
fix batching in reshape for yolo&resnet
Semyon1104 Oct 13, 2025
6639384
fix matmul for batching in yolo
Semyon1104 Oct 14, 2025
ef88c46
fix static analizys
Semyon1104 Oct 14, 2025
e3fdc36
fix ACC* in ci.yml
Semyon1104 Oct 14, 2025
27f89ea
fix txt -> json && name of InputLayer read from json
Semyon1104 Oct 14, 2025
37aa544
fix parser, regex, int64_t in tensor, extra file
Semyon1104 Oct 14, 2025
3d158e7
Delete src/layers/ConсatLayer.cpp
Semyon1104 Oct 14, 2025
cafade8
add tests for softmax && reshape
Semyon1104 Oct 14, 2025
fe890f4
Merge branch 'Semyon1104/BuildGraph_branching' of https://github.com/…
Semyon1104 Oct 14, 2025
2584bd6
tests in && batch, def in Pooling
Semyon1104 Oct 14, 2025
921f2a7
fix json
Semyon1104 Oct 15, 2025
dc7fffe
clean debug
Semyon1104 Oct 18, 2025
2229aa7
clang
Semyon1104 Oct 18, 2025
78c627c
Merge branch 'main' into Semyon1104/BuildGraph_branching
Semyon1104 Oct 18, 2025
fd77a82
fix Layer style as nekit
Semyon1104 Oct 18, 2025
5d60704
clang
Semyon1104 Oct 18, 2025
14c2797
Update README.md
Semyon1104 Oct 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: true
- name: Set binary paths
id: set_binaries
run: |
echo "ACC_BINARY=build/bin/ACC" >> $GITHUB_OUTPUT
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
Expand Down Expand Up @@ -59,7 +63,7 @@ jobs:
with:
name: mnist-${{ matrix.build_type }}${{ matrix.stats && '-stats' || '' }}
path: |
build/bin/ACC_MNIST*
${{ steps.set_binaries.outputs.ACC_BINARY }}
build/bin/opencv_libs/*
build/setenv.sh
- name: Test
Expand Down Expand Up @@ -227,7 +231,10 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set binary path
id: set_eval_binary
run: |
echo "EVAL_BINARY=build/bin/ACC" >> $GITHUB_OUTPUT
- name: Install system dependencies
run: |
sudo apt-get update
Expand Down Expand Up @@ -274,7 +281,7 @@ jobs:

- name: Prepare environment
run: |
chmod +x build/bin/ACC_MNIST*
chmod +x "${{ steps.set_eval_binary.outputs.EVAL_BINARY }}"

export LD_LIBRARY_PATH=$PWD/build/bin/opencv_libs:/usr/lib/x86_64-linux-gnu
echo "Final LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
Expand All @@ -290,12 +297,12 @@ jobs:
export LD_LIBRARY_PATH=$PWD/build/bin/opencv_libs:/usr/lib/x86_64-linux-gnu
echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"

LD_DEBUG=files ./build/bin/ACC_MNIST* 2> ld_debug.log
LD_DEBUG=files "${{ steps.set_eval_binary.outputs.EVAL_BINARY }}" --model alexnet_mnist 2> ld_debug.log
echo "### Library loading debug ###"
grep -i "opencv_imgcodecs" ld_debug.log

./build/bin/ACC_MNIST* > accuracy.txt
echo "Accuracy: $(cat accuracy.txt)"
"${{ steps.set_eval_binary.outputs.EVAL_BINARY }}" > accuracy.txt
echo "Accuracy: $(cat accuracy.txt)"

- name: Update README (master only)
if: github.ref == 'refs/heads/master'
Expand Down
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@

<!--ACCURACY_PLACEHOLDER-->Accuracy: Stat: 98.01% (updated: 2025-04-28)<!--END_ACCURACY-->
## Short description
A lightweight C++ library for performing high-performance inference on MNIST handwritten digits using a modified AlexNet architecture. Designed for efficiency and educational purposes, this project demonstrates how classic CNNs can be optimized for small-scale tasks in native environments.
A lightweight C++ library for performing high-performance inference on MNIST and ImageNet using a modified AlexNet, different ONNX and Yolo architectures. Designed for efficiency and educational purposes, this project demonstrates how classic CNNs can be optimized for small-scale tasks in native environments.
### Key Features:

* C++17 implementation for bare-metal performance

* Simplified AlexNet for 28×28 grayscale images

* Googlenet, Densenet, Resnet and Yolo11x-cls for images of any size

* Parallel computing via Intel OneTBB (Threading Building Blocks)

* Pre-trained model: AlexNet-model.h5 included
* Pre-trained model: AlexNet-model.h5, Googlenet included
## **Some files used to create the library**
### Neural network models
You need to download [Alexnet-model.h5](https://github.com/moizahmed97/Convolutional-Neural-Net-Designer/blob/master/AlexNet-model.h5) to the folder *docs*
Expand All @@ -30,9 +32,9 @@ Other models:</br>

## **How do I launch the inference?**
* Make sure you install the project dependencies by running: *pip install -r requirements.txt*
* You need to run the script *parser.py* that is located in app/AlexNet to read weights from a model *Alexnet-model.h5* and the json file with the weights will be stored in the *docs* folder.
* You need to run the script *parser.py* that is located in app/converters to read weights from a model *Alexnet-model.h5* or *parser_onnx.py* to read weights from a models ONNX or YOLO and the json file with the weights will be stored in the *docs* folder.
* Then put the test images in png format in the folder *docs/input*
* After building the project, which is described below, run Graph_build in folder *build/bin*
* After building the project, which is described below, run Graph_build with the parameter --model (alexnet_mnist or googlenet or densenet or resnet or yolo) and the parameter --parallel if you need. App Graph_build is located in folder *build/bin*

## **Building a Project**
### *Windows*
Expand Down Expand Up @@ -69,7 +71,7 @@ To build and run this project locally on Windows, follow these steps:
```
and run the file
```bash
Graph_Build.exe
Graph_Build.exe --model alexnet_mnist
```
### *Linux/macOS*
To build and run this project locally on Linux or macOS, follow these steps:
Expand Down Expand Up @@ -116,7 +118,7 @@ To build and run this project locally on Windows, follow these steps:
```
and run the file
```bash
./Graph_Build
./Graph_Build --model alexnet_mnist
```

## Test Process
Expand Down Expand Up @@ -147,10 +149,14 @@ To start the testing process locally, you need to go to the directory
./run_test
```

## **Accuracy validation**
## **Accuracy validation for Alexnet on MNIST**
To run accuracy validation you need to use the MNIST dataset, which you can download [here](https://github.com/DeepTrackAI/MNIST_dataset/tree/main/mnist/test) and put it in a folder *docs/mnist/mnist/test*
Now you can run accuracy check - *build\bin\ACC_MNIST.exe*
* **The accuracy should be 98.02%**
Now you can run accuracy check - *build\bin\ACC.exe --model alexnet_mnist*
* **The accuracy should be 98.01%**

## **Accuracy validation for ONNX or YOLO models on ImageNet**
To run accuracy validation you need to use the ImageNet dataset, which you can download [here](https://www.kaggle.com/datasets/sautkin/imagenet1kvalid) and put it in a folder *docs/Imagenet/*
Now you can run accuracy check - *build\bin\ACC.exe --model googlenet*

## **Documentation of project**
https://github.com/embedded-dev-research/ITLabAI/blob/Semyon1104/Final_documentation/docs/IT_Lab_2023.pdf
Expand Down
108 changes: 79 additions & 29 deletions app/Converters/parser_onnx.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
from onnx import helper, numpy_helper
from ultralytics import YOLO


def convert_pt_to_onnx(pt_model_path, onnx_model_path=None):
if onnx_model_path is None:
onnx_model_path = pt_model_path.replace('.pt', '.onnx')

model = YOLO(pt_model_path)
model.export(format="onnx", dynamic=False, simplify=True)
model.export(format="onnx", dynamic=False, simplify=False)

return onnx_model_path


def onnx_to_json(model_path, output_json_path):
if model_path.endswith('.pt'):
model_path = convert_pt_to_onnx(model_path)
Expand All @@ -31,12 +33,40 @@ def onnx_to_json(model_path, output_json_path):
}

layer_info = []

input_info = {}
for input in model.graph.input:
if input.name in initializers_dict:
continue

shape = []
for dim in input.type.tensor_type.shape.dim:
if dim.HasField('dim_value'):
# 0 означает динамическую размерность в ONNX
shape.append(dim.dim_value if dim.dim_value != 0 else -1)
elif dim.HasField('dim_param'):
# Обрабатываем именованные параметры размерностей
shape.append(-1) # или можно сохранить как строку: dim.dim_param
else:
shape.append(-1) # неизвестная размерность

input_info = {
"name": input.name,
"shape": shape,
"data_type": input.type.tensor_type.elem_type
}
break

input_layer = {
"index": 0,
"name": "input_1",
"name": input_info.get("name", "input_1"),
"type": "InputLayer",
"weights": [],
"attributes": {}
"bias": [],
"attributes": {
"shape": input_info.get("shape", []),
"data_type": input_info.get("data_type", 1)
}
}
layer_info.append(input_layer)

Expand All @@ -45,9 +75,14 @@ def onnx_to_json(model_path, output_json_path):
"index": len(layer_info),
"name": node.name.replace('/', '_'),
"type": node.op_type,
"attributes": {}
"attributes": {},
"inputs": []
}

for input_name in node.input:
if input_name not in initializers_dict:
layer_data["inputs"].append(input_name.replace('/', '_'))

for attr in node.attribute:
attr_value = helper.get_attribute_value(attr)
if isinstance(attr_value, TensorProto):
Expand All @@ -67,29 +102,44 @@ def onnx_to_json(model_path, output_json_path):
elif attr.name == "strides":
layer_data["strides"] = attr_value

node_init = []
for input_name in node.input:
if input_name in initializers_dict:
node_init.append(initializers_dict[input_name])

if len(node_init) == 1:
init = node_init[0]
if len(init["dims"]) == 0 or (len(init["dims"]) == 1 and init["dims"][0] == 1):
layer_data["value"] = init["values"] if len(init["dims"]) == 0 else init["values"][0]
else:
layer_data["weights"] = init["values"]
elif len(node_init) > 1:
weights = []
for init in node_init[:-1]:
if len(init["dims"]) > 0:
weights.extend(init["values"]) if isinstance(init["values"][0], list) else weights.append(
init["values"])

if weights:
layer_data["weights"] = weights

if len(node_init[-1]["dims"]) == 1:
layer_data["bias"] = node_init[-1]["values"]
if node.op_type == "BatchNormalization":
bn_params = []
for input_name in node.input:
if input_name in initializers_dict:
bn_params.append(initializers_dict[input_name])

if len(bn_params) >= 4:
layer_data["scale"] = bn_params[0]["values"]
layer_data["bias"] = bn_params[1]["values"]
layer_data["mean"] = bn_params[2]["values"]
layer_data["var"] = bn_params[3]["values"]

layer_data["weights"] = []

else:
node_init = []
for input_name in node.input:
if input_name in initializers_dict:
node_init.append(initializers_dict[input_name])

if len(node_init) == 1:
init = node_init[0]
if len(init["dims"]) == 0 or (len(init["dims"]) == 1 and init["dims"][0] == 1):
layer_data["value"] = init["values"] if len(init["dims"]) == 0 else init["values"][0]
else:
layer_data["weights"] = init["values"]
elif len(node_init) > 1:
weights = []
for init in node_init[:-1]:
if len(init["dims"]) > 0:
weights.extend(init["values"]) if isinstance(init["values"][0], list) else weights.append(
init["values"])

if weights:
layer_data["weights"] = weights

if len(node_init[-1]["dims"]) == 1:
layer_data["bias"] = node_init[-1]["values"]

layer_info.append(layer_data)

Expand All @@ -116,7 +166,7 @@ def default(self, obj):

BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

MODEL_PATH = os.path.join(BASE_DIR, 'docs\\models', 'yolo11x-cls.pt')
MODEL_DATA_PATH = os.path.join(BASE_DIR, 'docs\\jsons', 'yolo11x-cls_onnx_model.json')
MODEL_PATH = os.path.join(BASE_DIR, 'docs\\models', 'resnest101e_Opset16.onnx')
MODEL_DATA_PATH = os.path.join(BASE_DIR, 'docs\\jsons', 'resnest101e_Opset16_onnx_model.json')

onnx_to_json(MODEL_PATH, MODEL_DATA_PATH)
27 changes: 22 additions & 5 deletions app/Graph/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ target_include_directories(BuildGraph PUBLIC ${CMAKE_SOURCE_DIR}/3rdparty/Json/i
add_executable(Graph_Build graph_build.cpp)
target_link_libraries(Graph_Build BuildGraph)

add_executable(ACC_MNIST acc_check_mnist.cpp)
target_link_libraries(ACC_MNIST BuildGraph)
add_executable(ACC acc_check.cpp)
target_link_libraries(ACC BuildGraph)

if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
Expand All @@ -33,24 +33,41 @@ if (WIN32)
endif()

if (WIN32)
add_custom_command(TARGET ACC_MNIST POST_BUILD
if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
set(CMAKE_BUILD_TYPE "Debug")
endif()
if ("${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE")
set(CMAKE_BUILD_TYPE "Release")
endif()
add_custom_command(TARGET ACC POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${OPENCV_BUILD_DIR}/bin/."
"${CMAKE_BINARY_DIR}/bin/")
endif()

file(DOWNLOAD
"https://raw.githubusercontent.com/DeepTrackAI/MNIST_dataset/main/mnist/test/1_000008.png"
"${CMAKE_SOURCE_DIR}/docs/input/test1.png"
"${CMAKE_SOURCE_DIR}/docs/input/28/test1.png"
SHOW_PROGRESS
STATUS status_code
LOG log_file
)

add_definitions(-DIMAGE1_PATH="${CMAKE_SOURCE_DIR}/docs/input/")
file(DOWNLOAD
"blob:https://ru.pinterest.com/63b88674-b4a6-4ef3-85b2-ab57ef7bb8e7"
"${CMAKE_SOURCE_DIR}/docs/input/Imagenet_test/tench.png"
SHOW_PROGRESS
STATUS status_code
LOG log_file
)

add_definitions(-DIMAGE28_PATH="${CMAKE_SOURCE_DIR}/docs/input/28/")
add_definitions(-DIMAGENET_ACC="${CMAKE_SOURCE_DIR}/docs/ImageNet/test/")
add_definitions(-DIMAGENET_PATH="${CMAKE_SOURCE_DIR}/docs/input/Imagenet_test/")
add_definitions(-DMODEL_PATH_H5="${CMAKE_SOURCE_DIR}/docs/jsons/model_data_alexnet_1.json")
add_definitions(-DMODEL_PATH_GOOGLENET_ONNX="${CMAKE_SOURCE_DIR}/docs/jsons/googlenet_onnx_model.json")
add_definitions(-DMODEL_PATH_DENSENET_ONNX="${CMAKE_SOURCE_DIR}/docs/jsons/densenet121_Opset16_onnx_model.json")
add_definitions(-DMODEL_PATH_RESNET_ONNX="${CMAKE_SOURCE_DIR}/docs/jsons/resnest101e_Opset16_onnx_model.json")
add_definitions(-DMODEL_PATH_YOLO11NET_ONNX="${CMAKE_SOURCE_DIR}/docs/jsons/yolo11x-cls_onnx_model.json")
add_definitions(-DIMAGENET_LABELS="${CMAKE_SOURCE_DIR}/docs/imagenet1000_clsidx_to_labels.json")
add_definitions(-DMNIST_PATH="${CMAKE_SOURCE_DIR}/docs/mnist/mnist/test")
Loading
Loading