Membuat Server Computer Vision Di Laptop + Endpoint Untuk Menerima Foto dari ESP32-CAM
Siap. Kita mulai CV-01: membuat server Computer Vision di laptop yang menerima foto dari ESP32-CAM melalui Wi-Fi.
Untuk tahap ini belum memakai YOLO dan belum memakai database. Kita pastikan dulu jalur paling dasar berhasil:
ESP32-CAM
│
│ HTTP POST /api/v1/vision/upload
│ JPEG
▼
Laptop
│
▼
FastAPI
│
├── validasi gambar
├── simpan JPEG
└── kembalikan JSON
Setelah ini berhasil, kita sambungkan OpenCV.
---
1. Software di laptop
Kita gunakan:
Python
FastAPI
Uvicorn
Pillow
Kalau environment XiaoZhi Anda sebelumnya sudah menggunakan conda, saya sarankan buat environment khusus supaya tidak mengganggu XiaoZhi.
Di Anaconda Prompt:
conda create -n vision python=3.10 -y
conda activate vision
Kemudian:
pip install fastapi uvicorn python-multipart pillow
Cek:
python --version
Harus menunjukkan Python 3.10.x.
---
2. Buat folder project
Misalnya:
C:\smart-incubator\
Buat:
C:\smart-incubator\
│
├── server\
│ └── main.py
│
└── storage\
└── images\
Jadi nanti:
C:\smart-incubator\storage\images
akan menjadi tempat foto dari ESP32-CAM.
---
3. Buat main.py
Buat:
C:\smart-incubator\server\main.py
Isi seluruhnya dengan kode berikut:
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import JSONResponse
from PIL import Image
from datetime import datetime
from pathlib import Path
import io
import uuid
# ============================================================
# SMART INCUBATOR - COMPUTER VISION SERVER V1
# CV-01
# ============================================================
APP_NAME = "Smart Incubator Computer Vision Server"
VERSION = "1.0.0"
# ------------------------------------------------------------
# PATH
# ------------------------------------------------------------
BASE_DIR = Path(__file__).resolve().parent.parent
IMAGE_DIR = BASE_DIR / "storage" / "images"
IMAGE_DIR.mkdir(parents=True, exist_ok=True)
# ------------------------------------------------------------
# FASTAPI
# ------------------------------------------------------------
app = FastAPI(
title=APP_NAME,
version=VERSION,
description="Server penerima gambar dari ESP32-CAM"
)
# ------------------------------------------------------------
# ROOT
# ------------------------------------------------------------
@app.get("/")
def root():
return {
"system": APP_NAME,
"version": VERSION,
"status": "online"
}
# ------------------------------------------------------------
# HEALTH CHECK
# ------------------------------------------------------------
@app.get("/health")
def health():
return {
"status": "ok",
"service": "computer-vision",
"version": VERSION
}
# ------------------------------------------------------------
# UPLOAD IMAGE
# ------------------------------------------------------------
@app.post("/api/v1/vision/upload")
async def upload_image(
file: UploadFile = File(...)
):
# --------------------------------------------------------
# CHECK CONTENT TYPE
# --------------------------------------------------------
allowed_types = [
"image/jpeg",
"image/jpg",
"image/png"
]
if file.content_type not in allowed_types:
raise HTTPException(
status_code=400,
detail=f"Format tidak didukung: {file.content_type}"
)
# --------------------------------------------------------
# READ FILE
# --------------------------------------------------------
data = await file.read()
if not data:
raise HTTPException(
status_code=400,
detail="File gambar kosong"
)
# --------------------------------------------------------
# VALIDATE IMAGE
# --------------------------------------------------------
try:
image = Image.open(io.BytesIO(data))
image.verify()
except Exception:
raise HTTPException(
status_code=400,
detail="File bukan gambar yang valid"
)
# --------------------------------------------------------
# REOPEN IMAGE
# --------------------------------------------------------
image = Image.open(io.BytesIO(data))
# --------------------------------------------------------
# IMAGE INFORMATION
# --------------------------------------------------------
width, height = image.size
# --------------------------------------------------------
# CREATE FILENAME
# --------------------------------------------------------
now = datetime.now()
date_folder = IMAGE_DIR / now.strftime("%Y-%m-%d")
date_folder.mkdir(
parents=True,
exist_ok=True
)
timestamp = now.strftime(
"%Y%m%d_%H%M%S_%f"
)[:-3]
unique_id = uuid.uuid4().hex[:8]
filename = (
f"egg_{timestamp}_{unique_id}.jpg"
)
filepath = date_folder / filename
# --------------------------------------------------------
# SAVE AS JPEG
# --------------------------------------------------------
if image.mode != "RGB":
image = image.convert("RGB")
image.save(
filepath,
format="JPEG",
quality=95
)
# --------------------------------------------------------
# RESPONSE
# --------------------------------------------------------
return JSONResponse(
content={
"status": "success",
"message": "Image received",
"filename": filename,
"path": str(filepath.relative_to(BASE_DIR)),
"width": width,
"height": height,
"size_bytes": len(data),
"timestamp": now.isoformat()
}
)
# ------------------------------------------------------------
# SERVER START MESSAGE
# ------------------------------------------------------------
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
reload=False
)
---
4. Jalankan server
Masuk ke:
cd C:\smart-incubator\server
Pastikan environment:
conda activate vision
Kemudian:
python main.py
Kalau berhasil, kira-kira:
INFO: Started server process
INFO: Uvicorn running on http://0.0.0.0:8000
Jangan tutup jendela ini.
Itulah Computer Vision Server kita.
---
5. Tes dari laptop terlebih dahulu
Buka browser laptop.
Masukkan:
http://127.0.0.1:8000
Harus muncul:
{
"system": "Smart Incubator Computer Vision Server",
"version": "1.0.0",
"status": "online"
}
Kemudian:
http://127.0.0.1:8000/health
Hasil:
{
"status": "ok",
"service": "computer-vision",
"version": "1.0.0"
}
Kalau ini berhasil berarti server hidup.
---
6. Kita punya endpoint khusus ESP32-CAM
Endpoint kita:
POST
/api/v1/vision/upload
Alamat lengkap di jaringan lokal nanti:
http://IP-LAPTOP:8000/api/v1/vision/upload
Misalnya IP laptop:
192.168.1.10
maka:
http://192.168.1.10:8000/api/v1/vision/upload
Jangan gunakan 127.0.0.1 dari ESP32.
Ini penting.
127.0.0.1 berarti perangkat itu sendiri.
Jadi:
Laptop:
127.0.0.1 → laptop
ESP32:
127.0.0.1 → ESP32
ESP32 harus menggunakan IP laptop.
---
7. Cara mengetahui IP laptop
Di Windows:
ipconfig
Cari:
Wireless LAN adapter Wi-Fi
Kemudian:
IPv4 Address
Misalnya:
192.168.1.15
Berarti ESP32 nantinya mengirim ke:
http://192.168.1.15:8000/api/v1/vision/upload
---
8. Tes endpoint menggunakan foto
Sebelum ESP32 kita libatkan, saya sangat menyarankan kita melakukan tes dari laptop.
Misalnya ada:
C:\test\egg.jpg
Di PowerShell:
curl.exe -X POST "http://127.0.0.1:8000/api/v1/vision/upload" -F "file=@C:\test\egg.jpg"
Jika berhasil, server mengembalikan sesuatu seperti:
{
"status": "success",
"message": "Image received",
"filename": "egg_20260905_224501_123_a1b2c3d4.jpg",
"path": "storage\\images\\2026-09-05\\egg_20260905_224501_123_a1b2c3d4.jpg",
"width": 640,
"height": 480,
"size_bytes": 52341,
"timestamp": "2026-09-05T22:45:01.123456"
}
---
9. Foto akan tersimpan otomatis
Strukturnya menjadi:
C:\smart-incubator\
│
├── server\
│ └── main.py
│
└── storage\
└── images\
└── 2026-09-05\
└── egg_20260905_224501_123_a1b2c3d4.jpg
Ini sengaja kita buat berdasarkan tanggal.
Nanti ketika sistem sudah berjalan berhari-hari:
images/
│
├── 2026-09-05/
├── 2026-09-06/
├── 2026-09-07/
├── 2026-09-08/
└── ...
Ini akan sangat berguna untuk histori Computer Vision dan candling.
---
10. Endpoint ini nantinya bukan hanya menerima foto
Saya sengaja membuat fondasi API seperti ini:
/api/v1/
│
└── vision/
│
├── upload
├── count
├── candling
└── analyze
Nanti kita bisa kembangkan menjadi:
POST /api/v1/vision/upload
ESP32 mengirim gambar.
Kemudian:
POST /api/v1/vision/count
untuk meminta penghitung telur.
Dan:
POST /api/v1/vision/candling
untuk analisis candling.
---
11. Arsitektur CV kita mulai terlihat
Sekarang:
ESP32-CAM
│
OV5640
│
JPEG
│
Wi-Fi
│
▼
┌──────────────────┐
│ FASTAPI SERVER │
│ │
│ /vision/upload │
└────────┬─────────┘
│
▼
storage/images
Berikutnya kita tambahkan:
│
▼
OpenCV
│
┌────────┴────────┐
│ │
preprocessing analysis
│
▼
YOLO
│
▼
EGG COUNT
---
12. Kenapa saya ingin OpenCV dulu sebelum YOLO?
Karena kita perlu mengetahui gambar asli dari OV5640.
Sebelum kita menyalahkan model AI, kita harus memastikan:
fokus kamera benar
exposure benar
white balance benar
resolusi benar
pencahayaan cukup
telur tidak blur
posisi kamera benar
gambar tidak terlalu gelap
gambar tidak overexposure
Kalau gambar buruk:
Kamera buruk
↓
YOLO bagus
↓
hasil tetap buruk
Jadi kita akan melakukan:
CV-01 → transfer gambar
CV-02 → OpenCV image viewer
CV-03 → preprocessing
CV-04 → Egg Counter
CV-05 → YOLO
---
Satu hal penting sebelum ESP32 kita sambungkan
Jangan membuka port 8000 ke internet.
Untuk tahap ini server cukup:
ESP32-CAM
│
│ Wi-Fi lokal
▼
Laptop
Tidak perlu port forwarding router.
Dan Windows Firewall mungkin akan meminta izin ketika pertama kali menjalankan server. Izinkan Private networks jika laptop dan ESP32 berada pada jaringan Wi-Fi lokal yang sama.
---
Target CV-01 kita
Kita belum perlu menyentuh XiaoZhi, database, atau AI.
Kita harus mencapai kondisi ini terlebih dahulu:
OV5640
↓
ESP32-CAM
↓
Wi-Fi
↓
Laptop
↓
FastAPI
↓
/api/v1/vision/upload
↓
JPEG tersimpan
Setelah itu baru kita buat CV-02: server membaca foto tersebut dengan OpenCV dan menampilkan gambar + informasi resolusi, brightness, contrast, dan histogram. Itu akan menjadi dasar untuk menentukan setting OV5640 yang optimal sebelum kita memasukkan YOLO.
Post a Comment for "Membuat Server Computer Vision Di Laptop + Endpoint Untuk Menerima Foto dari ESP32-CAM"