Skip to content

Commit b79af11

Browse files
committed
Data processor defines first layer of sensors
1 parent 067b148 commit b79af11

File tree

7 files changed

+200
-143
lines changed

7 files changed

+200
-143
lines changed

graphics/neurons/data_processor.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef DATA_PROCESSOR_H
2+
#define DATA_PROCESSOR_H
3+
4+
#include <bx/math.h>
5+
6+
7+
class DataProcessor {
8+
virtual bx::Vec3 get_area_size() const = 0;
9+
};
10+
11+
12+
#endif

graphics/neurons/data_processor.hpp

Lines changed: 0 additions & 105 deletions
This file was deleted.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#include "mnist_data_processor.h"
2+
#include "render/neuron_render.hpp"
3+
4+
5+
const size_t input_size = 784;
6+
const uint32_t width = 28, height = 28;
7+
8+
struct MnistImage {
9+
uint8_t label;
10+
uint8_t pixels[input_size];
11+
};
12+
13+
std::vector<MnistImage> load_mnist_bin(const std::string& path) {
14+
std::ifstream in(path, std::ios::binary);
15+
std::vector<MnistImage> images;
16+
MnistImage img;
17+
18+
while (in.read(reinterpret_cast<char*>(&img), sizeof(MnistImage))) {
19+
images.push_back(img);
20+
}
21+
return images;
22+
}
23+
24+
bgfx::TextureHandle create_mnist_texture(const uint8_t* pixels) {
25+
std::vector<uint8_t> rgba(width * height * 4);
26+
27+
for (int i = 0; i < input_size; ++i) {
28+
uint8_t v = pixels[i];
29+
rgba[i * 4 + 0] = v;
30+
rgba[i * 4 + 1] = v;
31+
rgba[i * 4 + 2] = v;
32+
rgba[i * 4 + 3] = 255;
33+
}
34+
35+
const bgfx::Memory* mem = bgfx::copy(rgba.data(), rgba.size());
36+
return bgfx::createTexture2D(width, height, false, 1, bgfx::TextureFormat::RGBA8, 0, mem);
37+
}
38+
39+
void MnistDataProcessor::init() {
40+
images = load_mnist_bin("mnist.bin");
41+
current_image_id = 0;
42+
cached_texture = BGFX_INVALID_HANDLE;
43+
}
44+
45+
size_t MnistDataProcessor::get_input_size() const {
46+
return input_size;
47+
}
48+
49+
bx::Vec3 MnistDataProcessor::get_area_size() const {
50+
return { width, height, 1.0f };
51+
}
52+
53+
size_t MnistDataProcessor::get_max_id() const {
54+
return images.size() - 1;
55+
}
56+
57+
size_t MnistDataProcessor::get_current_id() const {
58+
return current_image_id;
59+
}
60+
61+
uint8_t MnistDataProcessor::get_current_label() const {
62+
return images[current_image_id].label;
63+
}
64+
65+
void MnistDataProcessor::set_current_id(size_t id) {
66+
if (id != current_image_id) {
67+
if (bgfx::isValid(cached_texture)) {
68+
bgfx::destroy(cached_texture);
69+
}
70+
cached_texture = create_mnist_texture(images[id].pixels);
71+
}
72+
current_image_id = id;
73+
}
74+
75+
bgfx::TextureHandle MnistDataProcessor::create_currnet_texture() {
76+
if (!bgfx::isValid(cached_texture)) {
77+
cached_texture = create_mnist_texture(images[current_image_id].pixels);
78+
}
79+
return cached_texture;
80+
}
81+
82+
std::vector<uint8_t> MnistDataProcessor::convert_current_to_inputs() {
83+
std::vector<uint8_t> inputs;
84+
// TODO: wtf is the type for `pixels` to pass to `begin` and `end` ???
85+
inputs.assign(
86+
std::begin(images[current_image_id].pixels),
87+
std::end(images[current_image_id].pixels));
88+
return inputs;
89+
}
90+
91+
std::vector<Neuron> MnistDataProcessor::prepare_neurons() const {
92+
std::vector<Neuron> neurons(input_size);
93+
bx::Vec3 area_size = get_area_size();
94+
95+
for (size_t i = 0; i < input_size; ++i) {
96+
auto ctx = std::make_shared<NeuronVisualContext>(neurons[i]);
97+
ctx->position = {
98+
float(i % int32_t(area_size.x)),
99+
i / area_size.x,
100+
0.0f };
101+
neurons[i].render = std::make_shared<NeuronRenderStrategy>(ctx);
102+
}
103+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef MNIST_DATA_PROCESSOR_H
2+
#define MNIST_DATA_PROCESSOR_H
3+
4+
#include <iostream>
5+
#include <fstream>
6+
#include <string>
7+
#include <vector>
8+
9+
#include <bx/math.h>
10+
#include <bx/uint32_t.h>
11+
#include <bgfx/bgfx.h>
12+
13+
#include "data_processor.h"
14+
#include "neuron.hpp"
15+
16+
struct MnistImage;
17+
18+
class MnistDataProcessor : public DataProcessor {
19+
private:
20+
std::vector<MnistImage> images;
21+
size_t current_image_id;
22+
bgfx::TextureHandle cached_texture;
23+
24+
public:
25+
26+
void init();
27+
28+
size_t get_input_size() const;
29+
bx::Vec3 get_area_size() const override;
30+
size_t get_max_id() const;
31+
size_t get_current_id() const;
32+
uint8_t get_current_label() const;
33+
void set_current_id(size_t id);
34+
bgfx::TextureHandle create_currnet_texture();
35+
std::vector<uint8_t> convert_current_to_inputs();
36+
37+
std::vector<Neuron> prepare_neurons() const;
38+
39+
};
40+
41+
#endif

graphics/neurons/network.hpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010

1111

1212
struct Network {
13-
std::vector<Neuron> neurons;
13+
using NeuronLayer = std::vector<Neuron>;
14+
// std::vector<Neuron> neurons;
15+
std::vector<NeuronLayer> layers;
16+
1417
using Location = uint64_t;
1518
std::unordered_map<Location, Synapse> synapses;
1619
// std::vector<std::vector<Synapse>> synapses;
@@ -21,16 +24,20 @@ struct Network {
2124

2225
explicit Network() = default;
2326

24-
Network(int N) {
25-
setSize(N);
27+
Network() {
28+
// setSize(N);
2629
// Init weights, if desired
2730
}
2831

29-
void setSize(int N) {
30-
neurons.resize(N);
31-
// synapses.resize(N, std::vector<Synapse>(N));
32+
void addLayer(const NeuronLayer&& layer) {
33+
layers.push_back(layer);
3234
}
3335

36+
// void setSize(int N) {
37+
// neurons.resize(N);
38+
// // synapses.resize(N, std::vector<Synapse>(N));
39+
// }
40+
3441
std::vector<float> get_current_voltage_state() const {
3542
std::vector<float> state(neurons.size(), 0.0);
3643
for (size_t i = 0; i < neurons.size(); ++i) {

graphics/neurons/neurons_gui.cpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "render/neuron_render.hpp"
2121
#include "render/network_render.hpp"
2222
#include "simulation_clock.hpp"
23-
#include "data_processor.hpp"
23+
#include "mnist_data_processor.h"
2424

2525
#include "camera.cpp"
2626
#include "mouse.cpp"
@@ -33,8 +33,6 @@
3333
namespace
3434
{
3535

36-
const int32_t width = 28, height = 28;
37-
3836
class SpikingWorld : public entry::AppI
3937
{
4038
public:
@@ -47,10 +45,7 @@ const int32_t width = 28, height = 28;
4745
{
4846
Args args(_argc, _argv);
4947

50-
data.init();
51-
52-
// TODO: data dimensions should come from MnistData
53-
48+
data.init();
5449

5550
m_width = _width;
5651
m_height = _height;
@@ -88,14 +83,18 @@ const int32_t width = 28, height = 28;
8883
auto ctx = std::make_shared<NetworkVisualContext>(net);
8984
net.render = std::make_shared<NetworkRenderStrategy>(ctx);
9085

91-
for (size_t i = 0; i < net.neurons.size(); ++i) {
92-
auto ctx2 = std::make_shared<NeuronVisualContext>(net.neurons[i]);
93-
ctx2->position = {
94-
float(i % width),
95-
float(i / width),
96-
0.0f };
97-
net.neurons[i].render = std::make_shared<NeuronRenderStrategy>(ctx2);
98-
}
86+
87+
net.addLayer(data.prepare_neurons());
88+
// bx::Vec3 area_size = data.get_area_size();
89+
90+
// for (size_t i = 0; i < net.neurons.size(); ++i) {
91+
// auto ctx2 = std::make_shared<NeuronVisualContext>(net.neurons[i]);
92+
// ctx2->position = {
93+
// float(i % int32_t(area_size.x)),
94+
// i / area_size.x,
95+
// 0.0f };
96+
// net.neurons[i].render = std::make_shared<NeuronRenderStrategy>(ctx2);
97+
// }
9998

10099
sim_clock.set_dt(10);
101100
sim_clock.pause();

0 commit comments

Comments
 (0)