-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathinterpolation.cpp
More file actions
105 lines (93 loc) · 4.38 KB
/
interpolation.cpp
File metadata and controls
105 lines (93 loc) · 4.38 KB
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
#include <Arduino.h>
float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y, float f);
void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
float cubicInterpolate(float p[], float x);
float bicubicInterpolate(float p[], float x, float y);
void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols,
float *dest, uint8_t dest_rows, uint8_t dest_cols);
float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y) {
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= cols) x = cols - 1;
if (y >= rows) y = rows - 1;
return p[y * cols + x];
}
void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y, float f) {
if ((x < 0) || (x >= cols)) return;
if ((y < 0) || (y >= rows)) return;
p[y * cols + x] = f;
}
// src is a grid src_rows * src_cols
// dest is a pre-allocated grid, dest_rows*dest_cols
void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols,
float *dest, uint8_t dest_rows, uint8_t dest_cols) {
float mu_x = (src_cols - 1.0) / (dest_cols - 1.0);
float mu_y = (src_rows - 1.0) / (dest_rows - 1.0);
float adj_2d[16]; // matrix for storing adjacents
for (uint8_t y_idx=0; y_idx < dest_rows; y_idx++) {
for (uint8_t x_idx=0; x_idx < dest_cols; x_idx++) {
float x = x_idx * mu_x;
float y = y_idx * mu_y;
//Serial.print("("); Serial.print(y_idx); Serial.print(", "); Serial.print(x_idx); Serial.print(") = ");
//Serial.print("("); Serial.print(y); Serial.print(", "); Serial.print(x); Serial.print(") = ");
get_adjacents_2d(src, adj_2d, src_rows, src_cols, x, y);
/*
Serial.print("[");
for (uint8_t i=0; i<16; i++) {
Serial.print(adj_2d[i]); Serial.print(", ");
}
Serial.println("]");
*/
float frac_x = x - (int)x; // we only need the ~delta~ between the points
float frac_y = y - (int)y; // we only need the ~delta~ between the points
float out = bicubicInterpolate(adj_2d, frac_x, frac_y);
//Serial.print("\tInterp: "); Serial.println(out);
set_point(dest, dest_rows, dest_cols, x_idx, y_idx, out);
}
}
}
// p is a list of 4 points, 2 to the left, 2 to the right
float cubicInterpolate(float p[], float x) {
float r = p[1] + (0.5 * x * (p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0]))));
/*
Serial.print("interpolating: [");
Serial.print(p[0],2); Serial.print(", ");
Serial.print(p[1],2); Serial.print(", ");
Serial.print(p[2],2); Serial.print(", ");
Serial.print(p[3],2); Serial.print("] w/"); Serial.print(x); Serial.print(" = ");
Serial.println(r);
*/
return r;
}
// p is a 16-point 4x4 array of the 2 rows & columns left/right/above/below
float bicubicInterpolate(float p[], float x, float y) {
float arr[4] = {0,0,0,0};
arr[0] = cubicInterpolate(p+0, x);
arr[1] = cubicInterpolate(p+4, x);
arr[2] = cubicInterpolate(p+8, x);
arr[3] = cubicInterpolate(p+12, x);
return cubicInterpolate(arr, y);
}
// src is rows*cols and dest is a 4-point array passed in already allocated!
void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y) {
//Serial.print("("); Serial.print(x); Serial.print(", "); Serial.print(y); Serial.println(")");
// pick two items to the left
dest[0] = get_point(src, rows, cols, x-1, y);
dest[1] = get_point(src, rows, cols, x, y);
// pick two items to the right
dest[2] = get_point(src, rows, cols, x+1, y);
dest[3] = get_point(src, rows, cols, x+2, y);
}
// src is rows*cols and dest is a 16-point array passed in already allocated!
void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y) {
//Serial.print("("); Serial.print(x); Serial.print(", "); Serial.print(y); Serial.println(")");
float arr[4];
for (int8_t delta_y = -1; delta_y < 3; delta_y++) { // -1, 0, 1, 2
float *row = dest + 4 * (delta_y+1); // index into each chunk of 4
for (int8_t delta_x = -1; delta_x < 3; delta_x++) { // -1, 0, 1, 2
row[delta_x+1] = get_point(src, rows, cols, x+delta_x, y+delta_y);
}
}
}