Masalah tugas tunggal
Dalam
seri terakhir
, saya meletakkan Intel Neural Computer Stick 2 di tangki dan melemparkan semua perhitungan jaringan saraf ke atasnya, meninggalkan Tensorflow dan OpenCV-DNN.
Ada masalah yang sudah saya temui saat itu - ketidakmampuan untuk bekerja dengan NCS dari beberapa proses secara bersamaan. Lalu itu tidak kritis, tapi sekarang saatnya untuk mencari tahu.
Ketika mencoba memuat model dari proses kedua, OpenVino mulai bersumpah:
E: [ncAPI] [ 926029] resetAll:348 Failed to connect to stalled device, rc: X_LINK_ERROR E: [ncAPI] [ 933282] ncDeviceOpen:672 Failed to find suitable device, rc: X_LINK_DEVICE_NOT_FOUND
Dengan mencari di Forum Dukungan Intel,
masalah serupa ditemukan
.Dari sana kami dipindahkan ke
dokumentasi yang dinyatakan dengan jelas:
Perangkat tunggal tidak dapat dibagi di berbagai proses.
Pada percobaan ini, Anda dapat meminimalkan dan mulai membuat akses multiproses.
Layanan NCS
Sangat logis untuk menempatkan kerja langsung dengan NCS dalam layanan terpisah, dan untuk mendistribusikan API ke semua klien yang akan digunakan untuk bekerja.
Secara umum, ini seharusnya menjadi topik tentang robot dan pencapaian baru dalam hal jaringan saraf. Tetapi ternyata materi pada API NCS cukup tertarik ke artikel terpisah.
API NCS
Pada level rendah, API NCS sangat sederhana:
- model beban
- mulai perhitungan
- dapatkan daftar model
- dapatkan properti model
Jika semuanya tidak ambigu saat memuat model, maka knalpot kalkulasi adalah tensor sensitif konteks yang mungkin tidak perlu semua klien.
Memperoleh daftar model juga cukup transparan, dan dari properti dimensi tensor input langsung terlintas dalam pikiran - dalam istilah manusia ini berarti bahwa akan lebih baik untuk menyesuaikan gambar di muka dengan pengaturan jaringan.
Selain itu, level rendah baik, tetapi jika Anda mendukung operasi khusus, itu menyederhanakan logika dan data.
Jadi, selain pangkalan, ada tugas untuk mendukung API untuk klasifikasi, deteksi, dan segmentasi.
Sayangnya, model segmentasi yang paling menarik
tidak didukung pada NCS, jadi Anda harus membatasi diri hingga yang paling sederhana, dengan jalan dan markup.
Setiap operasi ini menggunakan perhitungan dasar model, tetapi mereka berbeda dalam interpretasi tensor output.
Antarmuka utama
Jadi, antarmuka utama meliputi metode:
- POST: / load - memuat model
- POST: / unload / $ model - hapus model (dari layanan, tidak mungkin untuk menghapus dari perangkat)
- DAPATKAN: / daftar - dapatkan daftar model
- DAPATKAN: / input / shape / $ model - cari tahu dimensi tensor input
- POST: / inference / file / $ model - buat perhitungan dengan data dari memori
- POST: / inference / path / $ model - membuat perhitungan dengan data dalam sistem file
Berikut adalah dua kata tentang data dari memori dan sistem file:
Jika layanan NCS dan penggunanya menjalankan Raspberry yang sama, maka masuk akal untuk menghemat mentransfer gambar dan alih-alih memindahkan jalur sehingga layanan itu sendiri membaca file.
Jika gambar sudah ada dalam memori (atau tidak ada dalam sistem file), maka kami mentransfernya langsung dari sana.
Pengujian menunjukkan bahwa mentransfer byte dari memori secara signifikan lebih lambat (pengukuran dilakukan untuk 1000 upaya):
Dari memori: 87,5 detik
Jalur File: 63.3150 detik
Namun, kedua opsi ini didukung untuk metode apa pun, baik untuk perhitungan umum dan untuk kasus khusus di bawah ini.
Secara umum, metode inferensi mengambil gambar dalam bentuk array numpy sebagai input dan menghasilkan tensor dalam format yang sama.
Bagaimana menafsirkan knalpot sudah menjadi masalah pelanggan.
Untuk memfasilitasi tugas ini, layanan mendukung metode khusus yang mengekstrak informasi signifikan dalam bentuk manusia dari tensor keluaran.
Klasifikasi
Untuk klasifikasi, kami membuat metode REST terpisah, yang mengubah tensor output menjadi satu set pasangan (kelas, skor).
def get_class_tensor(data): ret = [] thr = 0.01 while(True): cls = np.argmax(data) if data[cls] < thr: break; logging.debug(("Class", cls, "score", data[cls])) c = {"class" : int(cls), "score" : int(100 * data[cls])} data[cls] = 0 ret.append(c) return ret def classify(model_id, img): rc, out = run_inference(model_id, img) if not rc: return rc, out return True, get_class_tensor(out)
Seperti halnya dengan output normal, dua metode didukung - melalui file dalam memori dan jalur pada disk.
- POST: / mengklasifikasikan / file / $ model
- POST: / mengklasifikasikan / path / $ model
Deteksi
Tensor output detektor berisi satu set (kelas, probabilitas, koordinat dinormalkan) dan terlihat agak rumit.
Kami mengubahnya menjadi bentuk yang dapat dimengerti, sambil memotong opsi yang tidak mungkin:
def get_detect_from_tensor(t, rows, cols): score = int(100 * t[2]) cls = int(t[1]) left = int(t[3] * cols) top = int(t[4] * rows) right = int(t[5] * cols) bottom = int(t[6] * rows) return {"class" : cls, "score" : score, "x" : left, "y" : top, "w" : (right - left), "h" : (bottom - top)} def build_detection(data, thr, rows, cols): T = {} for t in data: score = t[2] if score > thr: cls = int(t[1]) if cls not in T: T[cls] = get_detect_from_tensor(t, rows, cols) else: a = T[cls] if a["score"] < score: T[cls] = get_detect_from_tensor(t, rows, cols) return list(T.values()) def detect(model_id, img): rc, out = run_inference(model_id, img) if not rc: return rc, out rows, cols = img.shape[:2] return True, build_detection(out[0], 0.01, rows, cols)
Seperti biasa, kedua metode ini didukung:
- POST: / detect / file / $ model
- POST: / detect / path / $ model
Segmentasi
Tensor segmentasi berisi probabilitas berdasarkan kelas dan bahkan dalam dimensi jaringan saraf.
Konversikan ini menjadi mask kelas:
def segment(model_id, img): rc, out = run_inference(model_id, img) if not rc: return rc, out out = np.argmax(out, axis=0) out = cv.resize(out, (img.shape[1], img.shape[0]),interpolation=cv.INTER_NEAREST) return True, out
- POST: / segment / file / $ model
- POST: / segment / path / $ model
Kesimpulan
Seperti yang telah disebutkan, saya awalnya berencana untuk berbicara tentang layanan di salah satu bab artikel tentang penggunaannya, tetapi ternyata volumenya menarik pada dokumen terpisah.
Sekali lagi, saya menggunakan layanan pada Raspberry Pi, tetapi dapat dijalankan pada platform apa pun yang memiliki python dan OpenVino dengan NCS.
Referensi