Timer Camera X で遊ぼう
動画ストリーミングを M5Stack の LCD に表示させる
まずは Timer Camera X に Web カメラのサンプルを書き込みます。
サーバーが起動したら、M5Stack に以下のコードを書き込みます。
loop()
で API エンドポイント /capture
から静止画(JPEG形式)を取得し、バイト配列に変換して M5.Lcd.drawJpg()
に渡します。この処理を繰り返し続けると動画として表示されます。
#include <M5Stack.h>
#include <WiFi.h>
#include <HTTPClient.h>
#define min(a, b) ((a) < (b) ? (a) : (b))
const char* ssid = "***";
const char* password = "***";
const char* url = "http://192.168.11.7/capture";
void setup() {
M5.begin();
M5.Lcd.setBrightness(100);
WiFi.begin(ssid, password);
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK) {
// get the size of the message body
int len = http.getSize();
// create buffer for read
uint8_t buff[len] = { 0 };
// get tcp stream
WiFiClient *stream = http.getStreamPtr();
uint8_t *p = buff;
int size_read = 0;
while (http.connected() && (len > size_read || len == -1)) {
// get available data size
size_t size = stream->available();
if (size) {
// write data to buffer
int c = stream->readBytes(p, min(size, sizeof(buff)));
p += c;
size_read += c;
}
}
M5.Lcd.drawJpg(buff, len);
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
} else {
Serial.println("WiFi connection failed.");
}
}
OpenCV で顔検出を行う
OpenCV の Haar Cascade
を利用しています。
顔検出用の分類器 haarcascade_frontalface_default.xml
は ここ から取得できます。
import cv2
import requests
import numpy as np
url = 'http://192.168.11.7/capture'
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cv2.namedWindow("Camera", cv2.WINDOW_AUTOSIZE)
while True:
r = requests.get(url)
# convert bytes to numpy array
x = np.array(bytearray(r.content), dtype=np.uint8)
# decode image from numpy array
frame = cv2.imdecode(x, cv2.IMREAD_COLOR)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(100, 100),
flags=cv2.CASCADE_SCALE_IMAGE
)
for (x, y, w, h) in faces:
# draw a rectangle around the face
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# display text
cv2.putText(frame, "Face", (int(x), y - int(h / 5)),
cv2.FONT_HERSHEY_PLAIN, int(w / 50),
(0, 255, 0), 3, cv2.LINE_AA)
cv2.imshow('Camera', frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cv2.destroyAllWindows()