OpenCV.jsは、画像処理・コンピュータビジョンライブラリとして広く使われているOpenCVを、Webブラウザ上で動作させるためのJavaScriptバインディングです。
ライセンス
OpenCV.jsのライセンスは、Apache License, Version 2.0です。商用利用を含め、無料で自由に使えます。
OpenCV.js is licensed under the Apache License, Version 2.0.
詳細はApache License 2.0の原文をご確認ください。
導入方法
公式ビルドを利用する場合
<script async src="https://docs.opencv.org/4.x/opencv.js"></script>
動作確認
OpenCV.js 動作確認(グレースケール)
OpenCV.js を読み込み中…
入力
出力(Gray)
※実際動作します。
プライバシーについて
このデモはブラウザ内(ローカル)で画像を処理します。選択した画像がサーバーへアップロードされることはありません。
ソースコード
HTML
<p id="cv-status" style="margin:.25rem 0 1rem;">OpenCV.js を読み込み中…</p>
<label style="display:inline-block;margin:.25rem 0 .5rem;">
画像を選択: <input type="file" id="cv-file" accept="image/*">
</label>
<div style="display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap;">
<div>
<div style="font-size:.9em;margin-bottom:.25rem;">入力</div>
<img id="cv-input" alt="" style="display:none;" />
<canvas id="cv-input-canvas" width="0" height="0" style="border:1px solid #ddd;"></canvas>
</div>
<div>
<div style="font-size:.9em;margin-bottom:.25rem;">出力(Gray)</div>
<canvas id="cv-output" width="0" height="0" style="border:1px solid #ddd;"></canvas>
</div>
</div>
JavaScript
(function(){
// このページにデモ要素がなければ何もしない
const root = document.querySelector('#opencvjs-demo');
if (!root) return;
const OPENCV_SRC = 'https://docs.opencv.org/4.x/opencv.js';
const $ = (s)=>document.querySelector(s);
const statusEl = $('#cv-status');
const fileEl = $('#cv-file');
const imgEl = $('#cv-input');
const inCv = $('#cv-input-canvas');
const outCv = $('#cv-output');
// 読み込み状態表示
function setStatus(text){ if(statusEl) statusEl.textContent = text; }
// スクリプト動的読み込み
function loadScript(src){
return new Promise((resolve, reject) => {
// 既に読み込み済みならスキップ
if (document.querySelector('script[data-opencv-js="1"]')) return resolve();
const s = document.createElement('script');
s.src = src;
s.async = true;
s.defer = true;
s.dataset.opencvJs = '1';
s.onload = resolve;
s.onerror = () => reject(new Error('OpenCV.js が読み込めませんでした'));
document.head.appendChild(s);
});
}
// OpenCV 初期化待ち(cv.Mat が使えるまで)
function waitForOpenCV(timeoutMs = 15000){
return new Promise((resolve, reject) => {
const start = Date.now();
// すでに準備OK
if (window.cv && (cv.Mat || cv['matFromImageData'])) return resolve();
// onRuntimeInitialized を捕まえる
if (window.cv && cv.onRuntimeInitialized) {
cv.onRuntimeInitialized = () => resolve();
}
// 保険としてポーリング
const id = setInterval(() => {
if (window.cv && (cv.Mat || cv['matFromImageData'])) {
clearInterval(id);
resolve();
} else if (Date.now() - start > timeoutMs) {
clearInterval(id);
reject(new Error('OpenCV.js の初期化待ちがタイムアウトしました'));
}
}, 120);
});
}
// 画像を入力キャンバスに収めて描画
function drawToCanvas(img, canvas){
const maxW = 480; // 横幅の簡易制限
const ratio = img.naturalWidth > maxW ? maxW / img.naturalWidth : 1;
canvas.width = Math.round(img.naturalWidth * ratio);
canvas.height = Math.round(img.naturalHeight * ratio);
canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
}
// グレースケール処理(最小デモ)
function processGray(){
try {
const src = cv.imread(inCv);
const dst = new cv.Mat();
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY);
cv.imshow(outCv, dst);
src.delete(); dst.delete();
setStatus('処理完了:出力にグレースケールを表示しました。');
} catch (err) {
console.error(err);
setStatus('処理中にエラーが発生しました(コンソール参照)。');
}
}
// ファイル選択イベント
let objectUrl = null;
function onFileChange(e){
const file = e.target.files && e.target.files[0];
if (!file) return;
if (objectUrl) { URL.revokeObjectURL(objectUrl); objectUrl = null; }
objectUrl = URL.createObjectURL(file);
imgEl.src = objectUrl;
}
imgEl.addEventListener('load', () => { drawToCanvas(imgEl, inCv); processGray(); });
fileEl.addEventListener('change', onFileChange);
window.addEventListener('beforeunload', () => { if (objectUrl) URL.revokeObjectURL(objectUrl); });
// 実行シーケンス
(async () => {
try {
setStatus('OpenCV.js を読み込み中…');
await loadScript(OPENCV_SRC);
setStatus('OpenCV.js を初期化中…');
await waitForOpenCV();
setStatus('OpenCV.js の準備ができました。画像を選択してください。');
} catch (err) {
console.error(err);
setStatus(err.message || 'OpenCV.js の準備に失敗しました');
}
})();
})();
コメント