{"id":15048837,"url":"https://github.com/wasmvision/wasmcv","last_synced_at":"2025-04-10T01:34:17.365Z","repository":{"id":256543177,"uuid":"855073411","full_name":"wasmvision/wasmcv","owner":"wasmvision","description":"WebAssembly guest interfaces for computer vision using OpenCV. Includes bindings for Go, Rust and C. Supports both WASI and WASM \"unknown\".","archived":false,"fork":false,"pushed_at":"2025-04-09T18:45:36.000Z","size":1232,"stargazers_count":30,"open_issues_count":1,"forks_count":4,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-04-09T18:57:10.859Z","etag":null,"topics":["c-language","computer-vision","golang","opencv","opencv4","rust","tinygo","wasi","wasm","wasm-bindgen","wasmcv","webassembly"],"latest_commit_sha":null,"homepage":"https://wasmcv.org","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wasmvision.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-10T09:01:02.000Z","updated_at":"2025-04-09T18:43:49.000Z","dependencies_parsed_at":"2025-01-29T09:33:00.927Z","dependency_job_id":"8392b875-1078-41c4-948b-5be73d0e004f","html_url":"https://github.com/wasmvision/wasmcv","commit_stats":{"total_commits":124,"total_committers":2,"mean_commits":62.0,"dds":0.008064516129032251,"last_synced_commit":"4d99f72416c8537050c0cffc77951c68725be0a4"},"previous_names":["hybridgroup/wasmcv","wasmvision/wasmcv"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wasmvision%2Fwasmcv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wasmvision%2Fwasmcv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wasmvision%2Fwasmcv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wasmvision%2Fwasmcv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wasmvision","download_url":"https://codeload.github.com/wasmvision/wasmcv/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248140917,"owners_count":21054369,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-language","computer-vision","golang","opencv","opencv4","rust","tinygo","wasi","wasm","wasm-bindgen","wasmcv","webassembly"],"created_at":"2024-09-24T21:16:46.624Z","updated_at":"2025-04-10T01:34:17.354Z","avatar_url":"https://github.com/wasmvision.png","language":"Rust","readme":"# wasmCV\n\nwasmCV provides WebAssembly guest interface bindings for computer vision applications based on [OpenCV](https://github.com/opencv/opencv).\n\nIt includes [WIT](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md) files defining the interface to be used between a WebAssembly host application and a WASM guest module intended to process OpenCV `Mat` image frames.\n\nThese interface definitions are then used to generate WASM bindings for TinyGo, Rust, and C. Those bindings can then be used in a WASM guest module to call OpenCV functions implemented by the host to obtain information or perform operations on OpenCV image frames.\n\n```mermaid\nflowchart LR\n    subgraph host\n        OpenCV\n        Runtime[WASM Runtime]\u003c--\u003eOpenCV\n    end\n    subgraph guest\n        Runtime\u003c--wasmCV--\u003eprocessor-go.wasm\n        Runtime\u003c--wasmCV--\u003eprocessor-rust.wasm\n        Runtime\u003c--wasmCV--\u003eprocessor-c.wasm\n        processor-go.wasm\n        processor-rust.wasm\n        processor-c.wasm\n    end\n```\n\n## Example wasmCV modules\n\n### TinyGo\n\nThis TinyGo module exports a `process()` function to the WASM host application, which passes in the wasmCV image `Mat` to be processed. It then calls functions on that `Mat` which are handled by the host application by calling OpenCV to actually perform the operations.\n\n```go\npackage main\n\nimport (\n\t\"github.com/hybridgroup/mechanoid/convert\"\n\t\"go.bytecodealliance.org/cm\"\n\t\"wasmcv.org/wasm/cv/mat\"\n)\n\n//go:wasmimport hosted println\nfunc println(ptr *byte, size uint32)\n\n//export process\nfunc process(image mat.Mat) mat.Mat {\n\tprintln(cm.LowerString(\"Cols: \" +\n\t\tconvert.IntToString(int(image.Cols())) +\n\t\t\" Rows: \" +\n\t\tconvert.IntToString(int(image.Rows())) +\n\t\t\" Type: \" +\n\t\tconvert.IntToString(int(image.Type()))))\n\n\treturn image\n}\n```\n\nInstall the `wasmcv` package into your Go package:\n\n```shell\ngo get wasmcv.org/wasm/cv\n```\n\nYou can then compile this module using the TinyGo compiler.\n\n```shell\ntinygo build -o processor.wasm -target=wasm-unknown processor.go\n```\n\nNote that the `wasm-unknown` target can be used with wasmCV to produce very lightweight guest modules. The example above compiles to around 31k, including debug information.\n\n```shell\n-rwxrwxr-x 1 ron ron 31248 sep 11 11:00 processor.wasm\n```\n\nSee the [basic example application here](./examples/basic) to give it a try.\n\n### Rust\n\nThis Rust module does the same thing as the TinyGo wasm module example. It exports a `process()` function to the WASM host application, which then passes in the wasmCV image `Mat` to be processed. The module then calls functions on that `Mat` which are handled by the host application by calling OpenCV to actually perform the operations.\n\n```rust\n#![no_std]\n\nextern crate core;\nextern crate alloc;\n\nuse alloc::string::String;\nuse alloc::string::ToString;\nuse wasmcv::wasm::cv;\n\n#[no_mangle]\npub extern fn process(mat: cv::mat::Mat) -\u003e cv::mat::Mat {\n    println(\u0026[\"Cols: \", \u0026mat.cols().to_string(), \" Rows: \", \u0026mat.rows().to_string(), \" Size: \", \u0026mat.size().len().to_string()].concat());\n\n    return mat;\n}\n\n/// Print a message to the host [`_println`].\nfn println(message: \u0026String) {\n    unsafe {\n        let (ptr, len) = string_to_ptr(message);\n        _println(ptr, len);\n    }\n}\n\n#[link(wasm_import_module = \"hosted\")]\nextern \"C\" {\n    #[link_name = \"println\"]\n    fn _println(ptr: u32, size: u32);\n}\n\nunsafe fn string_to_ptr(s: \u0026String) -\u003e (u32, u32) {\n    return (s.as_ptr() as u32, s.len() as u32);\n}\n\n#[no_mangle]\npub extern fn malloc(size: usize) -\u003e *mut u8 {\n    let layout = core::alloc::Layout::from_size_align(size, 1).unwrap();\n    unsafe { alloc::alloc::alloc(layout) }\n}\n```\n\nInstall the `wasmcv` crate into your Rust project:\n\n```shell\ncargo add wasmcv\n```\n\nYou can then compile this module using the Rust compiler.\n\n```shell\ncargo build --target wasm32-unknown-unknown --release\n```\n\nThe `wasm32-unknown-unknown` target can be used with wasmCV to produce very lightweight guest modules when combined with `no_std`. The example above compiles to around 14k, including debug information.\n\n```shell\n-rwxrwxr-x 1 ron ron 14488 sep 12 14:23 processrs.wasm\n```\n\nSee the [multi example application here](./examples/multi) to try wasmCV with Rust.\n\n### C\n\nThis C module does the same thing as the TinyGo and Rust wasm module examples. It exports a `process()` function to the WASM host application, which then passes in the wasmCV image `Mat` to be processed. The module then calls functions on that `Mat` which are handled by the host application by calling OpenCV to actually perform the operations.\n\n```c\n#include \u003cstring.h\u003e\n#include \"../../../../components/c/wasmcv/imports.h\"\n\nextern int itoa(int value, char *sp, int radix);\n\n__attribute__((import_module(\"hosted\"), import_name(\"println\"))) void println(int32_t str, int32_t len);\n\nwasm_cv_mat_borrow_mat_t process(wasm_cv_mat_borrow_mat_t image) {\n    int32_t cols, rows;\n    cols = wasm_cv_mat_method_mat_cols(image);\n    rows = wasm_cv_mat_method_mat_rows(image);\n\n    char buf[20];\n    strcpy(buf, \"Cols: \");\n    itoa(cols, buf+6, 10);\n    strcpy(buf+9, \" Rows: \");\n    itoa(rows, buf+16, 10);\n\n    println((int32_t)buf, 20);\n\n    return image;\n}\n```\n\nYou can then compile this module using the `clang` compiler.\n\n```shell\n/opt/wasi-sdk/bin/clang --target=wasm32-unknown-unknown -O3 \\\n        --sysroot=\"/path/to/lib/wasi-libc/sysroot\" \\\n        -z stack-size=4096 -Wl,--initial-memory=65536 \\\n        -o ../processc.wasm process.c itoa.c ../../../../components/c/wasmcv/import.c ../../../../components/c/wasmcv/import_component_type.o \\\n        -Wl,--export=process \\\n        -Wl,--export=__data_end -Wl,--export=__heap_base \\\n        -Wl,--strip-all,--no-entry \\\n        -Wl,--unresolved-symbols=ignore-all \\\n        -nostdlib \\\n```\n\nThe `wasm32-unknown-unknown` target can be used with wasmCV to produce very lightweight guest modules. The example above compiles to just under 3k, including debug information.\n\n```shell\n-rwxrwxr-x 1 ron ron  2916 sep 13 20:03 processc.wasm\n```\n\nSee the [multi example application here](./examples/multi) to try wasmCV with C.\n\n## WASM Component Generation\n\nWASM Guest bindings are generated using `wit-bindgen` v0.41 or above.\n\nhttps://github.com/bytecodealliance/wit-bindgen\n\nGo bindings are generated by `wit-bindgen-go` command line tool v0.6.0 or above.\n\nhttps://github.com/bytecodealliance/go-modules\n\n### TinyGo\n\n```shell\nwit-bindgen-go generate --out ./components/tinygo -w imports -p wasmcv.org ./wit\n```\n\nNote that the TinyGo bindings are a git submodule. When regenerating the submodule must be updated in order to update the separate Go package repo.\n\n### Rust\n\n```shell\nwit-bindgen rust --out-dir ./components/rust/wasmcv/src -w imports ./wit\n```\n\n### C\n\n```shell\nwit-bindgen c --out-dir ./components/c/wasmcv/ -w imports ./wit\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwasmvision%2Fwasmcv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwasmvision%2Fwasmcv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwasmvision%2Fwasmcv/lists"}