Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 403df88

Browse files
ESP32 camera motion detection example
1 parent eb02981 commit 403df88

File tree

22 files changed

+1018
-303
lines changed

22 files changed

+1018
-303
lines changed

‎.idea/workspace.xml‎

Lines changed: 45 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#define CAMERA_MODEL_M5STACK_WIDE
2+
3+
#include "esp_camera.h"
4+
#include "camera_pins.h"
5+
6+
#define FRAME_SIZE FRAMESIZE_QVGA
7+
#define WIDTH 320
8+
#define HEIGHT 240
9+
#define BLOCK_SIZE 10
10+
#define W (WIDTH / BLOCK_SIZE)
11+
#define H (HEIGHT / BLOCK_SIZE)
12+
#define BLOCK_DIFF_THRESHOLD 0.2
13+
#define IMAGE_DIFF_THRESHOLD 0.1
14+
#define DEBUG 1
15+
16+
17+
uint16_t prev_frame[H][W] = { 0 };
18+
uint16_t current_frame[H][W] = { 0 };
19+
20+
21+
bool setup_camera(framesize_t);
22+
bool capture_still();
23+
bool motion_detect();
24+
void update_frame();
25+
void print_frame(uint16_t frame[H][W]);
26+
27+
28+
/**
29+
*
30+
*/
31+
void setup() {
32+
Serial.begin(115200);
33+
Serial.println(setup_camera(FRAME_SIZE) ? "OK" : "ERR INIT");
34+
}
35+
36+
/**
37+
*
38+
*/
39+
void loop() {
40+
if (!capture_still()) {
41+
Serial.println("Failed capture");
42+
delay(3000);
43+
44+
return;
45+
}
46+
47+
if (motion_detect()) {
48+
Serial.println("Motion detected");
49+
}
50+
51+
update_frame();
52+
Serial.println("=================");
53+
}
54+
55+
56+
/**
57+
*
58+
*/
59+
bool setup_camera(framesize_t frameSize) {
60+
camera_config_t config;
61+
62+
config.ledc_channel = LEDC_CHANNEL_0;
63+
config.ledc_timer = LEDC_TIMER_0;
64+
config.pin_d0 = Y2_GPIO_NUM;
65+
config.pin_d1 = Y3_GPIO_NUM;
66+
config.pin_d2 = Y4_GPIO_NUM;
67+
config.pin_d3 = Y5_GPIO_NUM;
68+
config.pin_d4 = Y6_GPIO_NUM;
69+
config.pin_d5 = Y7_GPIO_NUM;
70+
config.pin_d6 = Y8_GPIO_NUM;
71+
config.pin_d7 = Y9_GPIO_NUM;
72+
config.pin_xclk = XCLK_GPIO_NUM;
73+
config.pin_pclk = PCLK_GPIO_NUM;
74+
config.pin_vsync = VSYNC_GPIO_NUM;
75+
config.pin_href = HREF_GPIO_NUM;
76+
config.pin_sscb_sda = SIOD_GPIO_NUM;
77+
config.pin_sscb_scl = SIOC_GPIO_NUM;
78+
config.pin_pwdn = PWDN_GPIO_NUM;
79+
config.pin_reset = RESET_GPIO_NUM;
80+
config.xclk_freq_hz = 20000000;
81+
config.pixel_format = PIXFORMAT_GRAYSCALE;
82+
config.frame_size = frameSize;
83+
config.jpeg_quality = 12;
84+
config.fb_count = 1;
85+
86+
bool ok = esp_camera_init(&config) == ESP_OK;
87+
88+
sensor_t *sensor = esp_camera_sensor_get();
89+
sensor->set_framesize(sensor, frameSize);
90+
91+
return ok;
92+
}
93+
94+
/**
95+
* Capture image and do down-sampling
96+
*/
97+
bool capture_still() {
98+
camera_fb_t *frame_buffer = esp_camera_fb_get();
99+
100+
if (!frame_buffer)
101+
return false;
102+
103+
// set all 0s in current frame
104+
for (int y = 0; y < H; y++)
105+
for (int x = 0; x < W; x++)
106+
current_frame[y][x] = 0;
107+
108+
109+
// down-sample image in blocks
110+
for (uint32_t i = 0; i < WIDTH * HEIGHT; i++) {
111+
const uint16_t x = i % WIDTH;
112+
const uint16_t y = floor(i / WIDTH);
113+
const uint8_t block_x = floor(x / BLOCK_SIZE);
114+
const uint8_t block_y = floor(y / BLOCK_SIZE);
115+
const uint8_t pixel = frame_buffer->buf[i];
116+
const uint16_t current = current_frame[block_y][block_x];
117+
118+
// average pixels in block (accumulate)
119+
current_frame[block_y][block_x] += pixel;
120+
}
121+
122+
// average pixels in block (rescale)
123+
for (int y = 0; y < H; y++)
124+
for (int x = 0; x < W; x++)
125+
current_frame[y][x] /= BLOCK_SIZE * BLOCK_SIZE;
126+
127+
#if DEBUG
128+
Serial.println("Current frame:");
129+
print_frame(current_frame);
130+
Serial.println("---------------");
131+
#endif
132+
133+
return true;
134+
}
135+
136+
137+
/**
138+
* Compute the number of different blocks
139+
* If there are enough, then motion happened
140+
*/
141+
bool motion_detect() {
142+
uint16_t changes = 0;
143+
const uint16_t blocks = (WIDTH * HEIGHT) / (BLOCK_SIZE * BLOCK_SIZE);
144+
145+
for (int y = 0; y < H; y++) {
146+
for (int x = 0; x < W; x++) {
147+
float current = current_frame[y][x];
148+
float prev = prev_frame[y][x];
149+
float delta = abs(current - prev) / prev;
150+
151+
if (delta >= BLOCK_DIFF_THRESHOLD) {
152+
#if DEBUG
153+
Serial.print("diff\t");
154+
Serial.print(y);
155+
Serial.print('\t');
156+
Serial.println(x);
157+
#endif
158+
159+
changes += 1;
160+
}
161+
}
162+
}
163+
164+
Serial.print("Changed ");
165+
Serial.print(changes);
166+
Serial.print(" out of ");
167+
Serial.println(blocks);
168+
169+
return (1.0 * changes / blocks) > IMAGE_DIFF_THRESHOLD;
170+
}
171+
172+
173+
/**
174+
* Copy current frame to previous
175+
*/
176+
void update_frame() {
177+
for (int y = 0; y < H; y++) {
178+
for (int x = 0; x < W; x++) {
179+
prev_frame[y][x] = current_frame[y][x];
180+
}
181+
}
182+
}
183+
184+
/**
185+
* For serial debugging
186+
* @param frame
187+
*/
188+
void print_frame(uint16_t frame[H][W]) {
189+
for (int y = 0; y < H; y++) {
190+
for (int x = 0; x < W; x++) {
191+
Serial.print(frame[y][x]);
192+
Serial.print('\t');
193+
}
194+
195+
Serial.println();
196+
}
197+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#if defined(CAMERA_MODEL_WROVER_KIT)
2+
#define PWDN_GPIO_NUM -1
3+
#define RESET_GPIO_NUM -1
4+
#define XCLK_GPIO_NUM 21
5+
#define SIOD_GPIO_NUM 26
6+
#define SIOC_GPIO_NUM 27
7+
8+
#define Y9_GPIO_NUM 35
9+
#define Y8_GPIO_NUM 34
10+
#define Y7_GPIO_NUM 39
11+
#define Y6_GPIO_NUM 36
12+
#define Y5_GPIO_NUM 19
13+
#define Y4_GPIO_NUM 18
14+
#define Y3_GPIO_NUM 5
15+
#define Y2_GPIO_NUM 4
16+
#define VSYNC_GPIO_NUM 25
17+
#define HREF_GPIO_NUM 23
18+
#define PCLK_GPIO_NUM 22
19+
20+
#elif defined(CAMERA_MODEL_ESP_EYE)
21+
#define PWDN_GPIO_NUM -1
22+
#define RESET_GPIO_NUM -1
23+
#define XCLK_GPIO_NUM 4
24+
#define SIOD_GPIO_NUM 18
25+
#define SIOC_GPIO_NUM 23
26+
27+
#define Y9_GPIO_NUM 36
28+
#define Y8_GPIO_NUM 37
29+
#define Y7_GPIO_NUM 38
30+
#define Y6_GPIO_NUM 39
31+
#define Y5_GPIO_NUM 35
32+
#define Y4_GPIO_NUM 14
33+
#define Y3_GPIO_NUM 13
34+
#define Y2_GPIO_NUM 34
35+
#define VSYNC_GPIO_NUM 5
36+
#define HREF_GPIO_NUM 27
37+
#define PCLK_GPIO_NUM 25
38+
39+
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
40+
#define PWDN_GPIO_NUM -1
41+
#define RESET_GPIO_NUM 15
42+
#define XCLK_GPIO_NUM 27
43+
#define SIOD_GPIO_NUM 25
44+
#define SIOC_GPIO_NUM 23
45+
46+
#define Y9_GPIO_NUM 19
47+
#define Y8_GPIO_NUM 36
48+
#define Y7_GPIO_NUM 18
49+
#define Y6_GPIO_NUM 39
50+
#define Y5_GPIO_NUM 5
51+
#define Y4_GPIO_NUM 34
52+
#define Y3_GPIO_NUM 35
53+
#define Y2_GPIO_NUM 32
54+
#define VSYNC_GPIO_NUM 22
55+
#define HREF_GPIO_NUM 26
56+
#define PCLK_GPIO_NUM 21
57+
58+
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
59+
#define PWDN_GPIO_NUM -1
60+
#define RESET_GPIO_NUM 15
61+
#define XCLK_GPIO_NUM 27
62+
#define SIOD_GPIO_NUM 22
63+
#define SIOC_GPIO_NUM 23
64+
65+
#define Y9_GPIO_NUM 19
66+
#define Y8_GPIO_NUM 36
67+
#define Y7_GPIO_NUM 18
68+
#define Y6_GPIO_NUM 39
69+
#define Y5_GPIO_NUM 5
70+
#define Y4_GPIO_NUM 34
71+
#define Y3_GPIO_NUM 35
72+
#define Y2_GPIO_NUM 32
73+
#define VSYNC_GPIO_NUM 25
74+
#define HREF_GPIO_NUM 26
75+
#define PCLK_GPIO_NUM 21
76+
77+
#elif defined(CAMERA_MODEL_AI_THINKER)
78+
#define PWDN_GPIO_NUM 32
79+
#define RESET_GPIO_NUM -1
80+
#define XCLK_GPIO_NUM 0
81+
#define SIOD_GPIO_NUM 26
82+
#define SIOC_GPIO_NUM 27
83+
84+
#define Y9_GPIO_NUM 35
85+
#define Y8_GPIO_NUM 34
86+
#define Y7_GPIO_NUM 39
87+
#define Y6_GPIO_NUM 36
88+
#define Y5_GPIO_NUM 21
89+
#define Y4_GPIO_NUM 19
90+
#define Y3_GPIO_NUM 18
91+
#define Y2_GPIO_NUM 5
92+
#define VSYNC_GPIO_NUM 25
93+
#define HREF_GPIO_NUM 23
94+
#define PCLK_GPIO_NUM 22
95+
96+
#else
97+
#error "Camera model not selected"
98+
#endif

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /