Parking Detection

Detect occupied and empty parking spaces from overhead or angled lot images. Ideal for smart parking systems, toll gates, and real-time occupancy dashboards powered by Raspberry Pi or ESP32-CAM.

100 scans/monthView Docs

Get Started in Minutes

Start sending IoT notifications in just a few simple steps

1

Create Account

Sign up for free, no credit card required

2

Get API Key

Generate your API key from the dashboard

3

Upload Lot Image

POST a parking lot photo to /api/v1/parking-detection/detect

4

Get Occupancy

Receive occupied/empty counts and bounding boxes per space

Try API
Test the Parking Detection directly from your browser
API Key:
cd_xxxxxxxxxxxxxxxxxxxx

Parking Lot Image

Upload Image

Upload an image for analysis. Use a clear, well-lit photo for best results.

Click or drag & drop

JPG, PNG up to 5MB

All classes active (default)

40%

Min detection confidence

Result

No result yet

Upload an image and run the test to see the annotated output

1#include "esp_camera.h"
2#include <WiFi.h>
3#include <WiFiClientSecure.h>
4
5const char* WIFI_SSID = "YOUR_WIFI_SSID";
6const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
7const char* API_KEY = "YOUR_API_KEY";
8const char* serverName = "www.circuitdigest.cloud";
9const char* serverPath = "/api/v1/parking-detection/detect";
10const int serverPort = 443;
11
12#define TRIGGER_BTN 13
13unsigned long lastTriggerTime = 0;
14const unsigned long debounceDelay = 500;
15
16#define PWDN_GPIO_NUM 32
17#define RESET_GPIO_NUM -1
18#define XCLK_GPIO_NUM 0
19#define SIOD_GPIO_NUM 26
20#define SIOC_GPIO_NUM 27
21#define Y9_GPIO_NUM 35
22#define Y8_GPIO_NUM 34
23#define Y7_GPIO_NUM 39
24#define Y6_GPIO_NUM 36
25#define Y5_GPIO_NUM 21
26#define Y4_GPIO_NUM 19
27#define Y3_GPIO_NUM 18
28#define Y2_GPIO_NUM 5
29#define VSYNC_GPIO_NUM 25
30#define HREF_GPIO_NUM 23
31#define PCLK_GPIO_NUM 22
32
33WiFiClientSecure client;
34
35void initCamera() {
36  camera_config_t cfg = {};
37  cfg.ledc_channel = LEDC_CHANNEL_0; cfg.ledc_timer = LEDC_TIMER_0;
38  cfg.pin_d0 = Y2_GPIO_NUM; cfg.pin_d1 = Y3_GPIO_NUM;
39  cfg.pin_d2 = Y4_GPIO_NUM; cfg.pin_d3 = Y5_GPIO_NUM;
40  cfg.pin_d4 = Y6_GPIO_NUM; cfg.pin_d5 = Y7_GPIO_NUM;
41  cfg.pin_d6 = Y8_GPIO_NUM; cfg.pin_d7 = Y9_GPIO_NUM;
42  cfg.pin_xclk = XCLK_GPIO_NUM; cfg.pin_pclk = PCLK_GPIO_NUM;
43  cfg.pin_vsync = VSYNC_GPIO_NUM; cfg.pin_href = HREF_GPIO_NUM;
44  cfg.pin_sscb_sda = SIOD_GPIO_NUM; cfg.pin_sscb_scl = SIOC_GPIO_NUM;
45  cfg.pin_pwdn = PWDN_GPIO_NUM; cfg.pin_reset = RESET_GPIO_NUM;
46  cfg.xclk_freq_hz = 20000000;
47  cfg.pixel_format = PIXFORMAT_JPEG;
48  cfg.frame_size = FRAMESIZE_VGA;
49  cfg.jpeg_quality = 10;
50  cfg.fb_count = 1;
51
52  if (esp_camera_init(&cfg) != ESP_OK) {
53    Serial.println("Camera init failed!");
54    while (1) delay(1000);
55  }
56
57  sensor_t* s = esp_camera_sensor_get();
58  s->set_brightness(s, 1);
59  s->set_contrast(s, 1);
60  s->set_saturation(s, 0);
61  s->set_whitebal(s, 1);
62  s->set_exposure_ctrl(s, 1);
63  s->set_gain_ctrl(s, 1);
64  Serial.println("Camera initialized.");
65}
66
67String sendImageToAPI(camera_fb_t* fb) {
68  if (!client.connect(serverName, serverPort)) {
69    return "Connection failed";
70  }
71
72  String boundary = "----ESP32Boundary";
73  String head = "--" + boundary + "
74";
75  head += "Content-Disposition: form-data; name="imageFile"; filename="snap.jpg"
76";
77  head += "Content-Type: image/jpeg
78
79";
80  String tail = "
81--" + boundary + "--
82";
83  int contentLen = head.length() + fb->len + tail.length();
84
85  client.println("POST " + String(serverPath) + " HTTP/1.1");
86  client.println("Host: " + String(serverName));
87  client.println("X-API-Key: " + String(API_KEY));
88  client.println("Content-Type: multipart/form-data; boundary=" + boundary);
89  client.println("Content-Length: " + String(contentLen));
90  client.println("Connection: close");
91  client.println();
92  client.print(head);
93  client.write(fb->buf, fb->len);
94  client.print(tail);
95
96  long timeout = millis();
97  while (client.available() == 0) {
98    if (millis() - timeout > 15000) {
99      client.stop();
100      return "Timeout";
101    }
102  }
103
104  String response = "";
105  while (client.available()) {
106    response += (char)client.read();
107  }
108  client.stop();
109
110  int jsonStart = response.indexOf("
111
112");
113  return (jsonStart != -1) ? response.substring(jsonStart + 4) : response;
114}
115
116void checkParking() {
117  camera_fb_t* fb = esp_camera_fb_get();
118  esp_camera_fb_return(fb);
119  delay(200);
120  fb = esp_camera_fb_get();
121  if (!fb) { Serial.println("Capture failed"); return; }
122  Serial.println("Photo captured! Sending to API...");
123  String result = sendImageToAPI(fb);
124
125  esp_camera_fb_return(fb);
126  Serial.println("Response: " + result);
127
128  // Parse occupied and empty counts
129  int occupiedIdx = result.indexOf(""occupied":");
130  int emptyIdx = result.indexOf(""empty":");
131  int occupiedCount = 0;
132  int emptyCount = 0;
133  if (occupiedIdx != -1) {
134    occupiedCount = result.substring(occupiedIdx + 11, occupiedIdx + 13).toInt();
135  }
136  if (emptyIdx != -1) {
137    emptyCount = result.substring(emptyIdx + 8, emptyIdx + 10).toInt();
138  }
139  Serial.println("Occupied slots: " + String(occupiedCount));
140  Serial.println("Empty slots: " + String(emptyCount));
141
142  if (emptyCount > 0) {
143    Serial.println("Status: Parking available!");
144  } else {
145    Serial.println("Status: Parking FULL!");
146  }
147}
148
149void setup() {
150  Serial.begin(115200);
151  pinMode(TRIGGER_BTN, INPUT_PULLUP);
152  initCamera();
153  WiFi.begin(WIFI_SSID, WIFI_PASS);
154  Serial.print("Connecting to WiFi");
155  while (WiFi.status() != WL_CONNECTED) {
156    delay(500);
157    Serial.print(".");
158  }
159
160  Serial.println("
161Connected: " + WiFi.localIP().toString());
162  client.setInsecure(); // Accept self-signed certs
163}
164
165void loop() {
166  if (digitalRead(TRIGGER_BTN) == LOW) {
167    unsigned long currentTime = millis();
168    if (currentTime - lastTriggerTime > debounceDelay) {
169      lastTriggerTime = currentTime;
170      Serial.println("Button pressed! Capturing image...");
171      checkParking();
172    }
173  }
174}