📸
ZigのOpenCVライブラリ「zigcv」を作っている
はじめに
以前、Zig の Tensorflow Lite のライブラリを使って遊ぶ記事を書いた。
この記事内では、静止画の処理を行うために、STB ライブラリを用いた。
こうなると次は動画の処理を行いたくなるものだ。
... ならば OpenCV を Zig から使えるようにしようではないか。
OpenCV の C バインディングを作る
OpenCV は C++で書かれているので、Zig から関数を呼び出すには C バインディングを作る必要がある。
1から OpenCV の C バインディングを作るのは大変なので、
今回は同じ手法で C バインディングを実装して呼び出している gocv のコードを利用させていただくことにした。
これで、工数の半分以上が省けることになる。
Zig バインディングを作る
この記事の執筆中ではまだ完成はしていない。
しかし、Web カメラの画像を取得して文字や図を書き込んだり、画像をファイルから読み込んで加工、保存をすることはできる。
また、DNN のモデルを呼び出し推論を行うこともできるようになった。
Web カメラから画像を取得し、顔が含まれているならば Blur 処理をするコード
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;
}
}
}
実用例?
いくつかの実装例は以下においてある。
また、mattn 氏が前述の tensorflow Lite ライブラリと組み合わせた例を公開している。
終わりに
まだまだ開発途中です。
API もまだ不安定ですし、テストも足りていません。
しかし、ある程度は実用できると思います。
Contribution 大歓迎です。
ぜひお待ちしています。
追記 2022/10/06
先日、Core 部分の実装が終わり、0.1.1 をリリースしました!
Discussion