Skip to content

Commit 886f941

Browse files
committed
Create EX_SIMPLE_IMAGE_STABILIZATION.hpp
1 parent b6afcb6 commit 886f941

File tree

1 file changed

+267
-0
lines changed

1 file changed

+267
-0
lines changed
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
#include <scamp5.hpp>
2+
#include <vector>
3+
#include "MISC/MISC_FUNCS.hpp"
4+
using namespace SCAMP5_PE;
5+
6+
vs_stopwatch frame_timer;
7+
vs_stopwatch output_timer;
8+
vs_stopwatch sum_timer;
9+
10+
const areg_t AREG_image = A;
11+
const areg_t AREG_vertical_edges = B;
12+
const areg_t AREG_horizontal_edges = C;
13+
14+
const dreg_t DREG_keyframe_edges = S0;
15+
const dreg_t DREG_combined_edges = S1;
16+
const dreg_t DREG_vertical_edges = S2;
17+
const dreg_t DREG_horizontal_edges = S3;
18+
19+
void threshold_F_into_S6_for_frame_blending(areg_t reg,vs_handle display, int frame_blend_window = 16);
20+
21+
int main()
22+
{
23+
vs_init();
24+
25+
VS_GUI_DISPLAY_STYLE(style_plot,R"JSON(
26+
{
27+
"plot_palette": "plot_4",
28+
"plot_palette_groups": 4
29+
}
30+
)JSON");
31+
32+
int display_size = 2;
33+
vs_handle display_00 = vs_gui_add_display("Stabilized Image",0,0,display_size);
34+
vs_handle display_01 = vs_gui_add_display("Captured Image",0,display_size,display_size);
35+
36+
int alignment_x = 0; int alignment_y = 0;
37+
int vel_x = 0; int vel_y = 0;
38+
39+
int use_inertia = 1;
40+
vs_gui_add_switch("use_inertia",1,&use_inertia);
41+
42+
bool set_anchor_image = false;
43+
auto gui_btn_set_anchor_image = vs_gui_add_button("set_anchor_image");
44+
vs_on_gui_update(gui_btn_set_anchor_image,[&](int32_t new_value)
45+
{
46+
set_anchor_image = true;
47+
});
48+
49+
int edge_threshold = 12;
50+
vs_gui_add_slider("edge_threshold x",0,127,edge_threshold,&edge_threshold);
51+
52+
53+
// Frame Loop
54+
while(1)
55+
{
56+
frame_timer.reset();//reset frame_timer
57+
58+
vs_disable_frame_trigger();
59+
vs_frame_loop_control();
60+
61+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
62+
//CAPTURE FRAME
63+
64+
scamp5_kernel_begin();
65+
//A = pixel data of latest frame, F = intermediate result
66+
get_image(A,F);
67+
scamp5_kernel_end();
68+
69+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70+
//COMPUTE HORIZONTAL & VERTICAL EDGE IMAGES
71+
72+
scamp5_kernel_begin();
73+
//COPY IMAGE TO F AND SHIFT ONE "PIXEL" RIGHT
74+
bus(NEWS,AREG_image);
75+
bus(F,XW);
76+
bus(NEWS,F);
77+
bus(F,XW);
78+
79+
//SAVE THE ABSOLUTE DIFFERENCE BETWEEN THE SHIFTED IMAGE AND ORIGINAL AS THE VERTICAL EDGES RESULT
80+
sub(F,F,AREG_image);
81+
abs(AREG_vertical_edges,F);
82+
83+
//COPY IMAGE TO F AND SHIFT ONE "PIXEL" UP
84+
bus(NEWS,AREG_image);
85+
bus(F,XS);
86+
bus(NEWS,F);
87+
bus(F,XS);
88+
89+
//SAVE THE ABSOLUTE DIFFERENCE BETWEEN THE SHIFTED IMAGE AND ORIGINAL AS THE HORIZONTAL EDGES RESULT
90+
sub(F,F,AREG_image);
91+
abs(AREG_horizontal_edges,F);
92+
scamp5_kernel_end();
93+
94+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
95+
//THRESHOLD AREG EDGE DATA TO BINARY
96+
97+
scamp5_in(F,edge_threshold);//LOAD THRESHOLD INTO F
98+
99+
scamp5_kernel_begin();
100+
//THRESHOLD AREG_vertical_edges TO BINARY RESULT
101+
sub(E,AREG_vertical_edges,F);
102+
where(E);
103+
//IN PES WHERE AREG_vertical_edges > edge_threshold, FLAG == 1
104+
MOV(DREG_vertical_edges,FLAG);
105+
all();
106+
107+
//THRESHOLD AREG_horizontal_edges TO BINARY RESULT
108+
sub(E,AREG_horizontal_edges,F);
109+
where(E);
110+
//IN PES WHERE AREG_horizontal_edges > edge_threshold, FLAG == 1
111+
MOV(DREG_horizontal_edges,FLAG);
112+
all();
113+
scamp5_kernel_end();
114+
115+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
116+
//COMBINE THRESHOLDED HORIZONTAL & VERTICAL EDGE RESULTS
117+
118+
scamp5_kernel_begin();
119+
MOV(DREG_combined_edges,DREG_vertical_edges);//COPY VERTICAL EDGE RESULT
120+
OR(DREG_combined_edges,DREG_horizontal_edges);//OR WITH HORIZONTAL EDGE RESULT
121+
scamp5_kernel_end();
122+
123+
124+
int position_threshold = 48;
125+
if(abs(alignment_x) > position_threshold || abs(alignment_y) > position_threshold)
126+
{
127+
set_anchor_image = true;
128+
}
129+
if(set_anchor_image)
130+
{
131+
set_anchor_image = false;
132+
alignment_x = 0;
133+
alignment_y = 0;
134+
vel_x = 0;
135+
vel_y = 0;
136+
137+
scamp5_kernel_begin();
138+
MOV(DREG_keyframe_edges,DREG_combined_edges);
139+
scamp5_kernel_end();
140+
}
141+
scamp5_kernel_begin();
142+
REFRESH(DREG_keyframe_edges);
143+
scamp5_kernel_end();
144+
145+
146+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147+
//IMAGE ALIGNMENT
148+
//This code updates the "position" at which the captured image aligns with the stored key-frame
149+
150+
if(use_inertia)
151+
{
152+
alignment_x += vel_x;
153+
alignment_y += vel_y;
154+
}
155+
156+
//Copy the latest edge frame and shift it to the previous position determined to align with the edge key-frame
157+
scamp5_kernel_begin();
158+
MOV(S4,S1);
159+
scamp5_kernel_end();
160+
scamp5_shift(S4,alignment_x,alignment_y);
161+
162+
//The directions to shift and test for better alignment (i.e. noshift,left,right,down,up)
163+
int test_shift_directions[][5] =
164+
{
165+
{0,0},
166+
{1,0},
167+
{-1, 0},
168+
{0,1},
169+
{0, -1},
170+
};
171+
172+
//Array to store the global summations for each tested shift
173+
int direction_global_sums[5];
174+
175+
//Test each shift
176+
for (int n = 0; n < 5; n++)
177+
{
178+
int x = test_shift_directions[n][0];
179+
int y = test_shift_directions[n][1];
180+
181+
//Copy the shifted edge frame & apply the test shift to it
182+
scamp5_kernel_begin();
183+
MOV(S6,S4);
184+
scamp5_kernel_end();
185+
scamp5_shift(S6,x,y);
186+
187+
scamp5_in(F,127);
188+
scamp5_kernel_begin();
189+
bus(D,F);//D = -127
190+
191+
AND(S5,S6,S0);//S5 == 1 where the edges of S6 & DREG_keyframe_edges overlap
192+
WHERE(S5);
193+
mov(D,F);//D = 127 in PEs where the edges of
194+
ALL();
195+
scamp5_kernel_end();
196+
direction_global_sums[n] = scamp5_global_sum_64(D);
197+
}
198+
199+
if(direction_global_sums[0] > direction_global_sums[1] &&
200+
direction_global_sums[0] > direction_global_sums[2] &&
201+
direction_global_sums[0] > direction_global_sums[3] &&
202+
direction_global_sums[0] > direction_global_sums[4])
203+
{
204+
205+
}
206+
else
207+
{
208+
if(direction_global_sums[1] < direction_global_sums[2])
209+
{
210+
alignment_x--;
211+
vel_x--;
212+
}
213+
else
214+
{
215+
alignment_x++;
216+
vel_x++;
217+
}
218+
219+
if(direction_global_sums[3] < direction_global_sums[4])
220+
{
221+
alignment_y--;
222+
vel_y--;
223+
}
224+
else
225+
{
226+
alignment_y++;
227+
vel_y++;
228+
}
229+
}
230+
231+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
232+
//OUTPUT
233+
234+
output_timer.reset();
235+
{
236+
// scamp5_output_image(S6,display_01);
237+
238+
239+
scamp5_kernel_begin();
240+
MOV(S6,S1);
241+
scamp5_kernel_end();
242+
scamp5_shift(S6,alignment_x+1,alignment_y);
243+
scamp5_kernel_begin();
244+
OR(S5,DREG_keyframe_edges,S6);
245+
scamp5_kernel_end();
246+
scamp5_output_image(S6,display_00);
247+
248+
scamp5_output_image(S1,display_01);
249+
250+
251+
252+
// scamp5_output_image(DREG_keyframe_edges,display_02);
253+
}
254+
int image_output_time_microseconds = output_timer.get_usec();//get the time taken for image output
255+
256+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
257+
//OUTPUT TEXT INFO
258+
259+
int frame_time_microseconds = frame_timer.get_usec(); //get the time taken this frame
260+
int max_possible_frame_rate = 1000000/frame_time_microseconds; //calculate the possible max FPS
261+
int image_output_time_percentage = (image_output_time_microseconds*100)/frame_time_microseconds; //calculate the % of frame time which is used for image output
262+
vs_post_text("frame time %d microseconds(%%%d image output), potential FPS ~%d \n",frame_time_microseconds,image_output_time_percentage,max_possible_frame_rate); //display this values on host
263+
}
264+
265+
return 0;
266+
}
267+

0 commit comments

Comments
 (0)