--- title: "ZigのOpenCVライブラリ「zigcv」を作っている" date: '2022-08-27' isPublished: true lang: 'ja' --- ![zigcv](./zigcv.gif) # はじめに 以前、Zig の Tensorflow Lite のライブラリを使って遊ぶ記事を書いた。 /blog/2022-08-18-zenn-4f4716118cc06b-ja この記事内では、静止画の処理を行うために、[STB ライブラリ](https://github.com/nothings/stb)を用いた。 こうなると次は動画の処理を行いたくなるものだ。 ... ならば OpenCV を Zig から使えるようにしようではないか。 https://github.com/ryoppippi/zigcv # OpenCV の C バインディングを作る OpenCV は C++で書かれているので、Zig から関数を呼び出すには C バインディングを作る必要がある。 1から OpenCV の C バインディングを作るのは大変なので、 今回は同じ手法で C バインディングを実装して呼び出している gocv のコードを利用させていただくことにした。 これで、工数の半分以上が省けることになる。 https://github.com/hybridgroup/gocv # Zig バインディングを作る この記事の執筆中ではまだ完成はしていない。 しかし、Web カメラの画像を取得して文字や図を書き込んだり、画像をファイルから読み込んで加工、保存をすることはできる。 また、DNN のモデルを呼び出し推論を行うこともできるようになった。
Web カメラから画像を取得し、顔が含まれているならば Blur 処理をするコード ```zig const std = @import("std"); const cv = @import("zigcv"); pub fn main() anyerror!void { var allocator = std.heap.page_allocator; var args = try std.process.argsWithAllocator(allocator); defer args.deinit(); const prog = args.next(); const device_id_char = args.next() orelse { std.log.err("usage: {s} [cameraID]", .{prog.?}); std.os.exit(1); }; const device_id = try std.fmt.parseUnsigned(c_int, device_id_char, 10); // open webcam var webcam = try cv.VideoCapture.init(); try webcam.openDevice(device_id); defer webcam.deinit(); // open display window const window_name = "Face Detect"; var window = try cv.Window.init(window_name); defer window.deinit(); // prepare image matrix var img = try cv.Mat.init(); defer img.deinit(); // load classifier to recognize faces var classifier = try cv.CascadeClassifier.init(); defer classifier.deinit(); classifier.load("./libs/gocv/data/haarcascade_frontalface_default.xml") catch { std.debug.print("no xml", .{}); std.os.exit(1); }; const size = cv.Size{ .width = 75, .height = 75 }; while (true) { webcam.read(&img) catch { std.debug.print("capture failed", .{}); std.os.exit(1); }; if (img.isEmpty()) { continue; } const rects = try classifier.detectMultiScale(img, allocator); defer rects.deinit(); const found_num = rects.items.len; std.debug.print("found {d} faces\n", .{found_num}); for (rects.items) |r| { std.debug.print("x:\t{}, y:\t{}, w:\t{}, h:\t{}\n", .{ r.x, r.y, r.width, r.height }); cv.gaussianBlur(img, &img, size, 0, 0, .{}); } window.imShow(img); if (window.waitKey(1) >= 0) { break; } } } ```
![blur](./zigcv-blur.jpg) # 実用例? いくつかの実装例は以下においてある。 https://github.com/ryoppippi/zigcv/tree/main/examples また、mattn 氏が前述の tensorflow Lite ライブラリと組み合わせた例を公開している。 https://github.com/mattn/zig-tflite-example # 終わりに まだまだ開発途中です。 API もまだ不安定ですし、テストも足りていません。 しかし、ある程度は実用できると思います。 Contribution 大歓迎です。 ぜひお待ちしています。 # 追記 2022/10/06 先日、Core 部分の実装が終わり、0.1.1 をリリースしました! https://github.com/ryoppippi/zigcv/releases/tag/0.1.1