環境設定:Arduino IDE 入門ガイドを参照してIDEのインストールを完了し、実際に使用する開発ボードに応じて対応するボードマネージャーと必要なドライバーライブラリをインストールしてください。
使用するドライバーライブラリ:
使用するハードウェア製品:
この接続方法では、事前に使用しているオペレーティングシステムに応じたSR9900ドライバープログラムをダウンロードしてインストールする必要があります。その後、UnitV2をUSB Type-Cインターフェースでパソコンに接続します。UnitV2には有線LANカードが内蔵されているため、パソコンは自動的にネットワークデバイスとして認識し、UnitV2とのネットワーク接続を自動的に確立します。
この接続方法ではドライバープログラムのインストールは必要ありません。UnitV2に電源を供給すると、UnitV2は自動的にWiFiホットスポットを起動します。ホットスポット名はUnitV2-XXXX
(XXXXはデバイスによって異なります)で、パスワードは12345678
です。パソコンやスマートフォンなどのデバイスでこのホットスポットに接続すると、UnitV2とのネットワーク接続を確立できます。
以下のサンプルプログラムはすべてM5Stack公式ファームウェアに対応しており、機能の切り替えとUnitV2から返されるJSONデータの解析を目的としています。公式ファームウェアについてはUnitV2ファームウェア更新ガイドを参照してください。UnitV2のその他の説明についてはこちらをご覧ください。
このサンプルでは UnitV2 をビデオストリーム機能に切り替えることができ、機能ページでカメラ映像をリアルタイムで確認できます。ブラウザでドメイン unitv2.py
または IP:10.254.239.1
にアクセスすると機能ページを表示できます。画面内容は以下の通りです:
ビデオストリーム機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Camera Stream";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);
Serial2.flush();
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') {// clear '\0'
line.remove(0, 1);
}
Serial2.flush();
JSONVar camera_stream_obj = JSON.parse(line);
// JSON.typeof(jsonVar) can be used to get the type of the var
if (!(JSON.typeof(camera_stream_obj) == "undefined")){
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Camera Stream example");
if (camera_stream_obj.hasOwnProperty("msg")) {
Serial.print("msg : ");
Serial.println(String(code_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(code_obj["msg"]).c_str());
}
if (camera_stream_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(code_obj["running"]).c_str());
display.printf(" running: %s\n", String(code_obj["running"]).c_str());
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
} else {
return;
}
}
}
このサンプルプログラムではUnitV2をコード認識機能に切り替えることができ、QRコード、バーコード、DataMatrixコードなどの一般的なコードを認識できます。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
コード認識機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
int code_cnt = 0;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);
// Create initial JSON for configuration
JSONVar obj;
obj["function"] = "Code Detector";
obj["args"] = "";
String jsonString = JSON.stringify(obj); // Convert JSON to string
Serial2.println(jsonString); // Send JSON string to Serial2
Serial2.flush(); // Flush Serial2 buffer
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // Remove non-JSON starting characters
line.remove(0, 1);
}
Serial2.flush();
JSONVar code_obj = JSON.parse(line);
if (!(JSON.typeof(code_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Code Detector example");
// Configuration response
if (code_obj.hasOwnProperty("msg")) {
Serial.print("msg : ");
Serial.println(String(code_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(code_obj["msg"]).c_str());
if (code_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(code_obj["running"]).c_str());
display.printf(" running: %s\n", String(code_obj["running"]).c_str());
}
} else {
if (code_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(code_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(code_obj["running"]).c_str());
}
}
if (code_obj.hasOwnProperty("num")) {
code_cnt = (int)code_obj["num"];
Serial.printf("num = %d\n", code_cnt);
display.printf(" num: %d\n", code_cnt);
}
if (code_obj.hasOwnProperty("code")) {
JSONVar code_arr = code_obj["code"];
for (int i = 0; i < (int)code_cnt; i++) {
display.fillRect(0, 80, 320, 160, TFT_WHITE);
display.setCursor(0, 80);
if (JSON.typeof(code_arr[i]) != "undefined") {
Serial.printf("------[Code %d]------\n", i);
Serial.printf("\tprob: %f\n", (double)code_arr[i]["prob"]);
Serial.printf("\tx: %d\n", (int)code_arr[i]["x"]);
Serial.printf("\ty: %d\n", (int)code_arr[i]["y"]);
Serial.printf("\tw: %d\n", (int)code_arr[i]["w"]);
Serial.printf("\th: %d\n", (int)code_arr[i]["h"]);
Serial.printf("\ttype: %s\n", (const char*)code_arr[i]["type"]);
Serial.printf("\tcontent: %s\n", (const char*)code_arr[i]["content"]);
display.printf("Code %d:\n", i);
display.printf(" prob: %.3f\n", (double)code_arr[i]["prob"]);
display.printf(" x: %d, y: %d\n", (int)code_arr[i]["x"], (int)code_arr[i]["y"]);
display.printf(" w: %d, h: %d\n", (int)code_arr[i]["w"], (int)code_arr[i]["h"]);
display.printf(" type: %s\n", (const char*)code_arr[i]["type"]);
display.printf(" content: %s\n\n", (const char*)code_arr[i]["content"]);
}
delay(200);
}
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
下図左側のQRコードをスキャンすると、右側の図のような認識結果が表示されます。
このサンプルプログラムではUnitV2を物体認識機能に切り替えることができます。出荷時のファームウェアにはnanodet_80class
とyolo_20classs
のモデルがデフォルトで内蔵されており、すぐに使用できます。カスタムモデルを学習させたい場合は、ガイドUnitV2 V-Trainingを参照してください。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
物体認識機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
int obj_cnt = 0;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Object Recognition";
obj["args"][0] = "yolo_20class"; // yolo_20class or nanodet_80class
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);
Serial2.flush();
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // clear '\0'
line.remove(0, 1);
}
Serial2.flush();
JSONVar rec_obj = JSON.parse(line);
if (!(JSON.typeof(rec_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Object Recognition example");
if (rec_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println((const char*) rec_obj["msg"]);
display.setCursor(0, 35);
display.printf(" msg: %s\n", (const char*) rec_obj["msg"]);
if (rec_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(rec_obj["running"]).c_str());
display.printf(" running: %s\n", String(rec_obj["running"]).c_str());
}
} else {
if (rec_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(rec_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(rec_obj["running"]).c_str());
}
}
if (rec_obj.hasOwnProperty("num")) {
obj_cnt = (int)rec_obj["num"];
Serial.printf("num = %d\n", obj_cnt);
display.printf(" num: %d\n", obj_cnt);
}
if (rec_obj.hasOwnProperty("obj")) {
JSONVar obj_arr = rec_obj["obj"];
for (int i = 0; i < (int)obj_cnt; i++) {
display.fillRect(0, 80, 320, 160, TFT_WHITE);
display.setCursor(0, 80);
if (JSON.typeof(obj_arr[i]) != "undefined") {
Serial.printf("------[obj %d]------\n", i);
Serial.printf("\tprob: %f\n", (double)obj_arr[i]["prob"]);
Serial.printf("\tx: %d\n", (int)obj_arr[i]["x"]);
Serial.printf("\ty: %d\n", (int)obj_arr[i]["y"]);
Serial.printf("\tw: %d\n", (int)obj_arr[i]["w"]);
Serial.printf("\th: %d\n", (int)obj_arr[i]["h"]);
Serial.printf("\ttype: %s\n", (const char*)obj_arr[i]["type"]);
display.printf("obj %d:\n", i);
display.printf(" prob: %.3f\n", (double)obj_arr[i]["prob"]);
display.printf(" x: %d, y: %d\n", (int)obj_arr[i]["x"], (int)obj_arr[i]["y"]);
display.printf(" w: %d, h: %d\n", (int)obj_arr[i]["w"], (int)obj_arr[i]["h"]);
display.printf(" type: %s\n\n", (const char*)obj_arr[i]["type"]);
}
delay(200);
}
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
下図左側の画像をスキャンすると、右側の図のような認識結果が表示されます。
このサンプルプログラムではUnitV2を色追跡機能に切り替えることができます。色追跡機能を使用するには、UnitV2に電源を供給した後、追跡する色のパラメータを設定する必要があります。色パラメータの設定方法は2通りあります。1つは機能ページで画面をクリックして追跡する色を範囲選択する方法(操作方法は下図参照)、または左側のL、A、Bの値を入力した後「update」ボタンをクリックして設定する方法です。
もう1つは以下のコード内のJSON形式で設定する方法で、ROI(関心領域)を範囲選択して自動的にLAB色値を分析して設定することも、直接LAB色値を設定することもできます。以下のコードではデフォルトでROI方式を使用して設定しています。LAB方式で設定したい場合は、コード内の#define USING_LAB
のコメントを解除し、以下に示すコード部分にLAB色値を入力してください。
LAB["l_min"] = 0;
LAB["l_max"] = 255;
LAB["a_min"] = 179;
LAB["a_max"] = 201;
LAB["b_min"] = 162;
LAB["b_max"] = 184;
ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
色追跡機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
// このマクロ定義を有効にするとLAB方式を使用します。無効の場合はデフォルトでROI方式を使用します。
// #define USING_LAB
M5GFX display;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Color Tracker";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);
Serial2.flush();
delay(200);
#if defined(USING_LAB)
JSONVar LAB;
LAB["config"] = "Color Tracker";
LAB["l_min"] = 0;
LAB["l_max"] = 255;
LAB["a_min"] = 179;
LAB["a_max"] = 201;
LAB["b_min"] = 162;
LAB["b_max"] = 184;
jsonString = JSON.stringify(LAB);
#else
JSONVar ROI;
ROI["config"] = "Color Tracker";
ROI["x"] = 160;
ROI["y"] = 120;
ROI["w"] = 320;
ROI["h"] = 240;
jsonString = JSON.stringify(ROI);
#endif
Serial2.println(jsonString);
Serial2.flush();
delay(200);
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // clear '\0'
line.remove(0, 1);
}
Serial2.flush();
JSONVar color_obj = JSON.parse(line);
if (!(JSON.typeof(color_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Color Tracker example");
if (color_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println(String(color_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(color_obj["msg"]).c_str());
if (color_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(color_obj["running"]).c_str());
display.printf(" running: %s\n", String(color_obj["running"]).c_str());
}
} else {
if (color_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(color_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(color_obj["running"]).c_str());
}
// ROI設定のレスポンス
if (color_obj.hasOwnProperty("a_cal")) {
double a_cal = (double)color_obj["a_cal"];
double b_cal = (double)color_obj["b_cal"];
double va = (double)color_obj["va"];
double vb = (double)color_obj["vb"];
int l_min = (int)color_obj["l_min"];
int l_max = (int)color_obj["l_max"];
int a_min = (int)color_obj["a_min"];
int a_max = (int)color_obj["a_max"];
int b_min = (int)color_obj["b_min"];
int b_max = (int)color_obj["b_max"];
Serial.printf("a_cal = %f\n", a_cal);
Serial.printf("b_cal = %f\n", b_cal);
Serial.printf("va = %f\n", va);
Serial.printf("vb = %f\n", vb);
Serial.printf("l_min = %d\nl_max = %d\n", l_min, l_max);
Serial.printf("a_min = %d\na_max = %d\nb_min = %d\nb_max = %d\n",
a_min, a_max, b_min, b_max);
display.printf(" a_cal: %f\n", a_cal);
display.printf(" b_cal: %f\n", b_cal);
display.printf(" va: %f\n", va);
display.printf(" vb: %f\n", vb);
display.printf(" l_min: %d\n", l_min);
display.printf(" l_max: %d\n", l_max);
display.printf(" a_min: %d\n", a_min);
display.printf(" a_max: %d\n", a_max);
display.printf(" b_min: %d\n", b_min);
display.printf(" b_max: %d\n", b_max);
delay(2000);
}
}
if (color_obj.hasOwnProperty("cx")) {
int cx = (int)color_obj["cx"];
int cy = (int)color_obj["cy"];
int r = (int)color_obj["r"];
int mx = (int)color_obj["mx"];
int my = (int)color_obj["my"];
Serial.printf("cx = %d\n", cx);
Serial.printf("cy = %d\n", cy);
Serial.printf("r = %d\n", r);
Serial.printf("mx = %d\n", mx);
Serial.printf("my = %d\n", my);
display.setCursor(0, 60);
display.printf(" cx = %d\n", cx);
display.printf(" cy = %d\n", cy);
display.printf(" r = %d\n", r);
display.printf(" mx = %d\n", mx);
display.printf(" my = %d\n", my);
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
サンプルプログラムが正常に実行されると、ホストボードは追跡している色のブロックの中心点の位置、サイズなどのデータをリアルタイムで表示・出力します。検出結果は以下の図の通りです:
このサンプルプログラムではUnitV2をレーンライン追跡機能に切り替えることができます。色追跡機能と同様に、UnitV2に電源を供給した後、色パラメータを設定する必要があります。色パラメータの設定方法は上記の色追跡を参照してください。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
以下のコードではデフォルトでROI方式を使用して設定しています。LAB方式で設定したい場合は、コード内の#define USING_LAB
のコメントを解除し、以下に示すコード部分にLAB色値を入力してください。
LAB["l_min"] = 0;
LAB["l_max"] = 255;
LAB["a_min"] = 176;
LAB["a_max"] = 198;
LAB["b_min"] = 155;
LAB["b_max"] = 175;
レーンライン追跡機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
// このマクロ定義を有効にするとLAB方式を使用します。無効の場合はデフォルトでROI方式を使用します。
// #define USING_LAB
M5GFX display;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Lane Line Tracker";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);
Serial2.flush();
delay(200);
#if defined(USING_LAB)
JSONVar LAB;
LAB["config"] = "Lane Line Tracker";
LAB["l_min"] = 0;
LAB["l_max"] = 255;
LAB["a_min"] = 176;
LAB["a_max"] = 198;
LAB["b_min"] = 155;
LAB["b_max"] = 175;
jsonString = JSON.stringify(LAB);
#else
JSONVar ROI;
ROI["config"] = "Lane Line Tracker";
ROI["x"] = 160;
ROI["y"] = 120;
ROI["w"] = 320;
ROI["h"] = 240;
jsonString = JSON.stringify(ROI);
#endif
Serial2.println(jsonString);
Serial2.flush();
delay(200);
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // clear '\0'
line.remove(0, 1);
}
Serial2.flush();
JSONVar line_obj = JSON.parse(line);
if (!(JSON.typeof(line_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Lane Line Tracker example");
if (line_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println(String(line_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(line_obj["msg"]).c_str());
if (line_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(line_obj["running"]).c_str());
display.printf(" running: %s\n", String(line_obj["running"]).c_str());
}
} else {
if (line_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(line_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(line_obj["running"]).c_str());
}
// ROI設定のレスポンス
if (line_obj.hasOwnProperty("a_cal")) {
double a_cal = (double)line_obj["a_cal"];
double b_cal = (double)line_obj["b_cal"];
double va = (double)line_obj["va"];
double vb = (double)line_obj["vb"];
int l_min = (int)line_obj["l_min"];
int l_max = (int)line_obj["l_max"];
int a_min = (int)line_obj["a_min"];
int a_max = (int)line_obj["a_max"];
int b_min = (int)line_obj["b_min"];
int b_max = (int)line_obj["b_max"];
Serial.printf("a_cal = %f\n", a_cal);
Serial.printf("b_cal = %f\n", b_cal);
Serial.printf("va = %f\n", va);
Serial.printf("vb = %f\n", vb);
Serial.printf("l_min = %d\nl_max = %d\n", l_min, l_max);
Serial.printf("a_min = %d\na_max = %d\nb_min = %d\nb_max = %d\n",
a_min, a_max, b_min, b_max);
display.printf(" a_cal: %f\n", a_cal);
display.printf(" b_cal: %f\n", b_cal);
display.printf(" va: %f\n", va);
display.printf(" vb: %f\n", vb);
display.printf(" l_min: %d\n", l_min);
display.printf(" l_max: %d\n", l_max);
display.printf(" a_min: %d\n", a_min);
display.printf(" a_max: %d\n", a_max);
display.printf(" b_min: %d\n", b_min);
display.printf(" b_max: %d\n", b_max);
delay(2000);
}
}
if (line_obj.hasOwnProperty("x")) {
int x = (int)line_obj["x"];
int y = (int)line_obj["y"];
double k = (double)line_obj["k"];
Serial.printf("x = %d\n", x);
Serial.printf("y = %d\n", y);
Serial.printf("k = %f\n", k);
display.setCursor(0, 60);
display.printf(" x = %d\n", x);
display.printf(" y = %d\n", y);
display.printf(" k = %f\n", k);
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
下図左側の画像をスキャンすると、右側の図のような認識結果が表示されます。
このサンプルプログラムではUnitV2をターゲット追跡機能に切り替えることができます。UnitV2に電源を供給した後、カメラの現在の映像からターゲット物体の情報を取得してから使用する必要があります。機能ページで範囲選択することができ(ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスして機能ページを開く)、以下のコードのパラメータを設定して取得することもできます。起点、幅、高さのパラメータを設定するコードは以下の通りです:
obj["x"] = 160; //起点のX座標
obj["y"] = 120; //起点のY座標
obj["w"] = 320; //幅
obj["h"] = 240; //高さ
ターゲット追跡機能のJSONデータフォーマットの詳細はこちらを参照してください。
以下のサンプルプログラムでは、ホストボードに電源を供給した後に1回だけパラメータ設定データを送信します。追跡対象が取得範囲内にあることを確認してください。サンプルの機能ページは以下の通りです:
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Target Tracker";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);
Serial2.flush();
delay(200);
JSONVar ROI;
ROI["config"] = "Target Tracker";
ROI["x"] = 160;
ROI["y"] = 120;
ROI["w"] = 320;
ROI["h"] = 240;
jsonString = JSON.stringify(ROI);
Serial2.println(jsonString);
Serial2.flush();
delay(200);
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // clear '\0'
line.remove(0, 1);
}
Serial2.flush();
JSONVar target_obj = JSON.parse(line);
if (!(JSON.typeof(target_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Target Tracker example");
if (target_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println(String(target_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(target_obj["msg"]).c_str());
if (target_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(target_obj["running"]).c_str());
display.printf(" running: %s\n", String(target_obj["running"]).c_str());
}
} else {
if (target_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(target_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(target_obj["running"]).c_str());
}
}
if (target_obj.hasOwnProperty("x")) {
int x = (int)target_obj["x"];
int y = (int)target_obj["y"];
int w = (int)target_obj["w"];
int h = (int)target_obj["h"];
Serial.printf("x = %d\n", x);
Serial.printf("y = %d\n", y);
Serial.printf("w = %d\n", w);
Serial.printf("h = %d\n", h);
display.setCursor(0, 60);
display.printf(" x = %d\n", x);
display.printf(" y = %d\n", y);
display.printf(" w = %d\n", w);
display.printf(" h = %d\n", h);
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
ターゲット物体のデータを正常に取得すると、ホストボードはターゲット物体の位置などのデータをリアルタイムで表示・出力します。検出結果は以下の図の通りです:
このサンプルプログラムではUnitV2を動体追跡機能に切り替えることができます。この機能を使用する前に、背景を1回設定して効果的に動体追跡を行う必要があります。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
動体検出機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
int motion_cnt = 0;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Motion Tracker";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);
Serial2.flush();
delay(200);
JSONVar BCKG;
BCKG["config"] = "Motion Tracker";
BCKG["operation"] = "update";
jsonString = JSON.stringify(BCKG);
Serial2.println(jsonString);
Serial2.flush();
delay(200);
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // clear '\0'
line.remove(0, 1);
}
Serial2.flush();
JSONVar motion_obj = JSON.parse(line);
if (!(JSON.typeof(motion_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Target Tracker example");
if (motion_obj.hasOwnProperty("msg")) {//ここは設定のレスポンスを1回受信するための処理です
Serial.print("msg = ");
Serial.println(String(motion_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(motion_obj["msg"]).c_str());
if (motion_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(motion_obj["running"]).c_str());
display.printf(" running: %s\n", String(motion_obj["running"]).c_str());
}
} else {
if (motion_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(motion_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(motion_obj["running"]).c_str());
}
}
if (motion_obj.hasOwnProperty("num")) {
motion_cnt = (int)motion_obj["num"];
Serial.printf("num = %d\n", motion_cnt);
display.printf(" num: %d\n", motion_cnt);
}
// obj配列を走査
if (motion_obj.hasOwnProperty("roi")) {
JSONVar obj_arr = motion_obj["roi"];
for (int i = 0; i < (int)motion_cnt; i++) {
display.fillRect(0, 80, 320, 160, TFT_WHITE);
display.setCursor(0, 80);
if (JSON.typeof(obj_arr[i]) != "undefined") {
Serial.printf("------[roi %d]------\n", i);
Serial.printf("\tx: %d\n", (int)obj_arr[i]["x"]);
Serial.printf("\ty: %d\n", (int)obj_arr[i]["y"]);
Serial.printf("\tw: %d\n", (int)obj_arr[i]["w"]);
Serial.printf("\th: %d\n", (int)obj_arr[i]["h"]);
Serial.printf("\tangle: %f\n", (double)obj_arr[i]["angle"]);
Serial.printf("\tarea: %d\n", (int)obj_arr[i]["area"]);
display.printf("roi %d:\n", i);
display.printf(" x: %d, y: %d\n", (int)obj_arr[i]["x"], (int)obj_arr[i]["y"]);
display.printf(" w: %d, h: %d\n", (int)obj_arr[i]["w"], (int)obj_arr[i]["h"]);
display.printf(" angle: %f\n", (double)obj_arr[i]["angle"]);
display.printf(" area: %d\n", (int)obj_arr[i]["area"]);
}
delay(200);
}
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
UnitV2が物体の動きを検出すると、物体の位置などのデータをリアルタイムでフィードバックします。フィードバック結果は以下の図の通りです:
このサンプルプログラムではUnitV2を物体認識分類機能に切り替えることができます。出荷時のファームウェアにはCore、UnitV、StickC、Atomの4つのカテゴリがデフォルトで搭載されています。カスタムカテゴリを作成したい場合は、機能ページの「add」ボタンをクリックして追加し、「train」ボタンをクリックして該当カテゴリの学習を行い、最後に「save&run」ボタンをクリックして該当カテゴリのデータを保存して学習モードを終了すると、物体認識分類機能を使用できます。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
また、以下のサンプルプログラム内のenter_training_mode
、save_and_start
関数を使用して設定することもできます。以下のサンプルプログラムではearphone
(イヤホン)というカテゴリを新規作成して学習を行い、学習回数は10回です。他のカテゴリを追加したい場合は、enter_training_mode
関数内のカテゴリIDと名前を変更してください。
enter_training_mode_with_all_classes_clear
関数を使用する)を行うと、すべての学習済みカテゴリデータ(出荷時のデフォルトカテゴリを含む)が永久に削除されます。電源を切断して再度供給しても復元されませんので、慎重に使用してください!物体認識分類機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
int cla_cnt = 0;
String enter_training_mode(int id, String name) {
JSONVar json;
json["config"] = "Online Classifier";
json["operation"] = "train";
json["class_id"] = id; //0~N
json["class"] = name; //形式:"class_name"
return JSON.stringify(json);
}
String enter_training_mode_with_all_classes_clear(void) {
JSONVar json;
json["config"] = "Online Classifier";
json["operation"] = "reset";
return JSON.stringify(json);
}
String save_and_start(void) {
JSONVar json;
json["config"] = "Online Classifier";
json["operation"] = "saverun";
return JSON.stringify(json);
}
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Online Classifier";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);delay(10);
// このコマンドを実行すると出荷時ファームウェアのデフォルトカテゴリが削除されます。推奨しません。
// jsonString = enter_training_mode_with_all_classes_clear();
// Serial2.println(jsonString);delay(10);
for (int i=0; i < 10; i++){
jsonString = enter_training_mode(0, "earphone");
Serial2.println(jsonString);delay(10);
}
delay(2000);
jsonString = save_and_start();
Serial2.println(jsonString);
delay(10);
Serial2.flush();
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // 空文字('\0')をクリア
line.remove(0, 1);
}
Serial2.flush();
JSONVar cla_obj = JSON.parse(line);
if (!(JSON.typeof(cla_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Target Tracker example");
if (cla_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println(String(cla_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(cla_obj["msg"]).c_str());
if (cla_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(cla_obj["running"]).c_str());
display.printf(" running: %s\n", String(cla_obj["running"]).c_str());
}
} else {
if (cla_obj.hasOwnProperty("running")) {
Serial.print("running = ");
Serial.println(String(cla_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(cla_obj["running"]).c_str());
}
}
if (cla_obj.hasOwnProperty("class_num")) {
cla_cnt = (int)cla_obj["class_num"];
String best_match = String(cla_obj["best_match"]).c_str();
double best_score = (double)cla_obj["best_score"];
Serial.printf("class num = %d\n", cla_cnt);
Serial.printf("best match = %s\n", best_match);
Serial.printf("best score = %f\n", best_score);
display.printf(" class num: %d\n", cla_cnt);
display.printf(" best match = %s\n", best_match);
display.printf(" best score = %f\n", best_score);
}
if (cla_obj.hasOwnProperty("class")) {
JSONVar obj_arr = cla_obj["class"];
for (int i = 0; i < (int)cla_cnt; i++) {
display.fillRect(0, 120, 320, 120, TFT_WHITE);
display.setCursor(0, 120);
if (JSON.typeof(obj_arr[i]) != "undefined") {
Serial.printf("------[class %d]------\n", i);
Serial.printf("\tname: %s\n", String(obj_arr[i]["name"]).c_str());
Serial.printf("\tscore: %f\n", (double)obj_arr[i]["score"]);
display.printf("class %d:\n", i);
display.printf(" name: %s\n", String(obj_arr[i]["name"]).c_str());
display.printf(" score: %f\n", (double)obj_arr[i]["score"]);
}
delay(200);
}
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
UnitV2が物体を検出すると、物体が属するカテゴリなどのデータをリアルタイムでフィードバックします。フィードバック結果は以下の図の通りです:
このサンプルプログラムではUnitV2を顔認識機能に切り替えることができます。出荷時のファームウェアには顔データが含まれていません。顔データを設定するには、機能ページの「add」ボタンをクリックして追加し、「train」ボタンをクリックして該当顔データの学習を行い、最後に「save」ボタンをクリックして該当顔データを保存して学習モードを終了すると、顔認識機能を使用できます。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
また、以下のサンプルプログラム内のcreate_new_face
、save_and_start
関数を使用して設定することもできます。以下のサンプルプログラムではLena
という顔データを新規作成して学習を行い、学習回数は10回です。他の顔データを追加したい場合は、create_new_face
関数内のカテゴリIDと名前を変更してください。
clear_all_faces
関数を使用する)を行うと、すべての学習済み顔データが永久に削除されます。電源を切断して再度供給しても復元されませんので、慎重に使用してください!顔認識機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
int face_cnt = 0;
String create_new_face(int id, String name) {
JSONVar json;
json["config"] = "Face Recognition";
json["operation"] = "train";
json["face_id"] = id; //0~N
json["name"] = name; //形式:"face_name"
return JSON.stringify(json);
}
String clear_all_faces(void) {
JSONVar json;
json["config"] = "Face Recognition";
json["operation"] = "reset";
return JSON.stringify(json);
}
String save_and_start(void) {
JSONVar json;
json["config"] = "Face Recognition";
json["operation"] = "saverun";
return JSON.stringify(json);
}
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 3, 3);
display.drawLine(0, 23, 320, 23, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Face Recognition";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);delay(10);
// jsonString = clear_all_faces();
// Serial2.println(jsonString);delay(10);
for (int i=0; i < 10; i++){
jsonString = create_new_face(0, "Lena");
Serial2.println(jsonString);delay(10);
}
delay(2000);
jsonString = save_and_start();
Serial2.println(jsonString);delay(10);
Serial2.flush();
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // 空文字('\0')をクリア
line.remove(0, 1);
}
Serial2.flush();
JSONVar face_obj = JSON.parse(line);
if (!(JSON.typeof(face_obj) == "undefined")) {
display.fillRect(0, 25, 320, 215, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Face Recognition example");
if (face_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println(String(face_obj["msg"]).c_str());
display.setCursor(0, 25);
display.printf(" msg: %s\n", String(face_obj["msg"]).c_str());
if (face_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(face_obj["running"]).c_str());
display.printf(" running: %s\n", String(face_obj["running"]).c_str());
}
} else {
if (face_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(face_obj["running"]).c_str());
display.setCursor(0, 25);
display.printf(" running: %s\n", String(face_obj["running"]).c_str());
}
if (face_obj.hasOwnProperty("status")) {
Serial.printf("status : %s\n", String(face_obj["status"]).c_str());
Serial.printf("\tx: %d\n", (int)face_obj["x"]);
Serial.printf("\ty: %d\n", (int)face_obj["y"]);
Serial.printf("\tw: %d\n", (int)face_obj["w"]);
Serial.printf("\th: %d\n", (int)face_obj["h"]);
Serial.printf("\tprob: %f\n", (double)face_obj["prob"]);
Serial.printf("\tname: %s\n", String(face_obj["name"]).c_str());
display.printf(" status: %s\n", String(face_obj["status"]).c_str());
display.printf(" x: %d\n", (int)face_obj["x"]);
display.printf(" y: %d\n", (int)face_obj["y"]);
display.printf(" w: %d\n", (int)face_obj["w"]);
display.printf(" h: %d\n", (int)face_obj["h"]);
display.printf(" prob: %f\n", (double)face_obj["prob"]);
display.printf(" name: %s\n", String(face_obj["name"]).c_str());
}
}
if (face_obj.hasOwnProperty("num")) {
face_cnt = (int)face_obj["num"];
Serial.printf("num = %d\n", face_cnt);
display.printf(" num: %d\n", face_cnt);
}
if (face_obj.hasOwnProperty("face")) {
JSONVar obj_arr = face_obj["face"];
display.fillRect(0, 60, 320, 180, TFT_WHITE);
display.setCursor(0, 60);
for (int i = 0; i < (int)face_cnt; i++) {
if (JSON.typeof(obj_arr[i]) != "undefined") {
int fx = (int)obj_arr[i]["x"];
int fy = (int)obj_arr[i]["y"];
int fw = (int)obj_arr[i]["w"];
int fh = (int)obj_arr[i]["h"];
double fprob = (double)obj_arr[i]["prob"];
double fmprob = (double)obj_arr[i]["match_prob"];
String fname = String(obj_arr[i]["name"]);
Serial.printf("------[face %d]------\n", i);
Serial.printf("\tx: %d\n", fx);
Serial.printf("\ty: %d\n", fy);
Serial.printf("\tw: %d\n", fw);
Serial.printf("\th: %d\n", fh);
Serial.printf("\tprob: %f\n", fprob);
Serial.printf("\tmatch prob: %f\n", fmprob);
Serial.printf("\tname: %s\n", fname.c_str());
display.printf("face %d:\n", i);
display.printf(" x:%d, y:%d,", fx, fy);
display.printf(" w:%d, h:%d\n", fw, fh);
display.printf(" prob: %f\n", fprob);
display.printf(" match prob: %f\n", fmprob);
display.printf(" name: %s\n", fname.c_str());
if (obj_arr[i].hasOwnProperty("mark")) {
JSONVar marks = obj_arr[i]["mark"];
for (int j = 0; j < 5; j++) {
if (JSON.typeof(marks[j]) != "undefined") {
int mx = (int)marks[j]["x"];
int my = (int)marks[j]["y"];
display.printf("\t mark%d: x=%d, y=%d\n", j, mx, my);
Serial.printf("\t\tmark%d: x=%d, y=%d\n", j, mx, my);
}
}
}
}
delay(200);
}
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
下図左側の顔をスキャンすると、右側の図のような認識結果が表示されます。
このサンプルプログラムではUnitV2を顔検出機能に切り替えることができます。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
顔検出機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
int face_cnt = 0;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Face Detector";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);
Serial2.flush();
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // 空文字('\0')をクリア
line.remove(0, 1);
}
Serial2.flush();
JSONVar face_obj = JSON.parse(line);
if (!(JSON.typeof(face_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Face Detector example");
if (face_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println(String(face_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(face_obj["msg"]).c_str());
if (face_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(face_obj["running"]).c_str());
display.printf(" running: %s\n", String(face_obj["running"]).c_str());
}
} else {
if (face_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(face_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(face_obj["running"]).c_str());
}
}
if (face_obj.hasOwnProperty("num")) {
face_cnt = (int)face_obj["num"];
Serial.printf("num = %d\n", face_cnt);
display.printf(" num: %d\n", face_cnt);
}
if (face_obj.hasOwnProperty("face")) {
JSONVar obj_arr = face_obj["face"];
display.fillRect(0, 70, 320, 170, TFT_WHITE);
display.setCursor(0, 70);
for (int i = 0; i < (int)face_cnt; i++) {
if (JSON.typeof(obj_arr[i]) != "undefined") {
int fx = (int)obj_arr[i]["x"];
int fy = (int)obj_arr[i]["y"];
int fw = (int)obj_arr[i]["w"];
int fh = (int)obj_arr[i]["h"];
double fprob = (double)obj_arr[i]["prob"];
Serial.printf("------[face %d]------\n", i);
Serial.printf("\tx: %d\n", fx);
Serial.printf("\ty: %d\n", fy);
Serial.printf("\tw: %d\n", fw);
Serial.printf("\th: %d\n", fh);
Serial.printf("\tprob: %f\n", fprob);
display.printf("face %d:\n", i);
display.printf(" x:%d, y:%d\n", fx, fy);
display.printf(" w:%d, h:%d\n", fw, fh);
display.printf(" prob: %f\n", fprob);
if (obj_arr[i].hasOwnProperty("mark")) {
JSONVar marks = obj_arr[i]["mark"];
for (int j = 0; j < 5; j++) {
if (JSON.typeof(marks[j]) != "undefined") {
int mx = (int)marks[j]["x"];
int my = (int)marks[j]["y"];
display.printf("\t mark%d: x=%d, y=%d\n", j, mx, my);
Serial.printf("\t\tmark%d: x=%d, y=%d\n", j, mx, my);
}
}
}
}
delay(200);
}
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
下図左側の顔をスキャンすると、右側の図のような検出結果が表示されます。
このサンプルプログラムではUnitV2を形状検出機能に切り替えることができます。この機能を使用する前に、背景を1回設定して検出を行う必要があります。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
形状検出機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
int shape_cnt = 0;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Shape Detector";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);delay(10);
JSONVar BCKG;
BCKG["config"] = "Shape Detector";
BCKG["operation"] = "update";
jsonString = JSON.stringify(BCKG);
Serial2.println(jsonString);
Serial2.flush();
delay(200);
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // 空文字('\0')をクリア
line.remove(0, 1);
}
Serial2.flush();
JSONVar shape_obj = JSON.parse(line);
if (!(JSON.typeof(shape_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Shape Detector example");
if (shape_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println(String(shape_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(shape_obj["msg"]).c_str());
if (shape_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(shape_obj["running"]).c_str());
display.printf(" running: %s\n", String(shape_obj["running"]).c_str());
}
} else {
if (shape_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(shape_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(shape_obj["running"]).c_str());
}
}
if (shape_obj.hasOwnProperty("num")) {
shape_cnt = (int)shape_obj["num"];
Serial.printf("num = %d\n", shape_cnt);
display.printf(" num: %d\n", shape_cnt);
}
if (shape_obj.hasOwnProperty("shape")) {
JSONVar obj_arr = shape_obj["shape"];
for (int i = 0; i < (int)shape_cnt; i++) {
display.fillRect(0, 80, 320, 160, TFT_WHITE);
display.setCursor(0, 80);
if (JSON.typeof(obj_arr[i]) != "undefined") {
String name = String(obj_arr[i]["name"]);
int x = (int)obj_arr[i]["x"];
int y = (int)obj_arr[i]["y"];
int w = (int)obj_arr[i]["w"];
int h = (int)obj_arr[i]["h"];
double angle = (double)obj_arr[i]["angle"];
int area = (int)obj_arr[i]["area"];
Serial.printf("------[shape %d]------\n", i);
Serial.printf("\tname: %s\n", name.c_str());
Serial.printf("\tx: %d\n", x);
Serial.printf("\ty: %d\n", y);
Serial.printf("\tw: %d\n", w);
Serial.printf("\th: %d\n", h);
Serial.printf("\tangle: %f\n", angle);
Serial.printf("\tarea: %d\n", area);
display.printf("shape %d:\n", i);
display.printf(" name: %s\n", name.c_str());
display.printf(" x:%d, y:%d\n", x, y);
display.printf(" w:%d, h:%d\n", w, h);
display.printf(" angle: %f\n", angle);
display.printf(" area: %d\n", area);
}
delay(200);
}
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
下図左側の画像をスキャンすると、右側の図のような検出結果が表示されます。
このサンプルプログラムではUnitV2をカスタム形状マッチング機能に切り替えることができます。この機能を使用する前に、背景を1回設定して検出マッチングを行う必要があります。出荷時のファームウェアには形状データが含まれていません。形状データを設定するには、機能ページの「add」ボタンをクリックして追加し、「upload」ボタンをクリックして「白地に黒い形状」の「pngファイル」をアップロードします。作成される形状名はファイル名に基づいて設定され、この例ではアップロードするファイル名をarrow.pngとしているため、形状名はarrow
(矢印)となります。画像のアップロードが成功すると、形状マッチング機能を使用できます。ブラウザでドメインunitv2.py
またはIPアドレス10.254.239.1
にアクセスすると機能ページが表示され、ページの内容は以下の通りです:
形状検出機能のJSONデータフォーマットの詳細はこちらを参照してください。
#include <M5Unified.h>
#include <M5GFX.h>
#include <Arduino_JSON.h>
M5GFX display;
int shape_cnt = 0;
void setup() {
display.begin();
display.setRotation(1);
display.clear(TFT_WHITE);
display.setFont(&fonts::FreeMonoBold9pt7b);
display.setTextColor(TFT_BLACK);
delay(100);
display.drawString("UnitV2 Json Example", 5, 5);
display.drawLine(0, 25, 320, 25, TFT_BLACK);
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 13, 14);//PORT.C
//Setting JSON
JSONVar obj;
obj["function"] = "Shape Matching";
obj["args"] = "";
String jsonString = JSON.stringify(obj);
Serial2.println(jsonString);delay(10);
JSONVar BCKG;
BCKG["config"] = "Shape Matching";
BCKG["operation"] = "update";
jsonString = JSON.stringify(BCKG);
Serial2.println(jsonString);
Serial2.flush();
delay(200);
}
void loop() {
if (Serial2.available() > 0) {
String line = Serial2.readStringUntil('\r');
while (line.length() && line[0] != '{') { // 空文字('\0')をクリア
line.remove(0, 1);
}
Serial2.flush();
JSONVar shape_obj = JSON.parse(line);
if (!(JSON.typeof(shape_obj) == "undefined")) {
display.fillRect(0, 35, 320, 205, TFT_WHITE);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.println("UnitV2 Shape Matching example");
if (shape_obj.hasOwnProperty("msg")) {
Serial.print("msg = ");
Serial.println(String(shape_obj["msg"]).c_str());
display.setCursor(0, 35);
display.printf(" msg: %s\n", String(shape_obj["msg"]).c_str());
if (shape_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(shape_obj["running"]).c_str());
display.printf(" running: %s\n", String(shape_obj["running"]).c_str());
}
} else {
if (shape_obj.hasOwnProperty("running")) {
Serial.print("running : ");
Serial.println(String(shape_obj["running"]).c_str());
display.setCursor(0, 35);
display.printf(" running: %s\n", String(shape_obj["running"]).c_str());
}
}
if (shape_obj.hasOwnProperty("num")) {
shape_cnt = (int)shape_obj["num"];
Serial.printf("num = %d\n", shape_cnt);
display.printf(" num: %d\n", shape_cnt);
}
if (shape_obj.hasOwnProperty("shape")) {
JSONVar obj_arr = shape_obj["shape"];
for (int i = 0; i < (int)shape_cnt; i++) {
display.fillRect(0, 80, 320, 160, TFT_WHITE);
display.setCursor(0, 80);
if (JSON.typeof(obj_arr[i]) != "undefined") {
String name = String(obj_arr[i]["name"]);
int x = (int)obj_arr[i]["x"];
int y = (int)obj_arr[i]["y"];
int w = (int)obj_arr[i]["w"];
int h = (int)obj_arr[i]["h"];
int area = (int)obj_arr[i]["area"];
Serial.printf("------[shape %d]------\n", i);
Serial.printf("\tname: %s\n", name.c_str());
Serial.printf("\tx: %d\n", x);
Serial.printf("\ty: %d\n", y);
Serial.printf("\tw: %d\n", w);
Serial.printf("\th: %d\n", h);
Serial.printf("\tarea: %d\n", area);
display.printf("shape %d:\n", i);
display.printf(" name: %s\n", name.c_str());
display.printf(" x:%d, y:%d\n", x, y);
display.printf(" w:%d, h:%d\n", w, h);
display.printf(" area: %d\n", area);
}
delay(200);
}
}
Serial.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
}
}
下図左側の画像をスキャンすると、右側の図のような検出結果が表示されます。