add part of opencv
22
Lib/opencv/sources/doc/js_tutorials/js_assets/.eslintrc.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "google",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6
|
||||
},
|
||||
"rules": {
|
||||
"max-len": ["error", 100, {"ignoreUrls": true}],
|
||||
"quotes": ["error", "single"],
|
||||
"indent": ["error", 4, {"ArrayExpression": "first",
|
||||
"ObjectExpression": "first",
|
||||
"CallExpression": {"arguments": "first"},
|
||||
"SwitchCase": 1}],
|
||||
"require-jsdoc": "off",
|
||||
"new-cap": "off"
|
||||
},
|
||||
"plugins": ["html"],
|
||||
"settings": {
|
||||
"html/javascript-mime-types": ["text/javascript", "text/code-snippet"],
|
||||
"html/indent": "0",
|
||||
"html/report-bad-indent": "error"
|
||||
}
|
||||
}
|
||||
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/apple.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/coins.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/cup.mp4
Normal file
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/handDst.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/handSrc.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Padding Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Padding Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// You can try more different parameters
|
||||
let s = new cv.Scalar(255, 0, 0, 255);
|
||||
cv.copyMakeBorder(src, dst, 10, 10, 10, 10, cv.BORDER_CONSTANT, s);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete();
|
||||
dst.delete();
|
||||
</script>
|
||||
<script>
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image ROI Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image ROI Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// You can try more different parameters
|
||||
let rect = new cv.Rect(100, 100, 200, 200);
|
||||
dst = src.roi(rect);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete();
|
||||
dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Background Subtraction Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Background Subtraction Example</h2>
|
||||
<p>
|
||||
Click <b>Start/Stop</b> button to start or stop the camera capture.<br>
|
||||
The <b>videoInput</b> is a <video> element used as input.
|
||||
The <b>canvasOutput</b> is a <canvas> element used as output.<br>
|
||||
The code of <textarea> will be executed when video is started.
|
||||
You can modify the code to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="startAndStop" disabled>Start</button></div>
|
||||
<textarea class="code" rows="29" cols="80" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
</div>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<video id="videoInput" width="320" height="240" muted loop></video>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" width="320" height="240"></canvas>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">videoInput</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let video = document.getElementById('videoInput');
|
||||
let cap = new cv.VideoCapture(video);
|
||||
|
||||
let frame = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
let fgmask = new cv.Mat(video.height, video.width, cv.CV_8UC1);
|
||||
let fgbg = new cv.BackgroundSubtractorMOG2(500, 16, true);
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
try {
|
||||
if (!streaming) {
|
||||
// clean and stop.
|
||||
frame.delete(); fgmask.delete(); fgbg.delete();
|
||||
return;
|
||||
}
|
||||
let begin = Date.now();
|
||||
// start processing.
|
||||
cap.read(frame);
|
||||
fgbg.apply(frame, fgmask);
|
||||
cv.imshow('canvasOutput', fgmask);
|
||||
// schedule the next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
} catch (err) {
|
||||
utils.printError(err);
|
||||
}
|
||||
};
|
||||
|
||||
// schedule the first one.
|
||||
setTimeout(processVideo, 0);
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
|
||||
let streaming = false;
|
||||
let videoInput = document.getElementById('videoInput');
|
||||
let startAndStop = document.getElementById('startAndStop');
|
||||
let canvasOutput = document.getElementById('canvasOutput');
|
||||
let canvasContext = canvasOutput.getContext('2d');
|
||||
|
||||
startAndStop.addEventListener('click', () => {
|
||||
if (!streaming) {
|
||||
utils.clearError();
|
||||
videoInput.play().then(() => {
|
||||
onVideoStarted();
|
||||
});
|
||||
} else {
|
||||
videoInput.pause();
|
||||
videoInput.currentTime = 0;
|
||||
onVideoStopped();
|
||||
}
|
||||
});
|
||||
|
||||
function onVideoStarted() {
|
||||
streaming = true;
|
||||
startAndStop.innerText = 'Stop';
|
||||
videoInput.height = videoInput.width * (videoInput.videoHeight / videoInput.videoWidth);
|
||||
utils.executeCode('codeEditor');
|
||||
}
|
||||
|
||||
function onVideoStopped() {
|
||||
streaming = false;
|
||||
canvasContext.clearRect(0, 0, canvasOutput.width, canvasOutput.height);
|
||||
startAndStop.innerText = 'Start';
|
||||
}
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
videoInput.addEventListener('canplay', () => {
|
||||
startAndStop.removeAttribute('disabled');
|
||||
});
|
||||
videoInput.src = 'box.mp4';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
172
Lib/opencv/sources/doc/js_tutorials/js_assets/js_camshift.html
Normal file
@@ -0,0 +1,172 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CamShift Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>CamShift Example</h2>
|
||||
<p>
|
||||
Click <b>Start/Stop</b> button to start or stop the video.<br>
|
||||
The <b>videoInput</b> is a <video> element used as CamShift input.
|
||||
The <b>canvasOutput</b> is a <canvas> element used as CamShift output.<br>
|
||||
The code of <textarea> will be executed when video is started.
|
||||
You can modify the code to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="startAndStop" disabled>Start</button></div>
|
||||
<textarea class="code" rows="29" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
</div>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<video id="videoInput" width="320" height="240" muted loop></video>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" width="320" height="240"></canvas>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">videoInput</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let video = document.getElementById('videoInput');
|
||||
let cap = new cv.VideoCapture(video);
|
||||
|
||||
// take first frame of the video
|
||||
let frame = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
cap.read(frame);
|
||||
|
||||
// hardcode the initial location of window
|
||||
let trackWindow = new cv.Rect(150, 60, 63, 125);
|
||||
|
||||
// set up the ROI for tracking
|
||||
let roi = frame.roi(trackWindow);
|
||||
let hsvRoi = new cv.Mat();
|
||||
cv.cvtColor(roi, hsvRoi, cv.COLOR_RGBA2RGB);
|
||||
cv.cvtColor(hsvRoi, hsvRoi, cv.COLOR_RGB2HSV);
|
||||
let mask = new cv.Mat();
|
||||
let lowScalar = new cv.Scalar(30, 30, 0);
|
||||
let highScalar = new cv.Scalar(180, 180, 180);
|
||||
let low = new cv.Mat(hsvRoi.rows, hsvRoi.cols, hsvRoi.type(), lowScalar);
|
||||
let high = new cv.Mat(hsvRoi.rows, hsvRoi.cols, hsvRoi.type(), highScalar);
|
||||
cv.inRange(hsvRoi, low, high, mask);
|
||||
let roiHist = new cv.Mat();
|
||||
let hsvRoiVec = new cv.MatVector();
|
||||
hsvRoiVec.push_back(hsvRoi);
|
||||
cv.calcHist(hsvRoiVec, [0], mask, roiHist, [180], [0, 180]);
|
||||
cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX);
|
||||
|
||||
// delete useless mats.
|
||||
roi.delete(); hsvRoi.delete(); mask.delete(); low.delete(); high.delete(); hsvRoiVec.delete();
|
||||
|
||||
// Setup the termination criteria, either 10 iteration or move by atleast 1 pt
|
||||
let termCrit = new cv.TermCriteria(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1);
|
||||
|
||||
let hsv = new cv.Mat(video.height, video.width, cv.CV_8UC3);
|
||||
let hsvVec = new cv.MatVector();
|
||||
hsvVec.push_back(hsv);
|
||||
let dst = new cv.Mat();
|
||||
let trackBox = null;
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
try {
|
||||
if (!streaming) {
|
||||
// clean and stop.
|
||||
frame.delete(); dst.delete(); hsvVec.delete(); roiHist.delete(); hsv.delete();
|
||||
return;
|
||||
}
|
||||
let begin = Date.now();
|
||||
|
||||
// start processing.
|
||||
cap.read(frame);
|
||||
cv.cvtColor(frame, hsv, cv.COLOR_RGBA2RGB);
|
||||
cv.cvtColor(hsv, hsv, cv.COLOR_RGB2HSV);
|
||||
cv.calcBackProject(hsvVec, [0], roiHist, dst, [0, 180], 1);
|
||||
|
||||
// apply camshift to get the new location
|
||||
[trackBox, trackWindow] = cv.CamShift(dst, trackWindow, termCrit);
|
||||
|
||||
// Draw it on image
|
||||
let pts = cv.rotatedRectPoints(trackBox);
|
||||
cv.line(frame, pts[0], pts[1], [255, 0, 0, 255], 3);
|
||||
cv.line(frame, pts[1], pts[2], [255, 0, 0, 255], 3);
|
||||
cv.line(frame, pts[2], pts[3], [255, 0, 0, 255], 3);
|
||||
cv.line(frame, pts[3], pts[0], [255, 0, 0, 255], 3);
|
||||
cv.imshow('canvasOutput', frame);
|
||||
|
||||
// schedule the next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
} catch (err) {
|
||||
utils.printError(err);
|
||||
}
|
||||
};
|
||||
|
||||
// schedule the first one.
|
||||
setTimeout(processVideo, 0);
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
|
||||
let streaming = false;
|
||||
let videoInput = document.getElementById('videoInput');
|
||||
let startAndStop = document.getElementById('startAndStop');
|
||||
let canvasOutput = document.getElementById('canvasOutput');
|
||||
let canvasContext = canvasOutput.getContext('2d');
|
||||
|
||||
startAndStop.addEventListener('click', () => {
|
||||
if (!streaming) {
|
||||
utils.clearError();
|
||||
videoInput.play().then(() => {
|
||||
onVideoStarted();
|
||||
});
|
||||
} else {
|
||||
videoInput.pause();
|
||||
videoInput.currentTime = 0;
|
||||
onVideoStopped();
|
||||
}
|
||||
});
|
||||
|
||||
function onVideoStarted() {
|
||||
streaming = true;
|
||||
startAndStop.innerText = 'Stop';
|
||||
videoInput.height = videoInput.width * (videoInput.videoHeight / videoInput.videoWidth);
|
||||
utils.executeCode('codeEditor');
|
||||
}
|
||||
|
||||
function onVideoStopped() {
|
||||
streaming = false;
|
||||
canvasContext.clearRect(0, 0, canvasOutput.width, canvasOutput.height);
|
||||
startAndStop.innerText = 'Start';
|
||||
}
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
videoInput.addEventListener('canplay', () => {
|
||||
startAndStop.removeAttribute('disabled');
|
||||
});
|
||||
videoInput.src = 'cup.mp4';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
68
Lib/opencv/sources/doc/js_tutorials/js_assets/js_canny.html
Normal file
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Canny Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Canny Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
|
||||
// You can try more different parameters
|
||||
cv.Canny(src, dst, 50, 100, 3, false);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Convert Color Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Convert Color Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// You can try more different parameters
|
||||
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image InRange Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image InRange Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let low = new cv.Mat(src.rows, src.cols, src.type(), [0, 0, 0, 0]);
|
||||
let high = new cv.Mat(src.rows, src.cols, src.type(), [150, 150, 150, 255]);
|
||||
// You can try more different parameters
|
||||
cv.inRange(src, low, high, dst);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); low.delete(); high.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image ApproxPolyDP Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image ApproxPolyDP Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 100, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
let poly = new cv.MatVector();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
// approximates each contour to polygon
|
||||
for (let i = 0; i < contours.size(); ++i) {
|
||||
let tmp = new cv.Mat();
|
||||
let cnt = contours.get(i);
|
||||
// You can try more different parameters
|
||||
cv.approxPolyDP(cnt, tmp, 3, true);
|
||||
poly.push_back(tmp);
|
||||
cnt.delete(); tmp.delete();
|
||||
}
|
||||
// draw contours with random Scalar
|
||||
for (let i = 0; i < contours.size(); ++i) {
|
||||
let color = new cv.Scalar(Math.round(Math.random() * 255), Math.round(Math.random() * 255),
|
||||
Math.round(Math.random() * 255));
|
||||
cv.drawContours(dst, poly, i, color, 1, 8, hierarchy, 0);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); hierarchy.delete(); contours.delete(); poly.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Area Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Area Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>The area is: </strong><span id="areaOutput"></span></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let cnt = contours.get(20);
|
||||
// You can try more different parameters
|
||||
let area = cv.contourArea(cnt, false);
|
||||
areaOutput.innerHTML = area;
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete(); cnt.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bounding Rect Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Bounding Rect Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let cnt = contours.get(0);
|
||||
// You can try more different parameters
|
||||
let rect = cv.boundingRect(cnt);
|
||||
let contoursColor = new cv.Scalar(255, 255, 255);
|
||||
let rectangleColor = new cv.Scalar(255, 0, 0);
|
||||
cv.drawContours(dst, contours, 0, contoursColor, 1, 8, hierarchy, 100);
|
||||
let point1 = new cv.Point(rect.x, rect.y);
|
||||
let point2 = new cv.Point(rect.x + rect.width, rect.y + rect.height);
|
||||
cv.rectangle(dst, point1, point2, rectangleColor, 2, cv.LINE_AA, 0);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete(); cnt.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Convex Hull Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Convex Hull Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 100, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
let hull = new cv.MatVector();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
// approximates each contour to convex hull
|
||||
for (let i = 0; i < contours.size(); ++i) {
|
||||
let tmp = new cv.Mat();
|
||||
let cnt = contours.get(i);
|
||||
// You can try more different parameters
|
||||
cv.convexHull(cnt, tmp, false, true);
|
||||
hull.push_back(tmp);
|
||||
cnt.delete(); tmp.delete();
|
||||
}
|
||||
// draw contours with random Scalar
|
||||
for (let i = 0; i < contours.size(); ++i) {
|
||||
let colorHull = new cv.Scalar(Math.round(Math.random() * 255), Math.round(Math.random() * 255),
|
||||
Math.round(Math.random() * 255));
|
||||
cv.drawContours(dst, hull, i, colorHull, 1, 8, hierarchy, 0);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); hierarchy.delete(); contours.delete(); hull.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Fit Ellipse Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Fit Ellipse Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let cnt = contours.get(0);
|
||||
// You can try more different parameters
|
||||
let rotatedRect = cv.fitEllipse(cnt);
|
||||
let contoursColor = new cv.Scalar(255, 255, 255);
|
||||
let ellipseColor = new cv.Scalar(255, 0, 0);
|
||||
cv.drawContours(dst, contours, 0, contoursColor, 1, 8, hierarchy, 100);
|
||||
cv.ellipse1(dst, rotatedRect, ellipseColor, 1, cv.LINE_8);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete(); cnt.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Fit Line Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Fit Line Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
let line = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let cnt = contours.get(0);
|
||||
// You can try more different parameters
|
||||
cv.fitLine(cnt, line, cv.DIST_L2, 0, 0.01, 0.01);
|
||||
let contoursColor = new cv.Scalar(255, 255, 255);
|
||||
let lineColor = new cv.Scalar(255, 0, 0);
|
||||
cv.drawContours(dst, contours, 0, contoursColor, 1, 8, hierarchy, 100);
|
||||
let vx = line.data32F[0];
|
||||
let vy = line.data32F[1];
|
||||
let x = line.data32F[2];
|
||||
let y = line.data32F[3];
|
||||
let lefty = Math.round((-x * vy / vx) + y);
|
||||
let righty = Math.round(((src.cols - x) * vy / vx) + y);
|
||||
let point1 = new cv.Point(src.cols - 1, righty);
|
||||
let point2 = new cv.Point(0, lefty);
|
||||
cv.line(dst, point1, point2, lineColor, 2, cv.LINE_AA, 0);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete(); line.delete(); cnt.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Min Area Rect Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Min Area Rect Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let cnt = contours.get(0);
|
||||
// You can try more different parameters
|
||||
let rotatedRect = cv.minAreaRect(cnt);
|
||||
let vertices = cv.RotatedRect.points(rotatedRect);
|
||||
let contoursColor = new cv.Scalar(255, 255, 255);
|
||||
let rectangleColor = new cv.Scalar(255, 0, 0);
|
||||
cv.drawContours(dst, contours, 0, contoursColor, 1, 8, hierarchy, 100);
|
||||
// draw rotatedRect
|
||||
for (let i = 0; i < 4; i++) {
|
||||
cv.line(dst, vertices[i], vertices[(i + 1) % 4], rectangleColor, 2, cv.LINE_AA, 0);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete(); cnt.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Min Enclosing Circle Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Min Enclosing Circle Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let cnt = contours.get(0);
|
||||
// You can try more different parameters
|
||||
let circle = cv.minEnclosingCircle(cnt);
|
||||
let contoursColor = new cv.Scalar(255, 255, 255);
|
||||
let circleColor = new cv.Scalar(255, 0, 0);
|
||||
cv.drawContours(dst, contours, 0, contoursColor, 1, 8, hierarchy, 100);
|
||||
cv.circle(dst, circle.center, circle.radius, circleColor);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete(); cnt.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Moments Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Moments Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>The m00 is: </strong><span id="momentsOutput"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let cnt = contours.get(0);
|
||||
// You can try more different parameters
|
||||
let Moments = cv.moments(cnt, false);
|
||||
momentsOutput.innerHTML = Moments.m00;
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Perimeter Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Perimeter Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>The perimeter is: </strong><span id="perimeterOutput"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let cnt = contours.get(20);
|
||||
// You can try more different parameters
|
||||
let perimeter = cv.arcLength(cnt, true);
|
||||
perimeterOutput.innerHTML = perimeter;
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete(); cnt.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Transpose Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Transpose Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 120, 200, cv.THRESH_BINARY);
|
||||
cv.transpose(src, dst);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Contours Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Contours Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.cols, src.rows, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 120, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
// You can try more different parameters
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
// draw contours with random Scalar
|
||||
for (let i = 0; i < contours.size(); ++i) {
|
||||
let color = new cv.Scalar(Math.round(Math.random() * 255), Math.round(Math.random() * 255),
|
||||
Math.round(Math.random() * 255));
|
||||
cv.drawContours(dst, contours, i, color, 1, cv.LINE_8, hierarchy, 100);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Convexity Defects Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Convexity Defects Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 100, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let hull = new cv.Mat();
|
||||
let defect = new cv.Mat();
|
||||
let cnt = contours.get(0);
|
||||
let lineColor = new cv.Scalar(255, 0, 0);
|
||||
let circleColor = new cv.Scalar(255, 255, 255);
|
||||
cv.convexHull(cnt, hull, false, false);
|
||||
cv.convexityDefects(cnt, hull, defect);
|
||||
for (let i = 0; i < defect.rows; ++i) {
|
||||
let start = new cv.Point(cnt.data32S[defect.data32S[i * 4] * 2],
|
||||
cnt.data32S[defect.data32S[i * 4] * 2 + 1]);
|
||||
let end = new cv.Point(cnt.data32S[defect.data32S[i * 4 + 1] * 2],
|
||||
cnt.data32S[defect.data32S[i * 4 + 1] * 2 + 1]);
|
||||
let far = new cv.Point(cnt.data32S[defect.data32S[i * 4 + 2] * 2],
|
||||
cnt.data32S[defect.data32S[i * 4 + 2] * 2 + 1]);
|
||||
cv.line(dst, start, end, lineColor, 2, cv.LINE_AA, 0);
|
||||
cv.circle(dst, far, 3, circleColor, -1);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); hierarchy.delete(); contours.delete(); hull.delete(); defect.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Match Shape Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Match Shape Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>The result is: </strong><span id="matchShapesOutput"></span></p>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(src, src, 177, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
|
||||
let contourID0 = 10;
|
||||
let contourID1 = 5;
|
||||
let color0 = new cv.Scalar(255, 0, 0);
|
||||
let color1 = new cv.Scalar(0, 0, 255);
|
||||
// You can try more different parameters
|
||||
let result = cv.matchShapes(contours.get(contourID0), contours.get(contourID1), 1, 0);
|
||||
matchShapesOutput.innerHTML = result;
|
||||
cv.drawContours(dst, contours, contourID0, color0, 1, cv.LINE_8, hierarchy, 100);
|
||||
cv.drawContours(dst, contours, contourID1, color1, 1, cv.LINE_8, hierarchy, 100);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); contours.delete(); hierarchy.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('coins.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,70 @@
|
||||
body, div, p {
|
||||
font: 400 14px/22px Roboto,sans-serif;
|
||||
}
|
||||
canvas, img, video {
|
||||
border: 1px solid black;
|
||||
}
|
||||
td {
|
||||
padding: 10px 0px 0px 10px;
|
||||
text-align: center;
|
||||
}
|
||||
button {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
background-color: #337ab7;
|
||||
border-color: #2e6da4;
|
||||
padding: 6px 12px;
|
||||
margin-bottom: 0;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
-ms-touch-action: manipulation;
|
||||
touch-action: manipulation;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
button[disabled] {
|
||||
cursor: not-allowed;
|
||||
filter: alpha(opacity=65);
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
opacity: .65;
|
||||
}
|
||||
.control {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
.err {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
.caption {
|
||||
margin: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.code {
|
||||
padding: 4px 6px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
background-color: #FBFCFD;
|
||||
border: 1px solid #C4CFE5;
|
||||
font-family: monospace, fixed;
|
||||
font-size: 13px;
|
||||
min-height: 13px;
|
||||
line-height: 1.0;
|
||||
text-wrap: unrestricted;
|
||||
padding-bottom: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.small {
|
||||
max-width: 300px;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Face Detection Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Face Detection Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let gray = new cv.Mat();
|
||||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||
let faces = new cv.RectVector();
|
||||
let eyes = new cv.RectVector();
|
||||
let faceCascade = new cv.CascadeClassifier();
|
||||
let eyeCascade = new cv.CascadeClassifier();
|
||||
// load pre-trained classifiers
|
||||
faceCascade.load('haarcascade_frontalface_default.xml');
|
||||
eyeCascade.load('haarcascade_eye.xml');
|
||||
// detect faces
|
||||
let msize = new cv.Size(0, 0);
|
||||
faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, msize, msize);
|
||||
for (let i = 0; i < faces.size(); ++i) {
|
||||
let roiGray = gray.roi(faces.get(i));
|
||||
let roiSrc = src.roi(faces.get(i));
|
||||
let point1 = new cv.Point(faces.get(i).x, faces.get(i).y);
|
||||
let point2 = new cv.Point(faces.get(i).x + faces.get(i).width,
|
||||
faces.get(i).y + faces.get(i).height);
|
||||
cv.rectangle(src, point1, point2, [255, 0, 0, 255]);
|
||||
// detect eyes in face ROI
|
||||
eyeCascade.detectMultiScale(roiGray, eyes);
|
||||
for (let j = 0; j < eyes.size(); ++j) {
|
||||
let point1 = new cv.Point(eyes.get(j).x, eyes.get(j).y);
|
||||
let point2 = new cv.Point(eyes.get(j).x + eyes.get(j).width,
|
||||
eyes.get(j).y + eyes.get(j).height);
|
||||
cv.rectangle(roiSrc, point1, point2, [0, 0, 255, 255]);
|
||||
}
|
||||
roiGray.delete(); roiSrc.delete();
|
||||
}
|
||||
cv.imshow('canvasOutput', src);
|
||||
src.delete(); gray.delete(); faceCascade.delete();
|
||||
eyeCascade.delete(); faces.delete(); eyes.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
let eyeCascadeFile = 'haarcascade_eye.xml';
|
||||
utils.createFileFromUrl(eyeCascadeFile, eyeCascadeFile, () => {
|
||||
let faceCascadeFile = 'haarcascade_frontalface_default.xml';
|
||||
utils.createFileFromUrl(faceCascadeFile, faceCascadeFile, () => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,142 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Face Detection Camera Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Face Detection Camera Example</h2>
|
||||
<p>
|
||||
Click <b>Start/Stop</b> button to start or stop the camera capture.<br>
|
||||
The <b>videoInput</b> is a <video> element used as face detector input.
|
||||
The <b>canvasOutput</b> is a <canvas> element used as face detector output.<br>
|
||||
The code of <textarea> will be executed when video is started.
|
||||
You can modify the code to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="startAndStop" disabled>Start</button></div>
|
||||
<textarea class="code" rows="29" cols="80" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
</div>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<video id="videoInput" width=320 height=240></video>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" width=320 height=240></canvas>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">videoInput</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let video = document.getElementById('videoInput');
|
||||
let src = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
let dst = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
let gray = new cv.Mat();
|
||||
let cap = new cv.VideoCapture(video);
|
||||
let faces = new cv.RectVector();
|
||||
let classifier = new cv.CascadeClassifier();
|
||||
|
||||
// load pre-trained classifiers
|
||||
classifier.load('haarcascade_frontalface_default.xml');
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
try {
|
||||
if (!streaming) {
|
||||
// clean and stop.
|
||||
src.delete();
|
||||
dst.delete();
|
||||
gray.delete();
|
||||
faces.delete();
|
||||
classifier.delete();
|
||||
return;
|
||||
}
|
||||
let begin = Date.now();
|
||||
// start processing.
|
||||
cap.read(src);
|
||||
src.copyTo(dst);
|
||||
cv.cvtColor(dst, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||
// detect faces.
|
||||
classifier.detectMultiScale(gray, faces, 1.1, 3, 0);
|
||||
// draw faces.
|
||||
for (let i = 0; i < faces.size(); ++i) {
|
||||
let face = faces.get(i);
|
||||
let point1 = new cv.Point(face.x, face.y);
|
||||
let point2 = new cv.Point(face.x + face.width, face.y + face.height);
|
||||
cv.rectangle(dst, point1, point2, [255, 0, 0, 255]);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
// schedule the next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
} catch (err) {
|
||||
utils.printError(err);
|
||||
}
|
||||
};
|
||||
|
||||
// schedule the first one.
|
||||
setTimeout(processVideo, 0);
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
|
||||
let streaming = false;
|
||||
let videoInput = document.getElementById('videoInput');
|
||||
let startAndStop = document.getElementById('startAndStop');
|
||||
let canvasOutput = document.getElementById('canvasOutput');
|
||||
let canvasContext = canvasOutput.getContext('2d');
|
||||
|
||||
startAndStop.addEventListener('click', () => {
|
||||
if (!streaming) {
|
||||
utils.clearError();
|
||||
utils.startCamera('qvga', onVideoStarted, 'videoInput');
|
||||
} else {
|
||||
utils.stopCamera();
|
||||
onVideoStopped();
|
||||
}
|
||||
});
|
||||
|
||||
function onVideoStarted() {
|
||||
streaming = true;
|
||||
startAndStop.innerText = 'Stop';
|
||||
videoInput.width = videoInput.videoWidth;
|
||||
videoInput.height = videoInput.videoHeight;
|
||||
utils.executeCode('codeEditor');
|
||||
}
|
||||
|
||||
function onVideoStopped() {
|
||||
streaming = false;
|
||||
canvasContext.clearRect(0, 0, canvasOutput.width, canvasOutput.height);
|
||||
startAndStop.innerText = 'Start';
|
||||
}
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
let faceCascadeFile = 'haarcascade_frontalface_default.xml';
|
||||
utils.createFileFromUrl(faceCascadeFile, faceCascadeFile, () => {
|
||||
startAndStop.removeAttribute('disabled');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Gaussian Blur Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Gaussian Blur Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let ksize = new cv.Size(3, 3);
|
||||
// You can try more different parameters
|
||||
cv.GaussianBlur(src, dst, ksize, 0, 0, cv.BORDER_DEFAULT);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bilateral Filter Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Bilateral Filter Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
|
||||
// You can try more different parameters
|
||||
cv.bilateralFilter(src, dst, 9, 75, 75, cv.BORDER_DEFAULT);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Blur Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Blur Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let ksize = new cv.Size(3, 3);
|
||||
let anchor = new cv.Point(-1, -1);
|
||||
// You can try more different parameters
|
||||
cv.blur(src, dst, ksize, anchor, cv.BORDER_DEFAULT);
|
||||
// cv.boxFilter(src, dst, -1, ksize, anchor, true, cv.BORDER_DEFAULT)
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Filter Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Filter Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.Mat.eye(3, 3, cv.CV_32FC1);
|
||||
let anchor = new cv.Point(-1, -1);
|
||||
// You can try more different parameters
|
||||
cv.filter2D(src, dst, cv.CV_8U, M, anchor, 0, cv.BORDER_DEFAULT);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Median Blur Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Median Blur Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// You can try more different parameters
|
||||
cv.medianBlur(src, dst, 5);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,128 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image DFT Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image DFT Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
|
||||
// get optimal size of DFT
|
||||
let optimalRows = cv.getOptimalDFTSize(src.rows);
|
||||
let optimalCols = cv.getOptimalDFTSize(src.cols);
|
||||
let s0 = cv.Scalar.all(0);
|
||||
let padded = new cv.Mat();
|
||||
cv.copyMakeBorder(src, padded, 0, optimalRows - src.rows, 0,
|
||||
optimalCols - src.cols, cv.BORDER_CONSTANT, s0);
|
||||
|
||||
// use cv.MatVector to distribute space for real part and imaginary part
|
||||
let plane0 = new cv.Mat();
|
||||
padded.convertTo(plane0, cv.CV_32F);
|
||||
let planes = new cv.MatVector();
|
||||
let complexI = new cv.Mat();
|
||||
let plane1 = new cv.Mat.zeros(padded.rows, padded.cols, cv.CV_32F);
|
||||
planes.push_back(plane0);
|
||||
planes.push_back(plane1);
|
||||
cv.merge(planes, complexI);
|
||||
|
||||
// in-place dft transform
|
||||
cv.dft(complexI, complexI);
|
||||
|
||||
// compute log(1 + sqrt(Re(DFT(img))**2 + Im(DFT(img))**2))
|
||||
cv.split(complexI, planes);
|
||||
cv.magnitude(planes.get(0), planes.get(1), planes.get(0));
|
||||
let mag = planes.get(0);
|
||||
let m1 = new cv.Mat.ones(mag.rows, mag.cols, mag.type());
|
||||
cv.add(mag, m1, mag);
|
||||
cv.log(mag, mag);
|
||||
|
||||
// crop the spectrum, if it has an odd number of rows or columns
|
||||
let rect = new cv.Rect(0, 0, mag.cols & -2, mag.rows & -2);
|
||||
mag = mag.roi(rect);
|
||||
|
||||
// rearrange the quadrants of Fourier image
|
||||
// so that the origin is at the image center
|
||||
let cx = mag.cols / 2;
|
||||
let cy = mag.rows / 2;
|
||||
let tmp = new cv.Mat();
|
||||
|
||||
let rect0 = new cv.Rect(0, 0, cx, cy);
|
||||
let rect1 = new cv.Rect(cx, 0, cx, cy);
|
||||
let rect2 = new cv.Rect(0, cy, cx, cy);
|
||||
let rect3 = new cv.Rect(cx, cy, cx, cy);
|
||||
|
||||
let q0 = mag.roi(rect0);
|
||||
let q1 = mag.roi(rect1);
|
||||
let q2 = mag.roi(rect2);
|
||||
let q3 = mag.roi(rect3);
|
||||
|
||||
// exchange 1 and 4 quadrants
|
||||
q0.copyTo(tmp);
|
||||
q3.copyTo(q0);
|
||||
tmp.copyTo(q3);
|
||||
|
||||
// exchange 2 and 3 quadrants
|
||||
q1.copyTo(tmp);
|
||||
q2.copyTo(q1);
|
||||
tmp.copyTo(q2);
|
||||
|
||||
// The pixel value of cv.CV_32S type image ranges from 0 to 1.
|
||||
cv.normalize(mag, mag, 0, 1, cv.NORM_MINMAX);
|
||||
|
||||
cv.imshow('canvasOutput', mag);
|
||||
src.delete(); padded.delete(); planes.delete(); complexI.delete(); m1.delete(); tmp.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Get Affine Transform Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Get Affine Transform Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// (data32F[0], data32F[1]) is the first point
|
||||
// (data32F[2], data32F[3]) is the sescond point
|
||||
// (data32F[4], data32F[5]) is the third point
|
||||
let srcTri = cv.matFromArray(3, 1, cv.CV_32FC2, [0, 0, 0, 1, 1, 0]);
|
||||
let dstTri = cv.matFromArray(3, 1, cv.CV_32FC2, [0.6, 0.2, 0.1, 1.3, 1.5, 0.3]);
|
||||
let dsize = new cv.Size(src.rows, src.cols);
|
||||
let M = cv.getAffineTransform(srcTri, dstTri);
|
||||
// You can try more different parameters
|
||||
cv.warpAffine(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete(); srcTri.delete(); dstTri.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Resize Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Resize Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let dsize = new cv.Size(300, 300);
|
||||
// You can try more different parameters
|
||||
cv.resize(src, dst, dsize, 0, 0, cv.INTER_AREA);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Rotate Transform Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Rotate Transform Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let dsize = new cv.Size(src.rows, src.cols);
|
||||
let center = new cv.Point(src.cols / 2, src.rows / 2);
|
||||
// You can try more different parameters
|
||||
let M = cv.getRotationMatrix2D(center, 45, 1);
|
||||
cv.warpAffine(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Affine Transform Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Affine Transform Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.matFromArray(2, 3, cv.CV_64FC1, [1, 0, 50, 0, 1, 100]);
|
||||
let dsize = new cv.Size(src.rows, src.cols);
|
||||
// You can try more different parameters
|
||||
cv.warpAffine(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,75 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Perspectiv Transform Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Perspectiv Transform Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let dsize = new cv.Size(src.rows, src.cols);
|
||||
// (data32F[0], data32F[1]) is the first point
|
||||
// (data32F[2], data32F[3]) is the sescond point
|
||||
// (data32F[4], data32F[5]) is the third point
|
||||
// (data32F[6], data32F[7]) is the fourth point
|
||||
let srcTri = cv.matFromArray(4, 1, cv.CV_32FC2, [56, 65, 368, 52, 28, 387, 389, 390]);
|
||||
let dstTri = cv.matFromArray(4, 1, cv.CV_32FC2, [0, 0, 300, 0, 0, 300, 300, 300]);
|
||||
let M = cv.getPerspectiveTransform(srcTri, dstTri);
|
||||
// You can try more different parameters
|
||||
cv.warpPerspective(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete(); srcTri.delete(); dstTri.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image GrabCut Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image GrabCut Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
|
||||
let mask = new cv.Mat();
|
||||
let bgdModel = new cv.Mat();
|
||||
let fgdModel = new cv.Mat();
|
||||
let rect = new cv.Rect(50, 50, 260, 280);
|
||||
cv.grabCut(src, mask, rect, bgdModel, fgdModel, 1, cv.GC_INIT_WITH_RECT);
|
||||
// draw foreground
|
||||
for (let i = 0; i < src.rows; i++) {
|
||||
for (let j = 0; j < src.cols; j++) {
|
||||
if (mask.ucharPtr(i, j)[0] == 0 || mask.ucharPtr(i, j)[0] == 2) {
|
||||
src.ucharPtr(i, j)[0] = 0;
|
||||
src.ucharPtr(i, j)[1] = 0;
|
||||
src.ucharPtr(i, j)[2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// draw grab rect
|
||||
let color = new cv.Scalar(0, 0, 255);
|
||||
let point1 = new cv.Point(rect.x, rect.y);
|
||||
let point2 = new cv.Point(rect.x + rect.width, rect.y + rect.height);
|
||||
cv.rectangle(src, point1, point2, color);
|
||||
cv.imshow('canvasOutput', src);
|
||||
src.delete(); mask.delete(); bgdModel.delete(); fgdModel.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Laplacian Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Laplacian Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
|
||||
// You can try more different parameters
|
||||
cv.Laplacian(src, dst, cv.CV_8U, 1, 1, 0, cv.BORDER_DEFAULT);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Sobel Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Sobel Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b>, <b>canvasOutputx</b> and <b>canvasOutputy</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput" class="small"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutputx" class="small"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutputy" class="small"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutputx</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutputy</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dstx = new cv.Mat();
|
||||
let dsty = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
|
||||
// You can try more different parameters
|
||||
cv.Sobel(src, dstx, cv.CV_8U, 1, 0, 3, 1, 0, cv.BORDER_DEFAULT);
|
||||
cv.Sobel(src, dsty, cv.CV_8U, 0, 1, 3, 1, 0, cv.BORDER_DEFAULT);
|
||||
// cv.Scharr(src, dstx, cv.CV_8U, 1, 0, 1, 0, cv.BORDER_DEFAULT);
|
||||
// cv.Scharr(src, dsty, cv.CV_8U, 0, 1, 1, 0, cv.BORDER_DEFAULT);
|
||||
cv.imshow('canvasOutputx', dstx);
|
||||
cv.imshow('canvasOutputy', dsty);
|
||||
src.delete(); dstx.delete(); dsty.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image AbsSobel Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image AbsSobel Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b>, <b>canvasOutput8U</b> and <b>canvasOutput64F</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput" class="small"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput8U" class="small"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput64F" class="small"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput8U</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput64F</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dstx = new cv.Mat();
|
||||
let absDstx = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
|
||||
// You can try more different parameters
|
||||
cv.Sobel(src, dstx, cv.CV_8U, 1, 0, 3, 1, 0, cv.BORDER_DEFAULT);
|
||||
cv.Sobel(src, absDstx, cv.CV_64F, 1, 0, 3, 1, 0, cv.BORDER_DEFAULT);
|
||||
cv.convertScaleAbs(absDstx, absDstx, 1, 0);
|
||||
cv.imshow('canvasOutput8U', dstx);
|
||||
cv.imshow('canvasOutput64F', absDstx);
|
||||
src.delete(); dstx.delete(); absDstx.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,90 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Back Project Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Back Project Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>srcCanvasInput</b>, <b>dstCanvasInput</b> and <b>canvasInput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="srcCanvasInput" class="small"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="dstCanvasInput" class="small"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" class="small"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">srcCanvasInput <input type="file" id="srcFileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">dstCanvasInput <input type="file" id="dstFileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('srcCanvasInput');
|
||||
let dst = cv.imread('dstCanvasInput');
|
||||
cv.cvtColor(src, src, cv.COLOR_RGB2HSV, 0);
|
||||
cv.cvtColor(dst, dst, cv.COLOR_RGB2HSV, 0);
|
||||
let srcVec = new cv.MatVector();
|
||||
let dstVec = new cv.MatVector();
|
||||
srcVec.push_back(src); dstVec.push_back(dst);
|
||||
let backproj = new cv.Mat();
|
||||
let none = new cv.Mat();
|
||||
let mask = new cv.Mat();
|
||||
let hist = new cv.Mat();
|
||||
let channels = [0];
|
||||
let histSize = [50];
|
||||
let ranges = [0, 180];
|
||||
let accumulate = false;
|
||||
cv.calcHist(srcVec, channels, mask, hist, histSize, ranges, accumulate);
|
||||
cv.normalize(hist, hist, 0, 255, cv.NORM_MINMAX, -1, none);
|
||||
cv.calcBackProject(dstVec, channels, hist, backproj, ranges, 1);
|
||||
cv.imshow('canvasOutput', backproj);
|
||||
src.delete(); dst.delete(); srcVec.delete(); dstVec.delete();
|
||||
backproj.delete(); mask.delete(); hist.delete(); none.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('handSrc.jpg', 'srcCanvasInput');
|
||||
utils.loadImageToCanvas('handDst.jpg', 'dstCanvasInput');
|
||||
utils.addFileInputHandler('srcFileInput', 'srcCanvasInput');
|
||||
utils.addFileInputHandler('dstFileInput', 'dstCanvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Histogram Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Histogram Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
let srcVec = new cv.MatVector();
|
||||
srcVec.push_back(src);
|
||||
let accumulate = false;
|
||||
let channels = [0];
|
||||
let histSize = [256];
|
||||
let ranges = [0, 255];
|
||||
let hist = new cv.Mat();
|
||||
let mask = new cv.Mat();
|
||||
let color = new cv.Scalar(255, 255, 255);
|
||||
let scale = 2;
|
||||
// You can try more different parameters
|
||||
cv.calcHist(srcVec, channels, mask, hist, histSize, ranges, accumulate);
|
||||
let result = cv.minMaxLoc(hist, mask);
|
||||
let max = result.maxVal;
|
||||
let dst = new cv.Mat.zeros(src.rows, histSize[0] * scale,
|
||||
cv.CV_8UC3);
|
||||
// draw histogram
|
||||
for (let i = 0; i < histSize[0]; i++) {
|
||||
let binVal = hist.data32F[i] * src.rows / max;
|
||||
let point1 = new cv.Point(i * scale, src.rows - 1);
|
||||
let point2 = new cv.Point((i + 1) * scale - 1, src.rows - binVal);
|
||||
cv.rectangle(dst, point1, point2, color, cv.FILLED);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); srcVec.delete(); mask.delete(); hist.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image CLAHE Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image CLAHE Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let equalDst = new cv.Mat();
|
||||
let claheDst = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.equalizeHist(src, equalDst);
|
||||
let tileGridSize = new cv.Size(8, 8);
|
||||
// You can try more different parameters
|
||||
let clahe = new cv.CLAHE(40, tileGridSize);
|
||||
clahe.apply(src, claheDst);
|
||||
cv.imshow('canvasOutput', equalDst);
|
||||
cv.imshow('canvasOutput', claheDst);
|
||||
src.delete(); equalDst.delete(); claheDst.delete(); clahe.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Equalize Histogram Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Equalize Histogram Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.equalizeHist(src, dst);
|
||||
cv.imshow('canvasOutput', src);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Hough Circles Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Hough Circles Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8U);
|
||||
let circles = new cv.Mat();
|
||||
let color = new cv.Scalar(255, 0, 0);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
// You can try more different parameters
|
||||
cv.HoughCircles(src, circles, cv.HOUGH_GRADIENT,
|
||||
1, 45, 75, 40, 0, 0);
|
||||
// draw circles
|
||||
for (let i = 0; i < circles.cols; ++i) {
|
||||
let x = circles.data32F[i * 3];
|
||||
let y = circles.data32F[i * 3 + 1];
|
||||
let radius = circles.data32F[i * 3 + 2];
|
||||
let center = new cv.Point(x, y);
|
||||
cv.circle(dst, center, radius, color);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); circles.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('coins.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Hough Lines Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Hough Lines Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
let lines = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.Canny(src, src, 50, 200, 3);
|
||||
// You can try more different parameters
|
||||
cv.HoughLines(src, lines, 1, Math.PI / 180,
|
||||
30, 0, 0, 0, Math.PI);
|
||||
// draw lines
|
||||
for (let i = 0; i < lines.rows; ++i) {
|
||||
let rho = lines.data32F[i * 2];
|
||||
let theta = lines.data32F[i * 2 + 1];
|
||||
let a = Math.cos(theta);
|
||||
let b = Math.sin(theta);
|
||||
let x0 = a * rho;
|
||||
let y0 = b * rho;
|
||||
let startPoint = {x: x0 - 1000 * b, y: y0 + 1000 * a};
|
||||
let endPoint = {x: x0 + 1000 * b, y: y0 - 1000 * a};
|
||||
cv.line(dst, startPoint, endPoint, [255, 0, 0, 255]);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); lines.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image HoughLinesP Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image HoughLinesP Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
|
||||
let lines = new cv.Mat();
|
||||
let color = new cv.Scalar(255, 0, 0);
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.Canny(src, src, 50, 200, 3);
|
||||
// You can try more different parameters
|
||||
cv.HoughLinesP(src, lines, 1, Math.PI / 180, 2, 0, 0);
|
||||
// draw lines
|
||||
for (let i = 0; i < lines.rows; ++i) {
|
||||
let startPoint = new cv.Point(lines.data32S[i * 4], lines.data32S[i * 4 + 1]);
|
||||
let endPoint = new cv.Point(lines.data32S[i * 4 + 2], lines.data32S[i * 4 + 3]);
|
||||
cv.line(dst, startPoint, endPoint, color);
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); lines.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,114 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Bitwise Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Bitwise Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>imageCanvasInput</b>, <b>logoCanvasInput</b> and <b>CanvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="imageCanvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">imageCanvasInput <input type="file" id="imageFileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="logoCanvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">logoCanvasInput <input type="file" id="logoFileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('imageCanvasInput');
|
||||
let logo = cv.imread('logoCanvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let roi = new cv.Mat();
|
||||
let mask = new cv.Mat();
|
||||
let maskInv = new cv.Mat();
|
||||
let imgBg = new cv.Mat();
|
||||
let imgFg = new cv.Mat();
|
||||
let sum = new cv.Mat();
|
||||
let rect = new cv.Rect(0, 0, logo.cols, logo.rows);
|
||||
|
||||
// I want to put logo on top-left corner, So I create a ROI
|
||||
roi = src.roi(rect);
|
||||
|
||||
// Create a mask of logo and create its inverse mask also
|
||||
cv.cvtColor(logo, mask, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(mask, mask, 100, 255, cv.THRESH_BINARY);
|
||||
cv.bitwise_not(mask, maskInv);
|
||||
|
||||
// Black-out the area of logo in ROI
|
||||
cv.bitwise_and(roi, roi, imgBg, maskInv);
|
||||
|
||||
// Take only region of logo from logo image
|
||||
cv.bitwise_and(logo, logo, imgFg, mask);
|
||||
|
||||
// Put logo in ROI and modify the main image
|
||||
cv.add(imgBg, imgFg, sum);
|
||||
|
||||
dst = src.clone();
|
||||
for (let i = 0; i < logo.rows; i++) {
|
||||
for (let j = 0; j < logo.cols; j++) {
|
||||
dst.ucharPtr(i, j)[0] = sum.ucharPtr(i, j)[0];
|
||||
}
|
||||
}
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); logo.delete(); roi.delete(); mask.delete();
|
||||
maskInv.delete(); imgBg.delete(); imgFg.delete(); sum.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'imageCanvasInput');
|
||||
utils.loadImageToCanvas('lenaFace.png', 'logoCanvasInput');
|
||||
utils.addFileInputHandler('imageFileInput', 'imageCanvasInput');
|
||||
utils.addFileInputHandler('logoFileInput', 'logoCanvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Read and Show Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Read and Show Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="8" cols="80" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// To distinguish the input and output, we graying the image.
|
||||
// You can try different conversions.
|
||||
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete();
|
||||
dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,700 @@
|
||||
<!DOCTYPE html>
|
||||
<html >
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Processing Video Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
<style type="text/css">
|
||||
.dg {
|
||||
text-align: left;
|
||||
}
|
||||
.dg .property-name {
|
||||
font: 11px Lucida Grande,sans-serif;
|
||||
line-height: 27px;
|
||||
}
|
||||
.dg.main .close-button {
|
||||
font: 11px Lucida Grande,sans-serif;
|
||||
line-height: 27px;
|
||||
}
|
||||
.cell-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Processing Video Example</h2>
|
||||
<p>
|
||||
Open the controls and try different image processing filters.
|
||||
</p>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
<div id="container">
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<div>
|
||||
<span>Current Filter: </span><span id="filterName">Pass Through</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>Select Filter:</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="cell-top">
|
||||
<canvas id="canvasOutput" width="640" height="480"></canvas>
|
||||
</td>
|
||||
<td class="cell-top">
|
||||
<div id="guiContainer"></div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div>
|
||||
<video id="videoInput" class="hidden">Your browser does not support the video tag.</video>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js" type="text/javascript"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.4/dat.gui.min.js" type="text/javascript"></script>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
let width = 0;
|
||||
let height = 0;
|
||||
|
||||
let resolution = window.innerWidth < 960 ? 'qvga' : 'vga';
|
||||
|
||||
// whether streaming video from the camera.
|
||||
let streaming = false;
|
||||
|
||||
let video = document.getElementById('videoInput');
|
||||
let vc = null;
|
||||
|
||||
let container = document.getElementById('container');
|
||||
|
||||
let lastFilter = '';
|
||||
let src = null;
|
||||
let dstC1 = null;
|
||||
let dstC3 = null;
|
||||
let dstC4 = null;
|
||||
|
||||
function startVideoProcessing() {
|
||||
src = new cv.Mat(height, width, cv.CV_8UC4);
|
||||
dstC1 = new cv.Mat(height, width, cv.CV_8UC1);
|
||||
dstC3 = new cv.Mat(height, width, cv.CV_8UC3);
|
||||
dstC4 = new cv.Mat(height, width, cv.CV_8UC4);
|
||||
requestAnimationFrame(processVideo);
|
||||
}
|
||||
|
||||
function passThrough(src) {
|
||||
return src;
|
||||
}
|
||||
|
||||
function gray(src) {
|
||||
cv.cvtColor(src, dstC1, cv.COLOR_RGBA2GRAY);
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
function hsv(src) {
|
||||
cv.cvtColor(src, dstC3, cv.COLOR_RGBA2RGB);
|
||||
cv.cvtColor(dstC3, dstC3, cv.COLOR_RGB2HSV);
|
||||
return dstC3;
|
||||
}
|
||||
|
||||
function canny(src) {
|
||||
cv.cvtColor(src, dstC1, cv.COLOR_RGBA2GRAY);
|
||||
cv.Canny(dstC1, dstC1, controls.cannyThreshold1, controls.cannyThreshold2,
|
||||
controls.cannyApertureSize, controls.cannyL2Gradient);
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
function inRange(src) {
|
||||
let lowValue = controls.inRangeLow;
|
||||
let lowScalar = new cv.Scalar(lowValue, lowValue, lowValue, 255);
|
||||
let highValue = controls.inRangeHigh;
|
||||
let highScalar = new cv.Scalar(highValue, highValue, highValue, 255);
|
||||
let low = new cv.Mat(height, width, src.type(), lowScalar);
|
||||
let high = new cv.Mat(height, width, src.type(), highScalar);
|
||||
cv.inRange(src, low, high, dstC1);
|
||||
low.delete(); high.delete();
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
function threshold(src) {
|
||||
cv.threshold(src, dstC4, controls.thresholdValue, 200, cv.THRESH_BINARY);
|
||||
return dstC4;
|
||||
}
|
||||
|
||||
function adaptiveThreshold(src) {
|
||||
let mat = new cv.Mat(height, width, cv.CV_8U);
|
||||
cv.cvtColor(src, mat, cv.COLOR_RGBA2GRAY);
|
||||
cv.adaptiveThreshold(mat, dstC1, 200, cv.ADAPTIVE_THRESH_GAUSSIAN_C,
|
||||
cv.THRESH_BINARY, Number(controls.adaptiveBlockSize), 2);
|
||||
mat.delete();
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
function gaussianBlur(src) {
|
||||
cv.GaussianBlur(src, dstC4,
|
||||
{width: controls.gaussianBlurSize, height: controls.gaussianBlurSize},
|
||||
0, 0, cv.BORDER_DEFAULT);
|
||||
return dstC4;
|
||||
}
|
||||
|
||||
function bilateralFilter(src) {
|
||||
let mat = new cv.Mat(height, width, cv.CV_8UC3);
|
||||
cv.cvtColor(src, mat, cv.COLOR_RGBA2RGB);
|
||||
cv.bilateralFilter(mat, dstC3, controls.bilateralFilterDiameter, controls.bilateralFilterSigma,
|
||||
controls.bilateralFilterSigma, cv.BORDER_DEFAULT);
|
||||
mat.delete();
|
||||
return dstC3;
|
||||
}
|
||||
|
||||
function medianBlur(src) {
|
||||
cv.medianBlur(src, dstC4, controls.medianBlurSize);
|
||||
return dstC4;
|
||||
}
|
||||
|
||||
function sobel(src) {
|
||||
let mat = new cv.Mat(height, width, cv.CV_8UC1);
|
||||
cv.cvtColor(src, mat, cv.COLOR_RGB2GRAY, 0);
|
||||
cv.Sobel(mat, dstC1, cv.CV_8U, 1, 0, controls.sobelSize, 1, 0, cv.BORDER_DEFAULT);
|
||||
mat.delete();
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
function scharr(src) {
|
||||
let mat = new cv.Mat(height, width, cv.CV_8UC1);
|
||||
cv.cvtColor(src, mat, cv.COLOR_RGB2GRAY, 0);
|
||||
cv.Scharr(mat, dstC1, cv.CV_8U, 1, 0, 1, 0, cv.BORDER_DEFAULT);
|
||||
mat.delete();
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
function laplacian(src) {
|
||||
let mat = new cv.Mat(height, width, cv.CV_8UC1);
|
||||
cv.cvtColor(src, mat, cv.COLOR_RGB2GRAY);
|
||||
cv.Laplacian(mat, dstC1, cv.CV_8U, controls.laplacianSize, 1, 0, cv.BORDER_DEFAULT);
|
||||
mat.delete();
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
let contoursColor = [];
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
contoursColor.push([Math.round(Math.random() * 255),
|
||||
Math.round(Math.random() * 255),
|
||||
Math.round(Math.random() * 255), 0]);
|
||||
}
|
||||
|
||||
function contours(src) {
|
||||
cv.cvtColor(src, dstC1, cv.COLOR_RGBA2GRAY);
|
||||
cv.threshold(dstC1, dstC4, 120, 200, cv.THRESH_BINARY);
|
||||
let contours = new cv.MatVector();
|
||||
let hierarchy = new cv.Mat();
|
||||
cv.findContours(dstC4, contours, hierarchy,
|
||||
Number(controls.contoursMode),
|
||||
Number(controls.contoursMethod), {x: 0, y: 0});
|
||||
dstC3.delete();
|
||||
dstC3 = cv.Mat.ones(height, width, cv.CV_8UC3);
|
||||
for (let i = 0; i<contours.size(); ++i) {
|
||||
let color = contoursColor[i];
|
||||
cv.drawContours(dstC3, contours, i, color, 1, cv.LINE_8, hierarchy);
|
||||
}
|
||||
contours.delete(); hierarchy.delete();
|
||||
return dstC3;
|
||||
}
|
||||
|
||||
function calcHist(src) {
|
||||
cv.cvtColor(src, dstC1, cv.COLOR_RGBA2GRAY);
|
||||
let srcVec = new cv.MatVector();
|
||||
srcVec.push_back(dstC1);
|
||||
let scale = 2;
|
||||
let channels = [0];
|
||||
let histSize = [src.cols/scale];
|
||||
const ranges = [0, 255];
|
||||
let hist = new cv.Mat();
|
||||
let mask = new cv.Mat();
|
||||
let color = new cv.Scalar(0xfb, 0xca, 0x04, 0xff);
|
||||
cv.calcHist(srcVec, channels, mask, hist, histSize, ranges);
|
||||
let result = cv.minMaxLoc(hist, mask);
|
||||
let max = result.maxVal;
|
||||
cv.cvtColor(dstC1, dstC4, cv.COLOR_GRAY2RGBA);
|
||||
// draw histogram on src
|
||||
for (let i = 0; i < histSize[0]; i++) {
|
||||
let binVal = hist.data32F[i] * src.rows / max;
|
||||
cv.rectangle(dstC4, {x: i * scale, y: src.rows - 1},
|
||||
{x: (i + 1) * scale - 1, y: src.rows - binVal/3}, color, cv.FILLED);
|
||||
}
|
||||
srcVec.delete();
|
||||
mask.delete();
|
||||
hist.delete();
|
||||
return dstC4;
|
||||
}
|
||||
|
||||
function equalizeHist(src) {
|
||||
cv.cvtColor(src, dstC1, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.equalizeHist(dstC1, dstC1);
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
let base;
|
||||
|
||||
function backprojection(src) {
|
||||
if (lastFilter !== 'backprojection') {
|
||||
if (base instanceof cv.Mat) {
|
||||
base.delete();
|
||||
}
|
||||
base = src.clone();
|
||||
cv.cvtColor(base, base, cv.COLOR_RGB2HSV, 0);
|
||||
}
|
||||
cv.cvtColor(src, dstC3, cv.COLOR_RGB2HSV, 0);
|
||||
let baseVec = new cv.MatVector();
|
||||
let targetVec = new cv.MatVector();
|
||||
baseVec.push_back(base); targetVec.push_back(dstC3);
|
||||
let mask = new cv.Mat();
|
||||
let hist = new cv.Mat();
|
||||
let channels = [0];
|
||||
let histSize = [50];
|
||||
let ranges;
|
||||
if (controls.backprojectionRangeLow < controls.backprojectionRangeHigh) {
|
||||
ranges = [controls.backprojectionRangeLow, controls.backprojectionRangeHigh];
|
||||
} else {
|
||||
return src;
|
||||
}
|
||||
cv.calcHist(baseVec, channels, mask, hist, histSize, ranges);
|
||||
cv.normalize(hist, hist, 0, 255, cv.NORM_MINMAX);
|
||||
cv.calcBackProject(targetVec, channels, hist, dstC1, ranges, 1);
|
||||
baseVec.delete();
|
||||
targetVec.delete();
|
||||
mask.delete();
|
||||
hist.delete();
|
||||
return dstC1;
|
||||
}
|
||||
|
||||
function erosion(src) {
|
||||
let kernelSize = controls.erosionSize;
|
||||
let kernel = cv.Mat.ones(kernelSize, kernelSize, cv.CV_8U);
|
||||
let color = new cv.Scalar();
|
||||
cv.erode(src, dstC4, kernel, {x: -1, y: -1}, 1, Number(controls.erosionBorderType), color);
|
||||
kernel.delete();
|
||||
return dstC4;
|
||||
}
|
||||
|
||||
function dilation(src) {
|
||||
let kernelSize = controls.dilationSize;
|
||||
let kernel = cv.Mat.ones(kernelSize, kernelSize, cv.CV_8U);
|
||||
let color = new cv.Scalar();
|
||||
cv.dilate(src, dstC4, kernel, {x: -1, y: -1}, 1, Number(controls.dilationBorderType), color);
|
||||
kernel.delete();
|
||||
return dstC4;
|
||||
}
|
||||
|
||||
function morphology(src) {
|
||||
let kernelSize = controls.morphologySize;
|
||||
let kernel = cv.getStructuringElement(Number(controls.morphologyShape),
|
||||
{width: kernelSize, height: kernelSize});
|
||||
let color = new cv.Scalar();
|
||||
let op = Number(controls.morphologyOp);
|
||||
let image = src;
|
||||
if (op === cv.MORPH_GRADIENT || op === cv.MORPH_TOPHAT || op === cv.MORPH_BLACKHAT) {
|
||||
cv.cvtColor(src, dstC3, cv.COLOR_RGBA2RGB);
|
||||
image = dstC3;
|
||||
}
|
||||
cv.morphologyEx(image, dstC4, op, kernel, {x: -1, y: -1}, 1,
|
||||
Number(controls.morphologyBorderType), color);
|
||||
kernel.delete();
|
||||
return dstC4;
|
||||
}
|
||||
|
||||
function processVideo() {
|
||||
if (!streaming) return;
|
||||
stats.begin();
|
||||
vc.read(src);
|
||||
let result;
|
||||
switch (controls.filter) {
|
||||
case 'passThrough': result = passThrough(src); break;
|
||||
case 'gray': result = gray(src); break;
|
||||
case 'hsv': result = hsv(src); break;
|
||||
case 'canny': result = canny(src); break;
|
||||
case 'inRange': result = inRange(src); break;
|
||||
case 'threshold': result = threshold(src); break;
|
||||
case 'adaptiveThreshold': result = adaptiveThreshold(src); break;
|
||||
case 'gaussianBlur': result = gaussianBlur(src); break;
|
||||
case 'bilateralFilter': result = bilateralFilter(src); break;
|
||||
case 'medianBlur': result = medianBlur(src); break;
|
||||
case 'sobel': result = sobel(src); break;
|
||||
case 'scharr': result = scharr(src); break;
|
||||
case 'laplacian': result = laplacian(src); break;
|
||||
case 'contours': result = contours(src); break;
|
||||
case 'calcHist': result = calcHist(src); break;
|
||||
case 'equalizeHist': result = equalizeHist(src); break;
|
||||
case 'backprojection': result = backprojection(src); break;
|
||||
case 'erosion': result = erosion(src); break;
|
||||
case 'dilation': result = dilation(src); break;
|
||||
case 'morphology': result = morphology(src); break;
|
||||
default: result = passThrough(src);
|
||||
}
|
||||
cv.imshow('canvasOutput', result);
|
||||
stats.end();
|
||||
lastFilter = controls.filter;
|
||||
requestAnimationFrame(processVideo);
|
||||
}
|
||||
|
||||
let stats = null;
|
||||
|
||||
let filters = {
|
||||
'passThrough': 'Pass Through',
|
||||
'gray': 'Gray',
|
||||
'hsv': 'HSV',
|
||||
'canny': 'Canny Edge Detection',
|
||||
'inRange': 'In Range',
|
||||
'threshold': 'Threshold',
|
||||
'adaptiveThreshold': 'Adaptive Threshold',
|
||||
'gaussianBlur': 'Gaussian Blurring',
|
||||
'medianBlur': 'Median Blurring',
|
||||
'bilateralFilter': 'Bilateral Filtering',
|
||||
'sobel': 'Sobel Derivatives',
|
||||
'scharr': 'Scharr Derivatives',
|
||||
'laplacian': 'Laplacian Derivatives',
|
||||
'contours': 'Contours',
|
||||
'calcHist': 'Calculation',
|
||||
'equalizeHist': 'Equalization',
|
||||
'backprojection': 'Backprojection',
|
||||
'erosion': 'Erosion',
|
||||
'dilation': 'Dilation',
|
||||
'morphology': 'Morphology',
|
||||
};
|
||||
|
||||
let filterName = document.getElementById('filterName');
|
||||
|
||||
let controls;
|
||||
|
||||
function initUI() {
|
||||
stats = new Stats();
|
||||
stats.showPanel(0);
|
||||
container.appendChild(stats.domElement);
|
||||
stats.domElement.style.position = 'absolute';
|
||||
stats.domElement.style.right = '0px';
|
||||
stats.domElement.style.top = '0px';
|
||||
|
||||
controls = {
|
||||
filter: 'passThrough',
|
||||
setFilter: function(filter) {
|
||||
this.filter = filter;
|
||||
filterName.innerHTML = filters[filter];
|
||||
},
|
||||
passThrough: function() {
|
||||
this.setFilter('passThrough');
|
||||
},
|
||||
gray: function() {
|
||||
this.setFilter('gray');
|
||||
},
|
||||
hsv: function() {
|
||||
this.setFilter('hsv');
|
||||
},
|
||||
inRange: function() {
|
||||
this.setFilter('inRange');
|
||||
},
|
||||
inRangeLow: 75,
|
||||
inRangeHigh: 150,
|
||||
threshold: function() {
|
||||
this.setFilter('threshold');
|
||||
},
|
||||
thresholdValue: 100,
|
||||
adaptiveThreshold: function() {
|
||||
this.setFilter('adaptiveThreshold');
|
||||
},
|
||||
adaptiveBlockSize: 3,
|
||||
gaussianBlur: function() {
|
||||
this.setFilter('gaussianBlur');
|
||||
},
|
||||
gaussianBlurSize: 7,
|
||||
medianBlur: function() {
|
||||
this.setFilter('medianBlur');
|
||||
},
|
||||
medianBlurSize: 5,
|
||||
bilateralFilter: function() {
|
||||
this.setFilter('bilateralFilter');
|
||||
},
|
||||
bilateralFilterDiameter: 5,
|
||||
bilateralFilterSigma: 75,
|
||||
sobel: function() {
|
||||
this.setFilter('sobel');
|
||||
},
|
||||
sobelSize: 3,
|
||||
scharr: function() {
|
||||
this.setFilter('scharr');
|
||||
},
|
||||
laplacian: function() {
|
||||
this.setFilter('laplacian');
|
||||
},
|
||||
laplacianSize: 3,
|
||||
canny: function() {
|
||||
this.setFilter('canny');
|
||||
},
|
||||
cannyThreshold1: 150,
|
||||
cannyThreshold2: 300,
|
||||
cannyApertureSize: 3,
|
||||
cannyL2Gradient: false,
|
||||
contours: function() {
|
||||
this.setFilter('contours');
|
||||
},
|
||||
contoursMode: cv.RETR_CCOMP,
|
||||
contoursMethod: cv.CHAIN_APPROX_SIMPLE,
|
||||
calcHist: function() {
|
||||
this.setFilter('calcHist');
|
||||
},
|
||||
equalizeHist: function() {
|
||||
this.setFilter('equalizeHist');
|
||||
},
|
||||
backprojection: function() {
|
||||
this.setFilter('backprojection');
|
||||
},
|
||||
backprojectionRangeLow: 0,
|
||||
backprojectionRangeHigh: 150,
|
||||
morphology: function() {
|
||||
this.setFilter('morphology');
|
||||
},
|
||||
morphologyShape: cv.MORPH_RECT,
|
||||
morphologyOp: cv.MORPH_ERODE,
|
||||
morphologySize: 5,
|
||||
morphologyBorderType: cv.BORDER_CONSTANT,
|
||||
};
|
||||
|
||||
let gui = new dat.GUI({autoPlace: false});
|
||||
let guiContainer = document.getElementById('guiContainer');
|
||||
guiContainer.appendChild(gui.domElement);
|
||||
|
||||
let lastFolder = null;
|
||||
function closeLastFolder(folder) {
|
||||
if (lastFolder != null && lastFolder != folder) {
|
||||
lastFolder.close();
|
||||
}
|
||||
lastFolder = folder;
|
||||
}
|
||||
|
||||
gui.add(controls, 'passThrough').name(filters['passThrough']).onChange(function() {
|
||||
closeLastFolder(null);
|
||||
});
|
||||
|
||||
let colorConversion = gui.addFolder('Color Conversion');
|
||||
colorConversion.add(controls, 'gray').name(filters['gray']).onChange(function() {
|
||||
closeLastFolder(null);
|
||||
});
|
||||
|
||||
colorConversion.add(controls, 'hsv').name(filters['hsv']).onChange(function() {
|
||||
closeLastFolder(null);
|
||||
});
|
||||
|
||||
let inRange = colorConversion.addFolder(filters['inRange']);
|
||||
inRange.domElement.onclick = function() {
|
||||
closeLastFolder(inRange);
|
||||
controls.inRange();
|
||||
};
|
||||
inRange.add(controls, 'inRangeLow', 0, 255, 1).name('lower boundary');
|
||||
inRange.add(controls, 'inRangeHigh', 0, 255, 1).name('higher boundary');
|
||||
|
||||
// let geometricTransformations = gui.addFolder('Geometric Transformations');
|
||||
// TODO
|
||||
|
||||
let thresholding = gui.addFolder('Thresholding');
|
||||
|
||||
let threshold = thresholding.addFolder(filters['threshold']);
|
||||
threshold.domElement.onclick = function() {
|
||||
closeLastFolder(threshold);
|
||||
controls.threshold();
|
||||
};
|
||||
threshold.add(controls, 'thresholdValue', 0, 200, 1).name('threshold value');
|
||||
|
||||
let adaptiveThreshold = thresholding.addFolder(filters['adaptiveThreshold']);
|
||||
adaptiveThreshold.domElement.onclick = function() {
|
||||
closeLastFolder(adaptiveThreshold);
|
||||
controls.adaptiveThreshold();
|
||||
};
|
||||
adaptiveThreshold.add(
|
||||
controls, 'adaptiveBlockSize', 3, 99, 1).name('block size').onChange(
|
||||
function(value) {
|
||||
if (value % 2 === 0) controls.adaptiveBlockSize = value + 1;
|
||||
});
|
||||
|
||||
let smoothing = gui.addFolder('Smoothing');
|
||||
|
||||
let gaussianBlur = smoothing.addFolder(filters['gaussianBlur']);
|
||||
gaussianBlur.domElement.onclick = function() {
|
||||
closeLastFolder(gaussianBlur);
|
||||
controls.gaussianBlur();
|
||||
};
|
||||
gaussianBlur.add(
|
||||
controls, 'gaussianBlurSize', 7, 99, 1).name('kernel size').onChange(
|
||||
function(value) {
|
||||
if (value % 2 === 0) controls.gaussianBlurSize = value + 1;
|
||||
});
|
||||
|
||||
let medianBlur = smoothing.addFolder(filters['medianBlur']);
|
||||
medianBlur.domElement.onclick = function() {
|
||||
closeLastFolder(medianBlur);
|
||||
controls.medianBlur();
|
||||
};
|
||||
medianBlur.add(
|
||||
controls, 'medianBlurSize', 3, 99, 1).name('kernel size').onChange(
|
||||
function(value) {
|
||||
if (value % 2 === 0) controls.medianBlurSize = value + 1;
|
||||
});
|
||||
|
||||
let bilateralFilter = smoothing.addFolder(filters['bilateralFilter']);
|
||||
bilateralFilter.domElement.onclick = function() {
|
||||
closeLastFolder(bilateralFilter);
|
||||
controls.bilateralFilter();
|
||||
};
|
||||
bilateralFilter.add(controls, 'bilateralFilterDiameter', 1, 15, 1).name('diameter');
|
||||
bilateralFilter.add(controls, 'bilateralFilterSigma', 1, 255, 1).name('sigma');
|
||||
|
||||
let morphology = gui.addFolder('Morphology');
|
||||
morphology.domElement.onclick = function() {
|
||||
closeLastFolder(morphology);
|
||||
controls.morphology();
|
||||
};
|
||||
morphology.add(
|
||||
controls, 'morphologyOp',
|
||||
{'MORPH_ERODE': cv.MORPH_ERODE,
|
||||
'MORPH_DILATE': cv.MORPH_DILATE,
|
||||
'MORPH_OPEN ': cv.MORPH_OPEN,
|
||||
'MORPH_CLOSE': cv.MORPH_CLOSE,
|
||||
'MORPH_GRADIENT': cv.MORPH_GRADIENT,
|
||||
'MORPH_TOPHAT': cv.MORPH_TOPHAT,
|
||||
'MORPH_BLACKHAT': cv.MORPH_BLACKHAT}).name('operation');
|
||||
morphology.add(
|
||||
controls, 'morphologyShape',
|
||||
{'MORPH_RECT': cv.MORPH_RECT,
|
||||
'MORPH_CROSS': cv.MORPH_CROSS,
|
||||
'MORPH_ELLIPSE': cv.MORPH_ELLIPSE}).name('shape');
|
||||
morphology.add(
|
||||
controls, 'morphologySize', 1, 15, 1).name('kernel size').onChange(
|
||||
function(value) {
|
||||
if (value % 2 === 0) controls.morphologySize = value + 1;
|
||||
});
|
||||
morphology.add(
|
||||
controls, 'morphologyBorderType',
|
||||
{'BORDER_CONSTANT': cv.BORDER_CONSTANT,
|
||||
'BORDER_REPLICATE': cv.BORDER_REPLICATE,
|
||||
'BORDER_REFLECT': cv.BORDER_REFLECT,
|
||||
'BORDER_REFLECT_101': cv.BORDER_REFLECT_101}).name('boarder type');
|
||||
|
||||
let gradients = gui.addFolder('Gradients');
|
||||
let sobel = gradients.addFolder(filters['sobel']);
|
||||
sobel.domElement.onclick = function() {
|
||||
closeLastFolder(sobel);
|
||||
controls.sobel();
|
||||
};
|
||||
sobel.add(controls, 'sobelSize', 3, 19, 1).name('kernel size').onChange(function(value) {
|
||||
if (value % 2 === 0) controls.sobelSize = value + 1;
|
||||
});
|
||||
|
||||
gradients.add(controls, 'scharr').name(filters['scharr']).onChange(function() {
|
||||
closeLastFolder(null);
|
||||
});
|
||||
|
||||
let laplacian = gradients.addFolder(filters['laplacian']);
|
||||
laplacian.domElement.onclick = function() {
|
||||
closeLastFolder(laplacian);
|
||||
controls.laplacian();
|
||||
};
|
||||
laplacian.add(
|
||||
controls, 'laplacianSize', 1, 19, 1).name('kernel size').onChange(
|
||||
function(value) {
|
||||
if (value % 2 === 0) controls.laplacianSize = value + 1;
|
||||
});
|
||||
|
||||
let canny = gui.addFolder(filters['canny']);
|
||||
canny.domElement.onclick = function() {
|
||||
closeLastFolder(canny);
|
||||
controls.canny();
|
||||
};
|
||||
canny.add(controls, 'cannyThreshold1', 1, 500, 1).name('threshold1');
|
||||
canny.add(controls, 'cannyThreshold2', 1, 500, 1).name('threshold2');
|
||||
canny.add(controls, 'cannyApertureSize', 3, 7, 1).name('aperture size').onChange(
|
||||
function(value) {
|
||||
if (value % 2 === 0) controls.cannyApertureSize = value + 1;
|
||||
});
|
||||
canny.add(controls, 'cannyL2Gradient').name('l2 gradient');
|
||||
|
||||
let contours = gui.addFolder(filters['contours']);
|
||||
contours.domElement.onclick = function() {
|
||||
closeLastFolder(contours);
|
||||
controls.contours();
|
||||
};
|
||||
contours.add(
|
||||
controls, 'contoursMode',
|
||||
{'RETR_EXTERNAL': cv.RETR_EXTERNAL,
|
||||
'RETR_LIST': cv.RETR_LIST,
|
||||
'RETR_CCOMP': cv.RETR_CCOMP,
|
||||
'RETR_TREE': cv.RETR_TREE}).name('mode');
|
||||
contours.add(
|
||||
controls, 'contoursMethod',
|
||||
{'CHAIN_APPROX_NONE': cv.CHAIN_APPROX_NONE,
|
||||
'CHAIN_APPROX_SIMPLE': cv.CHAIN_APPROX_SIMPLE,
|
||||
'CHAIN_APPROX_TC89_L1': cv.CHAIN_APPROX_TC89_L1,
|
||||
'CHAIN_APPROX_TC89_KCOS': cv.CHAIN_APPROX_TC89_KCOS}).name('method');
|
||||
|
||||
let histograms = gui.addFolder('Histograms');
|
||||
histograms.add(controls, 'calcHist').name(filters['calcHist']).onChange(function() {
|
||||
closeLastFolder(null);
|
||||
});
|
||||
histograms.add(controls, 'equalizeHist').name(filters['equalizeHist']).onChange(function() {
|
||||
closeLastFolder(null);
|
||||
});
|
||||
|
||||
let backprojection = histograms.addFolder(filters['backprojection']);
|
||||
backprojection.domElement.onclick = function() {
|
||||
closeLastFolder(backprojection);
|
||||
controls.backprojection();
|
||||
};
|
||||
backprojection.add(controls, 'backprojectionRangeLow', 0, 255, 1).name('range low');
|
||||
backprojection.add(controls, 'backprojectionRangeHigh', 0, 255, 1).name('range high');
|
||||
}
|
||||
|
||||
function startCamera() {
|
||||
if (!streaming) {
|
||||
utils.clearError();
|
||||
utils.startCamera(resolution, onVideoStarted, 'videoInput');
|
||||
} else {
|
||||
utils.stopCamera();
|
||||
onVideoStopped();
|
||||
}
|
||||
}
|
||||
|
||||
function onVideoStarted() {
|
||||
height = video.videoHeight;
|
||||
width = video.videoWidth;
|
||||
video.setAttribute('width', width);
|
||||
video.setAttribute('height', height);
|
||||
streaming = true;
|
||||
vc = new cv.VideoCapture(video);
|
||||
startVideoProcessing();
|
||||
}
|
||||
|
||||
function stopVideoProcessing() {
|
||||
if (src != null && !src.isDeleted()) src.delete();
|
||||
if (dstC1 != null && !dstC1.isDeleted()) dstC1.delete();
|
||||
if (dstC3 != null && !dstC3.isDeleted()) dstC3.delete();
|
||||
if (dstC4 != null && !dstC4.isDeleted()) dstC4.delete();
|
||||
}
|
||||
|
||||
function onVideoStopped() {
|
||||
if (!streaming) return;
|
||||
stopVideoProcessing();
|
||||
document.getElementById('canvasOutput').getContext('2d').clearRect(0, 0, width, height);
|
||||
streaming = false;
|
||||
}
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
initUI();
|
||||
startCamera();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
170
Lib/opencv/sources/doc/js_tutorials/js_assets/js_meanshift.html
Normal file
@@ -0,0 +1,170 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>MeanShift Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>MeanShift Example</h2>
|
||||
<p>
|
||||
Click <b>Start/Stop</b> button to start or stop the video.<br>
|
||||
The <b>videoInput</b> is a <video> element used as meanShift input.
|
||||
The <b>canvasOutput</b> is a <canvas> element used as meanShift output.<br>
|
||||
The code of <textarea> will be executed when video is started.
|
||||
You can modify the code to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="startAndStop" disabled>Start</button></div>
|
||||
<textarea class="code" rows="29" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
</div>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<video id="videoInput" width="320" height="240" muted loop></video>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" width="320" height="240" ></canvas>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">videoInput</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let video = document.getElementById('videoInput');
|
||||
let cap = new cv.VideoCapture(video);
|
||||
|
||||
// take first frame of the video
|
||||
let frame = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
cap.read(frame);
|
||||
|
||||
// hardcode the initial location of window
|
||||
let trackWindow = new cv.Rect(150, 60, 63, 125);
|
||||
|
||||
// set up the ROI for tracking
|
||||
let roi = frame.roi(trackWindow);
|
||||
let hsvRoi = new cv.Mat();
|
||||
cv.cvtColor(roi, hsvRoi, cv.COLOR_RGBA2RGB);
|
||||
cv.cvtColor(hsvRoi, hsvRoi, cv.COLOR_RGB2HSV);
|
||||
let mask = new cv.Mat();
|
||||
let lowScalar = new cv.Scalar(30, 30, 0);
|
||||
let highScalar = new cv.Scalar(180, 180, 180);
|
||||
let low = new cv.Mat(hsvRoi.rows, hsvRoi.cols, hsvRoi.type(), lowScalar);
|
||||
let high = new cv.Mat(hsvRoi.rows, hsvRoi.cols, hsvRoi.type(), highScalar);
|
||||
cv.inRange(hsvRoi, low, high, mask);
|
||||
let roiHist = new cv.Mat();
|
||||
let hsvRoiVec = new cv.MatVector();
|
||||
hsvRoiVec.push_back(hsvRoi);
|
||||
cv.calcHist(hsvRoiVec, [0], mask, roiHist, [180], [0, 180]);
|
||||
cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX);
|
||||
|
||||
// delete useless mats.
|
||||
roi.delete(); hsvRoi.delete(); mask.delete(); low.delete(); high.delete(); hsvRoiVec.delete();
|
||||
|
||||
// Setup the termination criteria, either 10 iteration or move by atleast 1 pt
|
||||
let termCrit = new cv.TermCriteria(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1);
|
||||
|
||||
let hsv = new cv.Mat(video.height, video.width, cv.CV_8UC3);
|
||||
let dst = new cv.Mat();
|
||||
let hsvVec = new cv.MatVector();
|
||||
hsvVec.push_back(hsv);
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
try {
|
||||
if (!streaming) {
|
||||
// clean and stop.
|
||||
frame.delete(); dst.delete(); hsvVec.delete(); roiHist.delete(); hsv.delete();
|
||||
return;
|
||||
}
|
||||
let begin = Date.now();
|
||||
|
||||
// start processing.
|
||||
cap.read(frame);
|
||||
cv.cvtColor(frame, hsv, cv.COLOR_RGBA2RGB);
|
||||
cv.cvtColor(hsv, hsv, cv.COLOR_RGB2HSV);
|
||||
cv.calcBackProject(hsvVec, [0], roiHist, dst, [0, 180], 1);
|
||||
|
||||
// Apply meanshift to get the new location
|
||||
// and it also returns number of iterations meanShift took to converge,
|
||||
// which is useless in this demo.
|
||||
[, trackWindow] = cv.meanShift(dst, trackWindow, termCrit);
|
||||
|
||||
// Draw it on image
|
||||
let [x, y, w, h] = [trackWindow.x, trackWindow.y, trackWindow.width, trackWindow.height];
|
||||
cv.rectangle(frame, new cv.Point(x, y), new cv.Point(x+w, y+h), [255, 0, 0, 255], 2);
|
||||
cv.imshow('canvasOutput', frame);
|
||||
|
||||
// schedule the next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
} catch (err) {
|
||||
utils.printError(err);
|
||||
}
|
||||
};
|
||||
|
||||
// schedule the first one.
|
||||
setTimeout(processVideo, 0);
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
|
||||
let streaming = false;
|
||||
let videoInput = document.getElementById('videoInput');
|
||||
let startAndStop = document.getElementById('startAndStop');
|
||||
let canvasOutput = document.getElementById('canvasOutput');
|
||||
let canvasContext = canvasOutput.getContext('2d');
|
||||
|
||||
startAndStop.addEventListener('click', () => {
|
||||
if (!streaming) {
|
||||
utils.clearError();
|
||||
videoInput.play().then(() => {
|
||||
onVideoStarted();
|
||||
});
|
||||
} else {
|
||||
videoInput.pause();
|
||||
videoInput.currentTime = 0;
|
||||
onVideoStopped();
|
||||
}
|
||||
});
|
||||
|
||||
function onVideoStarted() {
|
||||
streaming = true;
|
||||
startAndStop.innerText = 'Stop';
|
||||
videoInput.height = videoInput.width * (videoInput.videoHeight / videoInput.videoWidth);
|
||||
utils.executeCode('codeEditor');
|
||||
}
|
||||
|
||||
function onVideoStopped() {
|
||||
streaming = false;
|
||||
canvasContext.clearRect(0, 0, canvasOutput.width, canvasOutput.height);
|
||||
startAndStop.innerText = 'Start';
|
||||
}
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
videoInput.addEventListener('canplay', () => {
|
||||
startAndStop.removeAttribute('disabled');
|
||||
});
|
||||
videoInput.src = 'cup.mp4';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Black Hat Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Black Hat Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB);
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.Mat.ones(53, 53, cv.CV_8U);
|
||||
// You can try more different parameters
|
||||
cv.morphologyEx(src, dst, cv.MORPH_BLACKHAT, M);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Closing Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Closing Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.Mat.ones(5, 5, cv.CV_8U);
|
||||
// You can try more different parameters
|
||||
cv.morphologyEx(src, dst, cv.MORPH_CLOSE, M);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Dilate Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Dilate Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.Mat.ones(5, 5, cv.CV_8U);
|
||||
let anchor = new cv.Point(-1, -1);
|
||||
// You can try more different parameters
|
||||
cv.dilate(src, dst, M, anchor, 1, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Erode Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Erode Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.Mat.ones(5, 5, cv.CV_8U);
|
||||
let anchor = new cv.Point(-1, -1);
|
||||
// You can try more different parameters
|
||||
cv.erode(src, dst, M, anchor, 1, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Get Structuring Element Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Get Structuring Element Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB);
|
||||
let dst = new cv.Mat();
|
||||
let M = new cv.Mat();
|
||||
let ksize = new cv.Size(5, 5);
|
||||
// You can try more different parameters
|
||||
M = cv.getStructuringElement(cv.MORPH_CROSS, ksize);
|
||||
cv.morphologyEx(src, dst, cv.MORPH_GRADIENT, M);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Gradient Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Gradient Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB);
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.Mat.ones(5, 5, cv.CV_8U);
|
||||
// You can try more different parameters
|
||||
cv.morphologyEx(src, dst, cv.MORPH_GRADIENT, M);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Opening Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Opening Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.Mat.ones(5, 5, cv.CV_8U);
|
||||
let anchor = new cv.Point(-1, -1);
|
||||
// You can try more different parameters
|
||||
cv.morphologyEx(src, dst, cv.MORPH_OPEN, M, anchor, 1,
|
||||
cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Top Hat Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Top Hat Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB);
|
||||
let dst = new cv.Mat();
|
||||
let M = cv.Mat.ones(9, 9, cv.CV_8U);
|
||||
// You can try more different parameters
|
||||
cv.morphologyEx(src, dst, cv.MORPH_TOPHAT, M);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('shape.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,163 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Dense Optical Flow Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Dense Optical Flow Example</h2>
|
||||
<p>
|
||||
Click <b>Start/Stop</b> button to start or stop the video.<br>
|
||||
The <b>videoInput</b> is a <video> element used as input.
|
||||
The <b>canvasOutput</b> is a <canvas> element used as output.<br>
|
||||
We get a 2-channel array with optical flow vectors, (u,v). We find their magnitude and direction.
|
||||
We color code the result for better visualization. Direction corresponds to Hue value of the image.
|
||||
Magnitude corresponds to Value plane.<br>
|
||||
The code of <textarea> will be executed when video is started.<br>
|
||||
You can modify the code to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="startAndStop" disabled>Start</button></div>
|
||||
<textarea class="code" rows="29" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
</div>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<video id="videoInput" width="320" height="240" muted></video>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" width="320" height="240" ></canvas>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">videoInput</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let video = document.getElementById('videoInput');
|
||||
let cap = new cv.VideoCapture(video);
|
||||
|
||||
// take first frame of the video
|
||||
let frame1 = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
cap.read(frame1);
|
||||
|
||||
let prvs = new cv.Mat();
|
||||
cv.cvtColor(frame1, prvs, cv.COLOR_RGBA2GRAY);
|
||||
frame1.delete();
|
||||
let hsv = new cv.Mat();
|
||||
let hsv0 = new cv.Mat(video.height, video.width, cv.CV_8UC1);
|
||||
let hsv1 = new cv.Mat(video.height, video.width, cv.CV_8UC1, new cv.Scalar(255));
|
||||
let hsv2 = new cv.Mat(video.height, video.width, cv.CV_8UC1);
|
||||
let hsvVec = new cv.MatVector();
|
||||
hsvVec.push_back(hsv0); hsvVec.push_back(hsv1); hsvVec.push_back(hsv2);
|
||||
|
||||
let frame2 = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
let next = new cv.Mat(video.height, video.width, cv.CV_8UC1);
|
||||
let flow = new cv.Mat(video.height, video.width, cv.CV_32FC2);
|
||||
let flowVec = new cv.MatVector();
|
||||
let mag = new cv.Mat(video.height, video.width, cv.CV_32FC1);
|
||||
let ang = new cv.Mat(video.height, video.width, cv.CV_32FC1);
|
||||
let rgb = new cv.Mat(video.height, video.width, cv.CV_8UC3);
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
try {
|
||||
if (!streaming) {
|
||||
// clean and stop.
|
||||
prvs.delete(); hsv.delete(); hsv0.delete(); hsv1.delete(); hsv2.delete();
|
||||
hsvVec.delete(); frame2.delete(); flow.delete(); flowVec.delete(); next.delete();
|
||||
mag.delete(); ang.delete(); rgb.delete();
|
||||
return;
|
||||
}
|
||||
let begin = Date.now();
|
||||
|
||||
// start processing.
|
||||
cap.read(frame2);
|
||||
cv.cvtColor(frame2, next, cv.COLOR_RGBA2GRAY);
|
||||
cv.calcOpticalFlowFarneback(prvs, next, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
|
||||
cv.split(flow, flowVec);
|
||||
let u = flowVec.get(0);
|
||||
let v = flowVec.get(1);
|
||||
cv.cartToPolar(u, v, mag, ang);
|
||||
u.delete(); v.delete();
|
||||
ang.convertTo(hsv0, cv.CV_8UC1, 180/Math.PI/2);
|
||||
cv.normalize(mag, hsv2, 0, 255, cv.NORM_MINMAX, cv.CV_8UC1);
|
||||
cv.merge(hsvVec, hsv);
|
||||
cv.cvtColor(hsv, rgb, cv.COLOR_HSV2RGB);
|
||||
cv.imshow('canvasOutput', rgb);
|
||||
next.copyTo(prvs);
|
||||
|
||||
// schedule the next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
} catch (err) {
|
||||
utils.printError(err);
|
||||
}
|
||||
};
|
||||
|
||||
// schedule the first one.
|
||||
setTimeout(processVideo, 0);
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
|
||||
let streaming = false;
|
||||
let videoInput = document.getElementById('videoInput');
|
||||
let startAndStop = document.getElementById('startAndStop');
|
||||
|
||||
startAndStop.addEventListener('click', () => {
|
||||
if (!streaming) {
|
||||
utils.clearError();
|
||||
videoInput.play().then(() => {
|
||||
onVideoStarted();
|
||||
});
|
||||
} else {
|
||||
videoInput.pause();
|
||||
videoInput.currentTime = 0;
|
||||
onVideoStopped();
|
||||
}
|
||||
});
|
||||
|
||||
function onVideoStarted() {
|
||||
streaming = true;
|
||||
startAndStop.innerText = 'Stop';
|
||||
videoInput.height = videoInput.width * (videoInput.videoHeight / videoInput.videoWidth);
|
||||
utils.executeCode('codeEditor');
|
||||
}
|
||||
|
||||
function onVideoStopped() {
|
||||
streaming = false;
|
||||
startAndStop.innerText = 'Start';
|
||||
}
|
||||
|
||||
videoInput.addEventListener('ended', () => {
|
||||
onVideoStopped();
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
videoInput.addEventListener('canplay', () => {
|
||||
startAndStop.removeAttribute('disabled');
|
||||
});
|
||||
videoInput.src = 'box.mp4';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,190 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Lucas-Kanade Optical Flow Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Lucas-Kanade Optical Flow Example</h2>
|
||||
<p>
|
||||
Click <b>Start/Stop</b> button to start or stop the video.<br>
|
||||
The <b>videoInput</b> is a <video> element used as input.
|
||||
The <b>canvasOutput</b> is a <canvas> element used as output.<br>
|
||||
To decide the points, we use <b>cv.goodFeaturesToTrack()</b>. We take the first frame, detect some Shi-Tomasi corner points in it, then we iteratively track those points using <b>cv.calcOpticalFlowPyrLK</b>.<br>
|
||||
The code of <textarea> will be executed when video is started.<br>
|
||||
You can modify the code to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="startAndStop" disabled>Start</button></div>
|
||||
<textarea class="code" rows="29" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
</div>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<video id="videoInput" width="320" height="240" muted></video>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" width="320" height="240" ></canvas>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">videoInput</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let video = document.getElementById('videoInput');
|
||||
let cap = new cv.VideoCapture(video);
|
||||
|
||||
// parameters for ShiTomasi corner detection
|
||||
let [maxCorners, qualityLevel, minDistance, blockSize] = [30, 0.3, 7, 7];
|
||||
|
||||
// parameters for lucas kanade optical flow
|
||||
let winSize = new cv.Size(15, 15);
|
||||
let maxLevel = 2;
|
||||
let criteria = new cv.TermCriteria(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03);
|
||||
|
||||
// create some random colors
|
||||
let color = [];
|
||||
for (let i = 0; i < maxCorners; i++) {
|
||||
color.push(new cv.Scalar(parseInt(Math.random()*255), parseInt(Math.random()*255),
|
||||
parseInt(Math.random()*255), 255));
|
||||
}
|
||||
|
||||
// take first frame and find corners in it
|
||||
let oldFrame = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
cap.read(oldFrame);
|
||||
let oldGray = new cv.Mat();
|
||||
cv.cvtColor(oldFrame, oldGray, cv.COLOR_RGB2GRAY);
|
||||
let p0 = new cv.Mat();
|
||||
let none = new cv.Mat();
|
||||
cv.goodFeaturesToTrack(oldGray, p0, maxCorners, qualityLevel, minDistance, none, blockSize);
|
||||
|
||||
// Create a mask image for drawing purposes
|
||||
let zeroEle = new cv.Scalar(0, 0, 0, 255);
|
||||
let mask = new cv.Mat(oldFrame.rows, oldFrame.cols, oldFrame.type(), zeroEle);
|
||||
|
||||
let frame = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
let frameGray = new cv.Mat();
|
||||
let p1 = new cv.Mat();
|
||||
let st = new cv.Mat();
|
||||
let err = new cv.Mat();
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
try {
|
||||
if (!streaming) {
|
||||
// clean and stop.
|
||||
frame.delete(); oldGray.delete(); p0.delete(); p1.delete(); err.delete(); mask.delete();
|
||||
return;
|
||||
}
|
||||
let begin = Date.now();
|
||||
|
||||
// start processing.
|
||||
cap.read(frame);
|
||||
cv.cvtColor(frame, frameGray, cv.COLOR_RGBA2GRAY);
|
||||
|
||||
// calculate optical flow
|
||||
cv.calcOpticalFlowPyrLK(oldGray, frameGray, p0, p1, st, err, winSize, maxLevel, criteria);
|
||||
|
||||
// select good points
|
||||
let goodNew = [];
|
||||
let goodOld = [];
|
||||
for (let i = 0; i < st.rows; i++) {
|
||||
if (st.data[i] === 1) {
|
||||
goodNew.push(new cv.Point(p1.data32F[i*2], p1.data32F[i*2+1]));
|
||||
goodOld.push(new cv.Point(p0.data32F[i*2], p0.data32F[i*2+1]));
|
||||
}
|
||||
}
|
||||
|
||||
// draw the tracks
|
||||
for (let i = 0; i < goodNew.length; i++) {
|
||||
cv.line(mask, goodNew[i], goodOld[i], color[i], 2);
|
||||
cv.circle(frame, goodNew[i], 5, color[i], -1);
|
||||
}
|
||||
cv.add(frame, mask, frame);
|
||||
|
||||
cv.imshow('canvasOutput', frame);
|
||||
|
||||
// now update the previous frame and previous points
|
||||
frameGray.copyTo(oldGray);
|
||||
p0.delete(); p0 = null;
|
||||
p0 = new cv.Mat(goodNew.length, 1, cv.CV_32FC2);
|
||||
for (let i = 0; i < goodNew.length; i++) {
|
||||
p0.data32F[i*2] = goodNew[i].x;
|
||||
p0.data32F[i*2+1] = goodNew[i].y;
|
||||
}
|
||||
|
||||
// schedule the next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
} catch (err) {
|
||||
utils.printError(err);
|
||||
}
|
||||
};
|
||||
|
||||
// schedule the first one.
|
||||
setTimeout(processVideo, 0);
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
|
||||
let streaming = false;
|
||||
let videoInput = document.getElementById('videoInput');
|
||||
let startAndStop = document.getElementById('startAndStop');
|
||||
|
||||
startAndStop.addEventListener('click', () => {
|
||||
if (!streaming) {
|
||||
utils.clearError();
|
||||
videoInput.play().then(() => {
|
||||
onVideoStarted();
|
||||
});
|
||||
} else {
|
||||
videoInput.pause();
|
||||
videoInput.currentTime = 0;
|
||||
onVideoStopped();
|
||||
}
|
||||
});
|
||||
|
||||
function onVideoStarted() {
|
||||
streaming = true;
|
||||
startAndStop.innerText = 'Stop';
|
||||
videoInput.height = videoInput.width * (videoInput.videoHeight / videoInput.videoWidth);
|
||||
utils.executeCode('codeEditor');
|
||||
}
|
||||
|
||||
function onVideoStopped() {
|
||||
streaming = false;
|
||||
startAndStop.innerText = 'Start';
|
||||
}
|
||||
|
||||
videoInput.addEventListener('ended', () => {
|
||||
onVideoStopped();
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
videoInput.addEventListener('canplay', () => {
|
||||
startAndStop.removeAttribute('disabled');
|
||||
});
|
||||
videoInput.src = 'box.mp4';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image PyrDown Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image PyrDown Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// You can try more different parameters
|
||||
cv.pyrDown(src, dst, new cv.Size(0, 0), cv.BORDER_DEFAULT);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image PyrUp Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image PyrUp Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// You can try more different parameters
|
||||
cv.pyrUp(src, dst, new cv.Size(0, 0), cv.BORDER_DEFAULT);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete(); dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Hello OpenCV.js</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Hello OpenCV.js</h2>
|
||||
<p id="status">OpenCV.js is loading...</p>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<img id="imageSrc" alt="No Image" class="small" />
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" class="small" height="300px"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">imageSrc <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
let imgElement = document.getElementById('imageSrc');
|
||||
let inputElement = document.getElementById('fileInput');
|
||||
inputElement.addEventListener('change', (e) => {
|
||||
imgElement.src = URL.createObjectURL(e.target.files[0]);
|
||||
}, false);
|
||||
|
||||
imgElement.onload = function() {
|
||||
let mat = cv.imread(imgElement);
|
||||
cv.imshow('canvasOutput', mat);
|
||||
mat.delete();
|
||||
};
|
||||
|
||||
function onOpenCvReady() { // eslint-disable-line no-unused-vars
|
||||
document.getElementById('status').innerHTML = '<b>OpenCV.js is ready</b>.' +
|
||||
'You can upload an image.<br>' +
|
||||
'The <b>imageSrc</b> is a <img> element used as cv.Mat input. ' +
|
||||
'The <b>canvasOutput</b> is a <canvas> element used as cv.Mat output.';
|
||||
}
|
||||
|
||||
function onOpenCvError() { // eslint-disable-line no-unused-vars
|
||||
let element = document.getElementById('status');
|
||||
element.setAttribute('class', 'err');
|
||||
element.innerHTML = 'Failed to load opencv.js';
|
||||
}
|
||||
</script>
|
||||
<script async src="opencv.js" type="text/javascript" onload="onOpenCvReady();" onerror="onOpenCvError();"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Template Match Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Template Match Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>imageCanvasInput</b>, <b>templateCanvasInput</b>
|
||||
and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="imageCanvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">imageCanvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="templateCanvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">templateCanvasInput <input type="file" id="templateFileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('imageCanvasInput');
|
||||
let templ = cv.imread('templateCanvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let mask = new cv.Mat();
|
||||
cv.matchTemplate(src, templ, dst, cv.TM_CCOEFF, mask);
|
||||
let result = cv.minMaxLoc(dst, mask);
|
||||
let maxPoint = result.maxLoc;
|
||||
let color = new cv.Scalar(255, 0, 0, 255);
|
||||
let point = new cv.Point(maxPoint.x + templ.cols, maxPoint.y + templ.rows);
|
||||
cv.rectangle(src, maxPoint, point, color, 2, cv.LINE_8, 0);
|
||||
cv.imshow('canvasOutput', src);
|
||||
src.delete(); dst.delete(); mask.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'imageCanvasInput');
|
||||
utils.loadImageToCanvas('lenaFace.png', 'templateCanvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Adaptive Threshold Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Adaptive Threshold Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
|
||||
// You can try more different parameters
|
||||
cv.adaptiveThreshold(src, dst, 200, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 3, 2);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete();
|
||||
dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Threshold Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Threshold Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
// You can try more different parameters
|
||||
cv.threshold(src, dst, 177, 200, cv.THRESH_BINARY);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
src.delete();
|
||||
dst.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('lena.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Trackbar Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Trackbar Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput1</b>, <b>canvasInput2</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
The code of <textarea> will be executed when <input> element named <b>trackbar</b> value changes.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<textarea class="code" rows="12" cols="80" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<b>trackbar</b>
|
||||
<input type="range" id="trackbar" disabled value="50" min="0" max="100" step="1">
|
||||
<label id="weightValue" ></label>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput1" class="small"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasInput2" class="small"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" class="small"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput1</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasInput2</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let trackbar = document.getElementById('trackbar');
|
||||
let alpha = trackbar.value/trackbar.max;
|
||||
let beta = ( 1.0 - alpha );
|
||||
let src1 = cv.imread('canvasInput1');
|
||||
let src2 = cv.imread('canvasInput2');
|
||||
let dst = new cv.Mat();
|
||||
cv.addWeighted( src1, alpha, src2, beta, 0.0, dst, -1);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
dst.delete();
|
||||
src1.delete();
|
||||
src2.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('apple.jpg', 'canvasInput1');
|
||||
utils.loadImageToCanvas('orange.jpg', 'canvasInput2');
|
||||
|
||||
let trackbar = document.getElementById('trackbar');
|
||||
trackbar.addEventListener('input', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
let weightValue = document.getElementById('weightValue');
|
||||
weightValue.innerText = trackbar.value;
|
||||
trackbar.addEventListener('input', () => {
|
||||
weightValue.innerText = trackbar.value;
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
trackbar.removeAttribute('disabled');
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,120 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Video Capture Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Video Capture Example</h2>
|
||||
<p>
|
||||
Click <b>Start/Stop</b> button to start or stop the camera capture.<br>
|
||||
The <b>videoInput</b> is a <video> element used as OpenCV.js input.
|
||||
The <b>canvasOutput</b> is a <canvas> element used as OpenCv.js output.<br>
|
||||
The code of <textarea> will be executed when video is started.
|
||||
You can modify the code to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="startAndStop" disabled>Start</button></div>
|
||||
<textarea class="code" rows="29" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
</div>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<video id="videoInput" width=320 height=240></video>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput" width=320 height=240></canvas>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">videoInput</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let video = document.getElementById('videoInput');
|
||||
let src = new cv.Mat(video.height, video.width, cv.CV_8UC4);
|
||||
let dst = new cv.Mat(video.height, video.width, cv.CV_8UC1);
|
||||
let cap = new cv.VideoCapture(video);
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
try {
|
||||
if (!streaming) {
|
||||
// clean and stop.
|
||||
src.delete();
|
||||
dst.delete();
|
||||
return;
|
||||
}
|
||||
let begin = Date.now();
|
||||
// start processing.
|
||||
cap.read(src);
|
||||
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
// schedule the next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
} catch (err) {
|
||||
utils.printError(err);
|
||||
}
|
||||
};
|
||||
|
||||
// schedule the first one.
|
||||
setTimeout(processVideo, 0);
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
|
||||
let streaming = false;
|
||||
let videoInput = document.getElementById('videoInput');
|
||||
let startAndStop = document.getElementById('startAndStop');
|
||||
let canvasOutput = document.getElementById('canvasOutput');
|
||||
let canvasContext = canvasOutput.getContext('2d');
|
||||
|
||||
startAndStop.addEventListener('click', () => {
|
||||
if (!streaming) {
|
||||
utils.clearError();
|
||||
utils.startCamera('qvga', onVideoStarted, 'videoInput');
|
||||
} else {
|
||||
utils.stopCamera();
|
||||
onVideoStopped();
|
||||
}
|
||||
});
|
||||
|
||||
function onVideoStarted() {
|
||||
streaming = true;
|
||||
startAndStop.innerText = 'Stop';
|
||||
videoInput.width = videoInput.videoWidth;
|
||||
videoInput.height = videoInput.videoHeight;
|
||||
utils.executeCode('codeEditor');
|
||||
}
|
||||
|
||||
function onVideoStopped() {
|
||||
streaming = false;
|
||||
canvasContext.clearRect(0, 0, canvasOutput.width, canvasOutput.height);
|
||||
startAndStop.innerText = 'Start';
|
||||
}
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
startAndStop.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Background Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Background Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let gray = new cv.Mat();
|
||||
let opening = new cv.Mat();
|
||||
let coinsBg = new cv.Mat();
|
||||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
|
||||
|
||||
// get background
|
||||
let M = cv.Mat.ones(3, 3, cv.CV_8U);
|
||||
cv.erode(gray, gray, M);
|
||||
cv.dilate(gray, opening, M);
|
||||
cv.dilate(opening, coinsBg, M, new cv.Point(-1, -1), 3);
|
||||
|
||||
cv.imshow('canvasOutput', coinsBg);
|
||||
src.delete(); dst.delete(); gray.delete(); opening.delete(); coinsBg.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('coins.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Distance Transform Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Distance Transform Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let gray = new cv.Mat();
|
||||
let opening = new cv.Mat();
|
||||
let coinsBg = new cv.Mat();
|
||||
let coinsFg = new cv.Mat();
|
||||
let distTrans = new cv.Mat();
|
||||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
|
||||
let M = cv.Mat.ones(3, 3, cv.CV_8U);
|
||||
cv.erode(gray, gray, M);
|
||||
cv.dilate(gray, opening, M);
|
||||
cv.dilate(opening, coinsBg, M, new cv.Point(-1, -1), 3);
|
||||
|
||||
// distance transform
|
||||
cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5);
|
||||
cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF);
|
||||
|
||||
cv.imshow('canvasOutput', distTrans);
|
||||
src.delete(); dst.delete(); gray.delete(); opening.delete();
|
||||
coinsBg.delete(); coinsFg.delete(); distTrans.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('coins.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Foreground Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Foreground Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let gray = new cv.Mat();
|
||||
let opening = new cv.Mat();
|
||||
let coinsBg = new cv.Mat();
|
||||
let coinsFg = new cv.Mat();
|
||||
let distTrans = new cv.Mat();
|
||||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
|
||||
let M = cv.Mat.ones(3, 3, cv.CV_8U);
|
||||
cv.erode(gray, gray, M);
|
||||
cv.dilate(gray, opening, M);
|
||||
cv.dilate(opening, coinsBg, M, new cv.Point(-1, -1), 3);
|
||||
cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5);
|
||||
cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF);
|
||||
|
||||
// get foreground
|
||||
cv.threshold(distTrans, coinsFg, 0.7 * 1, 255, cv.THRESH_BINARY);
|
||||
|
||||
cv.imshow('canvasOutput', coinsFg);
|
||||
src.delete(); dst.delete(); gray.delete(); opening.delete();
|
||||
coinsBg.delete(); coinsFg.delete(); distTrans.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('coins.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Threshold Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Threshold Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let gray = new cv.Mat();
|
||||
|
||||
// gray and threshold image
|
||||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
|
||||
|
||||
cv.imshow('canvasOutput', gray);
|
||||
src.delete(); dst.delete(); gray.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('coins.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Image Watershed Example</title>
|
||||
<link href="js_example_style.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>Image Watershed Example</h2>
|
||||
<p>
|
||||
<canvas> elements named <b>canvasInput</b> and <b>canvasOutput</b> have been prepared.<br>
|
||||
Click <b>Try it</b> button to see the result. You can choose another image.<br>
|
||||
You can change the code in the <textarea> to investigate more.
|
||||
</p>
|
||||
<div>
|
||||
<div class="control"><button id="tryIt" disabled>Try it</button></div>
|
||||
<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false">
|
||||
</textarea>
|
||||
<p class="err" id="errorMessage"></p>
|
||||
</div>
|
||||
<div>
|
||||
<table cellpadding="0" cellspacing="0" width="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<canvas id="canvasInput"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
<canvas id="canvasOutput"></canvas>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="caption">canvasInput <input type="file" id="fileInput" name="file" accept="image/*" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="caption">canvasOutput</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<script src="utils.js" type="text/javascript"></script>
|
||||
<script id="codeSnippet" type="text/code-snippet">
|
||||
let src = cv.imread('canvasInput');
|
||||
let dst = new cv.Mat();
|
||||
let gray = new cv.Mat();
|
||||
let opening = new cv.Mat();
|
||||
let coinsBg = new cv.Mat();
|
||||
let coinsFg = new cv.Mat();
|
||||
let distTrans = new cv.Mat();
|
||||
let unknown = new cv.Mat();
|
||||
let markers = new cv.Mat();
|
||||
// gray and threshold image
|
||||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
|
||||
// get background
|
||||
let M = cv.Mat.ones(3, 3, cv.CV_8U);
|
||||
cv.erode(gray, gray, M);
|
||||
cv.dilate(gray, opening, M);
|
||||
cv.dilate(opening, coinsBg, M, new cv.Point(-1, -1), 3);
|
||||
// distance transform
|
||||
cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5);
|
||||
cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF);
|
||||
// get foreground
|
||||
cv.threshold(distTrans, coinsFg, 0.7 * 1, 255, cv.THRESH_BINARY);
|
||||
coinsFg.convertTo(coinsFg, cv.CV_8U, 1, 0);
|
||||
cv.subtract(coinsBg, coinsFg, unknown);
|
||||
// get connected components markers
|
||||
cv.connectedComponents(coinsFg, markers);
|
||||
for (let i = 0; i < markers.rows; i++) {
|
||||
for (let j = 0; j < markers.cols; j++) {
|
||||
markers.intPtr(i, j)[0] = markers.ucharPtr(i, j)[0] + 1;
|
||||
if (unknown.ucharPtr(i, j)[0] == 255) {
|
||||
markers.intPtr(i, j)[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
|
||||
cv.watershed(src, markers);
|
||||
// draw barriers
|
||||
for (let i = 0; i < markers.rows; i++) {
|
||||
for (let j = 0; j < markers.cols; j++) {
|
||||
if (markers.intPtr(i, j)[0] == -1) {
|
||||
src.ucharPtr(i, j)[0] = 255; // R
|
||||
src.ucharPtr(i, j)[1] = 0; // G
|
||||
src.ucharPtr(i, j)[2] = 0; // B
|
||||
}
|
||||
}
|
||||
}
|
||||
cv.imshow('canvasOutput', src);
|
||||
src.delete(); dst.delete(); gray.delete(); opening.delete(); coinsBg.delete();
|
||||
coinsFg.delete(); distTrans.delete(); unknown.delete(); markers.delete(); M.delete();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
let utils = new Utils('errorMessage');
|
||||
|
||||
utils.loadCode('codeSnippet', 'codeEditor');
|
||||
utils.loadImageToCanvas('coins.jpg', 'canvasInput');
|
||||
utils.addFileInputHandler('fileInput', 'canvasInput');
|
||||
|
||||
let tryIt = document.getElementById('tryIt');
|
||||
tryIt.addEventListener('click', () => {
|
||||
utils.executeCode('codeEditor');
|
||||
});
|
||||
|
||||
utils.loadOpenCv(() => {
|
||||
tryIt.removeAttribute('disabled');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/lena.jpg
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/lenaFace.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/opencv_logo.jpg
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/orange.jpg
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
Lib/opencv/sources/doc/js_tutorials/js_assets/shape.jpg
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
164
Lib/opencv/sources/doc/js_tutorials/js_assets/utils.js
Normal file
@@ -0,0 +1,164 @@
|
||||
function Utils(errorOutputId) { // eslint-disable-line no-unused-vars
|
||||
let self = this;
|
||||
this.errorOutput = document.getElementById(errorOutputId);
|
||||
|
||||
const OPENCV_URL = 'opencv.js';
|
||||
this.loadOpenCv = function(onloadCallback) {
|
||||
let script = document.createElement('script');
|
||||
script.setAttribute('async', '');
|
||||
script.setAttribute('type', 'text/javascript');
|
||||
script.addEventListener('load', () => {
|
||||
if (cv.getBuildInformation)
|
||||
{
|
||||
console.log(cv.getBuildInformation());
|
||||
onloadCallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
// WASM
|
||||
cv['onRuntimeInitialized']=()=>{
|
||||
console.log(cv.getBuildInformation());
|
||||
onloadCallback();
|
||||
}
|
||||
}
|
||||
});
|
||||
script.addEventListener('error', () => {
|
||||
self.printError('Failed to load ' + OPENCV_URL);
|
||||
});
|
||||
script.src = OPENCV_URL;
|
||||
let node = document.getElementsByTagName('script')[0];
|
||||
node.parentNode.insertBefore(script, node);
|
||||
};
|
||||
|
||||
this.createFileFromUrl = function(path, url, callback) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.responseType = 'arraybuffer';
|
||||
request.onload = function(ev) {
|
||||
if (request.readyState === 4) {
|
||||
if (request.status === 200) {
|
||||
let data = new Uint8Array(request.response);
|
||||
cv.FS_createDataFile('/', path, data, true, false, false);
|
||||
callback();
|
||||
} else {
|
||||
self.printError('Failed to load ' + url + ' status: ' + request.status);
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send();
|
||||
};
|
||||
|
||||
this.loadImageToCanvas = function(url, cavansId) {
|
||||
let canvas = document.getElementById(cavansId);
|
||||
let ctx = canvas.getContext('2d');
|
||||
let img = new Image();
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.onload = function() {
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
ctx.drawImage(img, 0, 0, img.width, img.height);
|
||||
};
|
||||
img.src = url;
|
||||
};
|
||||
|
||||
this.executeCode = function(textAreaId) {
|
||||
try {
|
||||
this.clearError();
|
||||
let code = document.getElementById(textAreaId).value;
|
||||
eval(code);
|
||||
} catch (err) {
|
||||
this.printError(err);
|
||||
}
|
||||
};
|
||||
|
||||
this.clearError = function() {
|
||||
this.errorOutput.innerHTML = '';
|
||||
};
|
||||
|
||||
this.printError = function(err) {
|
||||
if (typeof err === 'undefined') {
|
||||
err = '';
|
||||
} else if (typeof err === 'number') {
|
||||
if (!isNaN(err)) {
|
||||
if (typeof cv !== 'undefined') {
|
||||
err = 'Exception: ' + cv.exceptionFromPtr(err).msg;
|
||||
}
|
||||
}
|
||||
} else if (typeof err === 'string') {
|
||||
let ptr = Number(err.split(' ')[0]);
|
||||
if (!isNaN(ptr)) {
|
||||
if (typeof cv !== 'undefined') {
|
||||
err = 'Exception: ' + cv.exceptionFromPtr(ptr).msg;
|
||||
}
|
||||
}
|
||||
} else if (err instanceof Error) {
|
||||
err = err.stack.replace(/\n/g, '<br>');
|
||||
}
|
||||
this.errorOutput.innerHTML = err;
|
||||
};
|
||||
|
||||
this.loadCode = function(scriptId, textAreaId) {
|
||||
let scriptNode = document.getElementById(scriptId);
|
||||
let textArea = document.getElementById(textAreaId);
|
||||
if (scriptNode.type !== 'text/code-snippet') {
|
||||
throw Error('Unknown code snippet type');
|
||||
}
|
||||
textArea.value = scriptNode.text.replace(/^\n/, '');
|
||||
};
|
||||
|
||||
this.addFileInputHandler = function(fileInputId, canvasId) {
|
||||
let inputElement = document.getElementById(fileInputId);
|
||||
inputElement.addEventListener('change', (e) => {
|
||||
let files = e.target.files;
|
||||
if (files.length > 0) {
|
||||
let imgUrl = URL.createObjectURL(files[0]);
|
||||
self.loadImageToCanvas(imgUrl, canvasId);
|
||||
}
|
||||
}, false);
|
||||
};
|
||||
|
||||
function onVideoCanPlay() {
|
||||
if (self.onCameraStartedCallback) {
|
||||
self.onCameraStartedCallback(self.stream, self.video);
|
||||
}
|
||||
};
|
||||
|
||||
this.startCamera = function(resolution, callback, videoId) {
|
||||
const constraints = {
|
||||
'qvga': {width: {exact: 320}, height: {exact: 240}},
|
||||
'vga': {width: {exact: 640}, height: {exact: 480}}};
|
||||
let video = document.getElementById(videoId);
|
||||
if (!video) {
|
||||
video = document.createElement('video');
|
||||
}
|
||||
|
||||
let videoConstraint = constraints[resolution];
|
||||
if (!videoConstraint) {
|
||||
videoConstraint = true;
|
||||
}
|
||||
|
||||
navigator.mediaDevices.getUserMedia({video: videoConstraint, audio: false})
|
||||
.then(function(stream) {
|
||||
video.srcObject = stream;
|
||||
video.play();
|
||||
self.video = video;
|
||||
self.stream = stream;
|
||||
self.onCameraStartedCallback = callback;
|
||||
video.addEventListener('canplay', onVideoCanPlay, false);
|
||||
})
|
||||
.catch(function(err) {
|
||||
self.printError('Camera Error: ' + err.name + ' ' + err.message);
|
||||
});
|
||||
};
|
||||
|
||||
this.stopCamera = function() {
|
||||
if (this.video) {
|
||||
this.video.pause();
|
||||
this.video.srcObject = null;
|
||||
this.video.removeEventListener('canplay', onVideoCanPlay);
|
||||
}
|
||||
if (this.stream) {
|
||||
this.stream.getVideoTracks()[0].stop();
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,266 @@
|
||||
Basic Operations on Images {#tutorial_js_basic_ops}
|
||||
==========================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- Learn how to access image properties
|
||||
- Learn how to construct Mat
|
||||
- Learn how to copy Mat
|
||||
- Learn how to convert the type of Mat
|
||||
- Learn how to use MatVector
|
||||
- Learn how to access pixel values and modify them
|
||||
- Learn how to set Region of Interest (ROI)
|
||||
- Learn how to split and merge images
|
||||
|
||||
Accessing Image Properties
|
||||
--------------------------
|
||||
|
||||
Image properties include number of rows, columns and size, depth, channels, type of image data.
|
||||
|
||||
@code{.js}
|
||||
let src = cv.imread("canvasInput");
|
||||
console.log('image width: ' + src.cols + '\n' +
|
||||
'image height: ' + src.rows + '\n' +
|
||||
'image size: ' + src.size().width + '*' + src.size().height + '\n' +
|
||||
'image depth: ' + src.depth() + '\n' +
|
||||
'image channels ' + src.channels() + '\n' +
|
||||
'image type: ' + src.type() + '\n');
|
||||
@endcode
|
||||
|
||||
@note src.type() is very important while debugging because a large number of errors in OpenCV.js
|
||||
code are caused by invalid data type.
|
||||
|
||||
How to construct Mat
|
||||
--------------------
|
||||
|
||||
There are 4 basic constructors:
|
||||
|
||||
@code{.js}
|
||||
// 1. default constructor
|
||||
let mat = new cv.Mat();
|
||||
// 2. two-dimensional arrays by size and type
|
||||
let mat = new cv.Mat(size, type);
|
||||
// 3. two-dimensional arrays by rows, cols, and type
|
||||
let mat = new cv.Mat(rows, cols, type);
|
||||
// 4. two-dimensional arrays by rows, cols, and type with initialization value
|
||||
let mat = new cv.Mat(rows, cols, type, new cv.Scalar());
|
||||
@endcode
|
||||
|
||||
There are 3 static functions:
|
||||
|
||||
@code{.js}
|
||||
// 1. Create a Mat which is full of zeros
|
||||
let mat = cv.Mat.zeros(rows, cols, type);
|
||||
// 2. Create a Mat which is full of ones
|
||||
let mat = cv.Mat.ones(rows, cols, type);
|
||||
// 3. Create a Mat which is an identity matrix
|
||||
let mat = cv.Mat.eye(rows, cols, type);
|
||||
@endcode
|
||||
|
||||
There are 2 factory functions:
|
||||
@code{.js}
|
||||
// 1. Use JS array to construct a mat.
|
||||
// For example: let mat = cv.matFromArray(2, 2, cv.CV_8UC1, [1, 2, 3, 4]);
|
||||
let mat = cv.matFromArray(rows, cols, type, array);
|
||||
// 2. Use imgData to construct a mat
|
||||
let ctx = canvas.getContext("2d");
|
||||
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
let mat = cv.matFromImageData(imgData);
|
||||
@endcode
|
||||
|
||||
@note Don't forget to delete cv.Mat when you don't want to use it any more.
|
||||
|
||||
How to copy Mat
|
||||
---------------
|
||||
|
||||
There are 2 ways to copy a Mat:
|
||||
|
||||
@code{.js}
|
||||
// 1. Clone
|
||||
let dst = src.clone();
|
||||
// 2. CopyTo(only entries indicated in the mask are copied)
|
||||
src.copyTo(dst, mask);
|
||||
@endcode
|
||||
|
||||
How to convert the type of Mat
|
||||
------------------------------
|
||||
|
||||
We use the function: **convertTo(m, rtype, alpha = 1, beta = 0)**
|
||||
@param m output matrix; if it does not have a proper size or type before the operation, it is reallocated.
|
||||
@param rtype desired output matrix type or, rather, the depth since the number of channels are the same as the input has; if rtype is negative, the output matrix will have the same type as the input.
|
||||
@param alpha optional scale factor.
|
||||
@param beta optional delta added to the scaled values.
|
||||
|
||||
@code{.js}
|
||||
src.convertTo(dst, rtype);
|
||||
@endcode
|
||||
|
||||
How use MatVector
|
||||
-----------------
|
||||
|
||||
@code{.js}
|
||||
let mat = new cv.Mat();
|
||||
// Initialise a MatVector
|
||||
let matVec = new cv.MatVector();
|
||||
// Push a Mat back into MatVector
|
||||
matVec.push_back(mat);
|
||||
// Get a Mat fom MatVector
|
||||
let cnt = matVec.get(0);
|
||||
mat.delete(); matVec.delete(); cnt.delete();
|
||||
@endcode
|
||||
|
||||
@note Don't forget to delete cv.Mat, cv.MatVector and cnt(the Mat you get from MatVector) when you don't want to use them any more.
|
||||
|
||||
Accessing and Modifying pixel values
|
||||
------------------------------------
|
||||
|
||||
Firstly, you should know the following type relationship:
|
||||
|
||||
Data Properties | C++ Type | JavaScript Typed Array | Mat Type
|
||||
--------------- | -------- | ---------------------- | --------
|
||||
data | uchar | Uint8Array | CV_8U
|
||||
data8S | char | Int8Array | CV_8S
|
||||
data16U | ushort | Uint16Array | CV_16U
|
||||
data16S | short | Int16Array | CV_16S
|
||||
data32S | int | Int32Array | CV_32S
|
||||
data32F | float | Float32Array | CV_32F
|
||||
data64F | double | Float64Array | CV_64F
|
||||
|
||||
**1. data**
|
||||
|
||||
@code{.js}
|
||||
let row = 3, col = 4;
|
||||
let src = cv.imread("canvasInput");
|
||||
if (src.isContinuous()) {
|
||||
let R = src.data[row * src.cols * src.channels() + col * src.channels()];
|
||||
let G = src.data[row * src.cols * src.channels() + col * src.channels() + 1];
|
||||
let B = src.data[row * src.cols * src.channels() + col * src.channels() + 2];
|
||||
let A = src.data[row * src.cols * src.channels() + col * src.channels() + 3];
|
||||
}
|
||||
@endcode
|
||||
|
||||
@note Data manipulation is only valid for continuous Mat. You should use isContinuous() to check first.
|
||||
|
||||
**2. at**
|
||||
|
||||
Mat Type | At Manipulation
|
||||
--------- | ---------------
|
||||
CV_8U | ucharAt
|
||||
CV_8S | charAt
|
||||
CV_16U | ushortAt
|
||||
CV_16S | shortAt
|
||||
CV_32S | intAt
|
||||
CV_32F | floatAt
|
||||
CV_64F | doubleAt
|
||||
|
||||
@code{.js}
|
||||
let row = 3, col = 4;
|
||||
let src = cv.imread("canvasInput");
|
||||
let R = src.ucharAt(row, col * src.channels());
|
||||
let G = src.ucharAt(row, col * src.channels() + 1);
|
||||
let B = src.ucharAt(row, col * src.channels() + 2);
|
||||
let A = src.ucharAt(row, col * src.channels() + 3);
|
||||
@endcode
|
||||
|
||||
@note At manipulation is only for single channel access and the value can't be modified.
|
||||
|
||||
**3. ptr**
|
||||
|
||||
Mat Type | Ptr Manipulation | JavaScript Typed Array
|
||||
-------- | --------------- | ----------------------
|
||||
CV_8U | ucharPtr | Uint8Array
|
||||
CV_8S | charPtr | Int8Array
|
||||
CV_16U | ushortPtr | Uint16Array
|
||||
CV_16S | shortPtr | Int16Array
|
||||
CV_32S | intPtr | Int32Array
|
||||
CV_32F | floatPtr | Float32Array
|
||||
CV_64F | doublePtr | Float64Array
|
||||
|
||||
@code{.js}
|
||||
let row = 3, col = 4;
|
||||
let src = cv.imread("canvasInput");
|
||||
let pixel = src.ucharPtr(row, col);
|
||||
let R = pixel[0];
|
||||
let G = pixel[1];
|
||||
let B = pixel[2];
|
||||
let A = pixel[3];
|
||||
@endcode
|
||||
|
||||
mat.ucharPtr(k) get the k th row of the mat. mat.ucharPtr(i, j) get the i th row and the j th column of the mat.
|
||||
|
||||
Image ROI
|
||||
---------
|
||||
|
||||
Sometimes, you will have to play with certain region of images. For eye detection in images, first
|
||||
face detection is done all over the image and when face is obtained, we select the face region alone
|
||||
and search for eyes inside it instead of searching whole image. It improves accuracy (because eyes
|
||||
are always on faces) and performance (because we search for a small area)
|
||||
|
||||
We use the function: **roi (rect)**
|
||||
@param rect rectangle Region of Interest.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_basic_ops_roi.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
|
||||
Splitting and Merging Image Channels
|
||||
------------------------------------
|
||||
|
||||
Sometimes you will need to work separately on R,G,B channels of image. Then you need to split the
|
||||
RGB images to single planes. Or another time, you may need to join these individual channels to RGB
|
||||
image.
|
||||
|
||||
@code{.js}
|
||||
let src = cv.imread("canvasInput");
|
||||
let rgbaPlanes = new cv.MatVector();
|
||||
// Split the Mat
|
||||
cv.split(src, rgbaPlanes);
|
||||
// Get R channel
|
||||
let R = rgbaPlanes.get(0);
|
||||
// Merge all channels
|
||||
cv.merge(rgbaPlanes, src);
|
||||
src.delete(); rgbaPlanes.delete(); R.delete();
|
||||
@endcode
|
||||
|
||||
@note Don't forget to delete cv.Mat, cv.MatVector and R(the Mat you get from MatVector) when you don't want to use them any more.
|
||||
|
||||
Making Borders for Images (Padding)
|
||||
-----------------------------------
|
||||
|
||||
If you want to create a border around the image, something like a photo frame, you can use
|
||||
**cv.copyMakeBorder()** function. But it has more applications for convolution operation, zero
|
||||
padding etc. This function takes following arguments:
|
||||
|
||||
- **src** - input image
|
||||
- **top**, **bottom**, **left**, **right** - border width in number of pixels in corresponding
|
||||
directions
|
||||
|
||||
- **borderType** - Flag defining what kind of border to be added. It can be following types:
|
||||
- **cv.BORDER_CONSTANT** - Adds a constant colored border. The value should be given
|
||||
as next argument.
|
||||
- **cv.BORDER_REFLECT** - Border will be mirror reflection of the border elements,
|
||||
like this : *fedcba|abcdefgh|hgfedcb*
|
||||
- **cv.BORDER_REFLECT_101** or **cv.BORDER_DEFAULT** - Same as above, but with a
|
||||
slight change, like this : *gfedcb|abcdefgh|gfedcba*
|
||||
- **cv.BORDER_REPLICATE** - Last element is replicated throughout, like this:
|
||||
*aaaaaa|abcdefgh|hhhhhhh*
|
||||
- **cv.BORDER_WRAP** - Can't explain, it will look like this :
|
||||
*cdefgh|abcdefgh|abcdefg*
|
||||
|
||||
- **value** - Color of border if border type is cv.BORDER_CONSTANT
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_basic_ops_copymakeborder.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
@@ -0,0 +1,62 @@
|
||||
Arithmetic Operations on Images {#tutorial_js_image_arithmetics}
|
||||
===============================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- Learn several arithmetic operations on images like addition, subtraction, bitwise operations
|
||||
etc.
|
||||
- You will learn these functions : **cv.add()**, **cv.subtract()** etc.
|
||||
|
||||
Image Addition
|
||||
--------------
|
||||
|
||||
You can add two images by OpenCV function, cv.add(). res = img1 + img2. Both images should be of same depth and type.
|
||||
|
||||
For example, consider below sample:
|
||||
@code{.js}
|
||||
let src1 = cv.imread("canvasInput1");
|
||||
let src2 = cv.imread("canvasInput2");
|
||||
let dst = new cv.Mat();
|
||||
let mask = new cv.Mat();
|
||||
let dtype = -1;
|
||||
cv.add(src1, src2, dst, mask, dtype);
|
||||
src1.delete(); src2.delete(); dst.delete(); mask.delete();
|
||||
@endcode
|
||||
|
||||
Image Subtraction
|
||||
--------------
|
||||
|
||||
You can subtract two images by OpenCV function, cv.subtract(). res = img1 - img2. Both images should be of same depth and type. Note that when used with RGBA images, the alpha channel is also subtracted.
|
||||
|
||||
For example, consider below sample:
|
||||
@code{.js}
|
||||
let src1 = cv.imread("canvasInput1");
|
||||
let src2 = cv.imread("canvasInput2");
|
||||
let dst = new cv.Mat();
|
||||
let mask = new cv.Mat();
|
||||
let dtype = -1;
|
||||
cv.subtract(src1, src2, dst, mask, dtype);
|
||||
src1.delete(); src2.delete(); dst.delete(); mask.delete();
|
||||
@endcode
|
||||
|
||||
Bitwise Operations
|
||||
------------------
|
||||
|
||||
This includes bitwise AND, OR, NOT and XOR operations. They will be highly useful while extracting
|
||||
any part of the image, defining and working with non-rectangular
|
||||
ROI etc. Below we will see an example on how to change a particular region of an image.
|
||||
|
||||
I want to put OpenCV logo above an image. If I add two images, it will change color. If I blend it,
|
||||
I get an transparent effect. But I want it to be opaque. If it was a rectangular region, I could use
|
||||
ROI as we did in last chapter. But OpenCV logo is a not a rectangular shape. So you can do it with
|
||||
bitwise operations.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_image_arithmetics_bitwise.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
@@ -0,0 +1,120 @@
|
||||
Some Data Structures {#tutorial_js_some_data_structures}
|
||||
===============================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- You will learn some data structures : **Point**, **Scalar**, **Size**, **Circle**, **Rect**, **RotatedRect** etc.
|
||||
|
||||
Scalar is array type in Javascript. Point, Size, Circle, Rect and RotatedRect are object type in JavaScript.
|
||||
|
||||
Point
|
||||
--------------
|
||||
|
||||
There are 2 ways to construct a Point and they are the same:
|
||||
@code{.js}
|
||||
// The first way
|
||||
let point = new cv.Point(x, y);
|
||||
// The second way
|
||||
let point = {x: x, y: y};
|
||||
@endcode
|
||||
|
||||
@param x x coordinate of the point.(the origin is the top left corner of the image)
|
||||
@param y y coordinate of the point.
|
||||
|
||||
Scalar
|
||||
--------------
|
||||
|
||||
There are 2 ways to construct a Scalar and they are the same:
|
||||
@code{.js}
|
||||
// The first way
|
||||
let scalar = new cv.Scalar(R, G, B, Alpha);
|
||||
// The second way
|
||||
let scalar = [R, G, B, Alpha];
|
||||
@endcode
|
||||
|
||||
@param R pixel value of red channel.
|
||||
@param G pixel value of green channel.
|
||||
@param B pixel value of blue channel.
|
||||
@param Alpha pixel value of alpha channel.
|
||||
|
||||
Size
|
||||
------------------
|
||||
|
||||
There are 2 ways to construct a Size and they are the same:
|
||||
@code{.js}
|
||||
// The first way
|
||||
let size = new cv.Size(width, height);
|
||||
// The second way
|
||||
let size = {width : width, height : height};
|
||||
@endcode
|
||||
|
||||
@param width the width of the size.
|
||||
@param height the height of the size.
|
||||
|
||||
Circle
|
||||
------------------
|
||||
|
||||
There are 2 ways to construct a Circle and they are the same:
|
||||
@code{.js}
|
||||
// The first way
|
||||
let circle = new cv.Circle(center, radius);
|
||||
// The second way
|
||||
let circle = {center : center, radius : radius};
|
||||
@endcode
|
||||
|
||||
@param center the center of the circle.
|
||||
@param radius the radius of the circle.
|
||||
|
||||
Rect
|
||||
------------------
|
||||
|
||||
There are 2 ways to construct a Rect and they are the same:
|
||||
@code{.js}
|
||||
// The first way
|
||||
let rect = new cv.Rect(x, y, width, height);
|
||||
// The second way
|
||||
let rect = {x : x, y : y, width : width, height : height};
|
||||
@endcode
|
||||
|
||||
@param x x coordinate of the vertex which is the top left corner of the rectangle.
|
||||
@param y y coordinate of the vertex which is the top left corner of the rectangle.
|
||||
@param width the width of the rectangle.
|
||||
@param height the height of the rectangle.
|
||||
|
||||
RotatedRect
|
||||
------------------
|
||||
|
||||
There are 2 ways to construct a RotatedRect and they are the same:
|
||||
@code{.js}
|
||||
// The first way
|
||||
let rotatedRect = new cv.RotatedRect(center, size, angle);
|
||||
// The second way
|
||||
let rotatedRect = {center : center, size : size, angle : angle};
|
||||
@endcode
|
||||
|
||||
@param center the rectangle mass center.
|
||||
@param size width and height of the rectangle.
|
||||
@param angle the rotation angle in a clockwise direction. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle.
|
||||
|
||||
Learn how to get the vertices from rotatedRect:
|
||||
|
||||
We use the function: **cv.RotatedRect.points(rotatedRect)**
|
||||
@param rotatedRect rotated rectangle
|
||||
|
||||
@code{.js}
|
||||
let vertices = cv.RotatedRect.points(rotatedRect);
|
||||
let point1 = vertices[0];
|
||||
let point2 = vertices[1];
|
||||
let point3 = vertices[2];
|
||||
let point4 = vertices[3];
|
||||
@endcode
|
||||
|
||||
Learn how to get the bounding rectangle from rotatedRect:
|
||||
|
||||
We use the function: **cv.RotatedRect.boundingRect(rotatedRect)**
|
||||
@param rotatedRect rotated rectangle
|
||||
|
||||
@code{.js}
|
||||
let boundingRect = cv.RotatedRect.boundingRect(rotatedRect);
|
||||
@endcode
|
||||
@@ -0,0 +1,16 @@
|
||||
Core Operations {#tutorial_js_table_of_contents_core}
|
||||
===============
|
||||
|
||||
- @subpage tutorial_js_basic_ops
|
||||
|
||||
Learn to read and
|
||||
edit pixel values, working with image ROI and other basic operations.
|
||||
|
||||
- @subpage tutorial_js_image_arithmetics
|
||||
|
||||
Perform arithmetic
|
||||
operations on images
|
||||
|
||||
- @subpage tutorial_js_some_data_structures
|
||||
|
||||
Learn some data structures
|
||||
|
After Width: | Height: | Size: 248 KiB |
@@ -0,0 +1,95 @@
|
||||
Getting Started with Images {#tutorial_js_image_display}
|
||||
===========================
|
||||
|
||||
Goals
|
||||
-----
|
||||
|
||||
- Learn how to read an image and how to display it in a web.
|
||||
|
||||
Read an image
|
||||
-------------
|
||||
|
||||
OpenCV.js saves images as cv.Mat type. We use HTML canvas element to transfer cv.Mat to the web
|
||||
or in reverse. The ImageData interface can represent or set the underlying pixel data of an area of a
|
||||
canvas element.
|
||||
|
||||
@sa Please refer to canvas docs for more details.
|
||||
|
||||
First, create an ImageData obj from canvas:
|
||||
@code{.js}
|
||||
let canvas = document.getElementById(canvasInputId);
|
||||
let ctx = canvas.getContext('2d');
|
||||
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
@endcode
|
||||
|
||||
Then, use cv.matFromImageData to construct a cv.Mat:
|
||||
@code{.js}
|
||||
let src = cv.matFromImageData(imgData);
|
||||
@endcode
|
||||
|
||||
@note Because canvas only support 8-bit RGBA image with continuous storage, the cv.Mat type is cv.CV_8UC4.
|
||||
It is different from native OpenCV because images returned and shown by the native **imread** and
|
||||
**imshow** have the channels stored in BGR order.
|
||||
|
||||
Display an image
|
||||
----------------
|
||||
|
||||
First, convert the type of src to cv.CV_8UC4:
|
||||
@code{.js}
|
||||
let dst = new cv.Mat();
|
||||
// scale and shift are used to map the data to [0, 255].
|
||||
src.convertTo(dst, cv.CV_8U, scale, shift);
|
||||
// *** is GRAY, RGB, or RGBA, according to src.channels() is 1, 3 or 4.
|
||||
cv.cvtColor(dst, dst, cv.COLOR_***2RGBA);
|
||||
@endcode
|
||||
|
||||
Then, new an ImageData obj from dst:
|
||||
@code{.js}
|
||||
let imgData = new ImageData(new Uint8ClampedArray(dst.data, dst.cols, dst.rows);
|
||||
@endcode
|
||||
|
||||
Finally, display it:
|
||||
@code{.js}
|
||||
let canvas = document.getElementById(canvasOutputId);
|
||||
let ctx = canvas.getContext('2d');
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
canvas.width = imgData.width;
|
||||
canvas.height = imgData.height;
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
@endcode
|
||||
|
||||
In OpenCV.js
|
||||
------------
|
||||
|
||||
OpenCV.js implements image reading and showing using the above method.
|
||||
|
||||
We use **cv.imread (imageSource)** to read an image from html canvas or img element.
|
||||
@param imageSource canvas element or id, or img element or id.
|
||||
@return mat with channels stored in RGBA order.
|
||||
|
||||
We use **cv.imshow (canvasSource, mat)** to display it. The function may scale the mat,
|
||||
depending on its depth:
|
||||
- If the mat is 8-bit unsigned, it is displayed as is.
|
||||
- If the mat is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That
|
||||
is, the value range [0,255*256] is mapped to [0,255].
|
||||
- If the mat is 32-bit floating-point, the pixel values are multiplied by 255. That is,
|
||||
the value range [0,1] is mapped to [0,255].
|
||||
|
||||
@param canvasSource canvas element or id.
|
||||
@param mat mat to be shown.
|
||||
|
||||
The above code of image reading and showing could be simplified as below.
|
||||
@code{.js}
|
||||
let img = cv.imread(imageSource);
|
||||
cv.imshow(canvasOutput, img);
|
||||
img.delete();
|
||||
@endcode
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_image_display.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
@@ -0,0 +1,14 @@
|
||||
GUI Features {#tutorial_js_table_of_contents_gui}
|
||||
============
|
||||
|
||||
- @subpage tutorial_js_image_display
|
||||
|
||||
Learn to load an image and display it in a web
|
||||
|
||||
- @subpage tutorial_js_video_display
|
||||
|
||||
Learn to capture video from Camera and play it
|
||||
|
||||
- @subpage tutorial_js_trackbar
|
||||
|
||||
Create trackbar to control certain parameters
|
||||
|
After Width: | Height: | Size: 350 B |
|
After Width: | Height: | Size: 60 KiB |
@@ -0,0 +1,73 @@
|
||||
Add a Trackbar to Your Application {#tutorial_js_trackbar}
|
||||
==================================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- Use HTML DOM Input Range Object to add a trackbar to your application.
|
||||
|
||||
Code Demo
|
||||
---------
|
||||
|
||||
Here, we will create a simple application that blends two images. We will let the user enter the
|
||||
weight by using the trackbar.
|
||||
|
||||
First, we need to create three canvas elements: two for input and one for output. Please refer to
|
||||
the tutorial @ref tutorial_js_image_display.
|
||||
@code{.js}
|
||||
let src1 = cv.imread('canvasInput1');
|
||||
let src2 = cv.imread('canvasInput2');
|
||||
@endcode
|
||||
|
||||
Then, we use HTML DOM Input Range Object to implement the trackbar, which is shown as below.
|
||||

|
||||
|
||||
@note <input> elements with type="range" are not supported in Internet Explorer 9 and earlier versions.
|
||||
|
||||
You can create an <input> element with type="range" with the document.createElement() method:
|
||||
@code{.js}
|
||||
let x = document.createElement('INPUT');
|
||||
x.setAttribute('type', 'range');
|
||||
@endcode
|
||||
|
||||
You can access an <input> element with type="range" with getElementById():
|
||||
@code{.js}
|
||||
let x = document.getElementById('myRange');
|
||||
@endcode
|
||||
|
||||
As a trackbar, the range element need a trackbar name, the default value, minimum value, maximum value,
|
||||
step and the callback function which is executed every time trackbar value changes. The callback function
|
||||
always has a default argument, which is the trackbar position. Additionally, a text element to display the
|
||||
trackbar value is fine. In our case, we can create the trackbar as below:
|
||||
@code{.html}
|
||||
Weight: <input type="range" id="trackbar" value="50" min="0" max="100" step="1" oninput="callback()">
|
||||
<input type="text" id="weightValue" size="3" value="50"/>
|
||||
@endcode
|
||||
|
||||
Finally, we can use the trackbar value in the callback function, blend the two images, and display the result.
|
||||
@code{.js}
|
||||
let weightValue = document.getElementById('weightValue');
|
||||
let trackbar = document.getElementById('trackbar');
|
||||
weightValue.setAttribute('value', trackbar.value);
|
||||
let alpha = trackbar.value/trackbar.max;
|
||||
let beta = ( 1.0 - alpha );
|
||||
let src1 = cv.imread('canvasInput1');
|
||||
let src2 = cv.imread('canvasInput2');
|
||||
let dst = new cv.Mat();
|
||||
cv.addWeighted( src1, alpha, src2, beta, 0.0, dst, -1);
|
||||
cv.imshow('canvasOutput', dst);
|
||||
dst.delete();
|
||||
src1.delete();
|
||||
src2.delete();
|
||||
@endcode
|
||||
|
||||
@sa cv.addWeighted
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_trackbar.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
@@ -0,0 +1,105 @@
|
||||
Getting Started with Videos {#tutorial_js_video_display}
|
||||
===========================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- Learn to capture video from a camera and display it.
|
||||
|
||||
Capture video from camera
|
||||
-------------------------
|
||||
|
||||
Often, we have to capture live stream with a camera. In OpenCV.js, we use [WebRTC](https://webrtc.org/)
|
||||
and HTML canvas element to implement this. Let's capture a video from the camera(built-in
|
||||
or a usb), convert it into grayscale video and display it.
|
||||
|
||||
To capture a video, you need to add some HTML elements to the web page:
|
||||
- a <video> to display video from camera directly
|
||||
- a <canvas> to transfer video to canvas ImageData frame-by-frame
|
||||
- another <canvas> to display the video OpenCV.js gets
|
||||
|
||||
First, we use WebRTC navigator.mediaDevices.getUserMedia to get the media stream.
|
||||
@code{.js}
|
||||
let video = document.getElementById("videoInput"); // video is the id of video tag
|
||||
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
|
||||
.then(function(stream) {
|
||||
video.srcObject = stream;
|
||||
video.play();
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log("An error occurred! " + err);
|
||||
});
|
||||
@endcode
|
||||
|
||||
@note This function is unnecessary when you capture video from a video file. But notice that
|
||||
HTML video element only supports video formats of Ogg(Theora), WebM(VP8/VP9) or MP4(H.264).
|
||||
|
||||
Playing video
|
||||
-------------
|
||||
Now, the browser gets the camera stream. Then, we use CanvasRenderingContext2D.drawImage() method
|
||||
of the Canvas 2D API to draw video onto the canvas. Finally, we can use the method in @ref tutorial_js_image_display
|
||||
to read and display image in canvas. For playing video, cv.imshow() should be executed every delay
|
||||
milliseconds. We recommend setTimeout() method. And if the video is 30fps, the delay milliseconds
|
||||
should be (1000/30 - processing_time).
|
||||
@code{.js}
|
||||
let canvasFrame = document.getElementById("canvasFrame"); // canvasFrame is the id of <canvas>
|
||||
let context = canvasFrame.getContext("2d");
|
||||
let src = new cv.Mat(height, width, cv.CV_8UC4);
|
||||
let dst = new cv.Mat(height, width, cv.CV_8UC1);
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
let begin = Date.now();
|
||||
context.drawImage(video, 0, 0, width, height);
|
||||
src.data.set(context.getImageData(0, 0, width, height).data);
|
||||
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY);
|
||||
cv.imshow("canvasOutput", dst); // canvasOutput is the id of another <canvas>;
|
||||
// schedule next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
}
|
||||
|
||||
// schedule first one.
|
||||
setTimeout(processVideo, 0);
|
||||
@endcode
|
||||
|
||||
OpenCV.js implements **cv.VideoCapture (videoSource)** using the above method. You need not to
|
||||
add the hidden canvas element manually.
|
||||
@param videoSource the video id or element.
|
||||
@return cv.VideoCapture instance
|
||||
|
||||
We use **read (image)** to get one frame of the video. For performance reasons, the image should be
|
||||
constructed with cv.CV_8UC4 type and same size as the video.
|
||||
@param image image with cv.CV_8UC4 type and same size as the video.
|
||||
|
||||
The above code of playing video could be simplified as below.
|
||||
@code{.js}
|
||||
let src = new cv.Mat(height, width, cv.CV_8UC4);
|
||||
let dst = new cv.Mat(height, width, cv.CV_8UC1);
|
||||
let cap = new cv.VideoCapture(videoSource);
|
||||
|
||||
const FPS = 30;
|
||||
function processVideo() {
|
||||
let begin = Date.now();
|
||||
cap.read(src);
|
||||
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY);
|
||||
cv.imshow("canvasOutput", dst);
|
||||
// schedule next one.
|
||||
let delay = 1000/FPS - (Date.now() - begin);
|
||||
setTimeout(processVideo, delay);
|
||||
}
|
||||
|
||||
// schedule first one.
|
||||
setTimeout(processVideo, 0);
|
||||
@endcode
|
||||
|
||||
@note Remember to delete src and dst after when stop.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_video_display.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
@@ -0,0 +1,88 @@
|
||||
Canny Edge Detection {#tutorial_js_canny}
|
||||
====================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- Concept of Canny edge detection
|
||||
- OpenCV functions for that : **cv.Canny()**
|
||||
|
||||
Theory
|
||||
------
|
||||
|
||||
Canny Edge Detection is a popular edge detection algorithm. It was developed by John F. Canny in 1986. It is a multi-stage algorithm and we will go through each stages.
|
||||
|
||||
-# **Noise Reduction**
|
||||
|
||||
Since edge detection is susceptible to noise in the image, first step is to remove the noise in the
|
||||
image with a 5x5 Gaussian filter. We have already seen this in previous chapters.
|
||||
|
||||
-# **Finding Intensity Gradient of the Image**
|
||||
|
||||
Smoothened image is then filtered with a Sobel kernel in both horizontal and vertical direction to
|
||||
get first derivative in horizontal direction (\f$G_x\f$) and vertical direction (\f$G_y\f$). From these two
|
||||
images, we can find edge gradient and direction for each pixel as follows:
|
||||
|
||||
\f[
|
||||
Edge\_Gradient \; (G) = \sqrt{G_x^2 + G_y^2} \\
|
||||
Angle \; (\theta) = \tan^{-1} \bigg(\frac{G_y}{G_x}\bigg)
|
||||
\f]
|
||||
|
||||
Gradient direction is always perpendicular to edges. It is rounded to one of four angles
|
||||
representing vertical, horizontal and two diagonal directions.
|
||||
|
||||
-# **Non-maximum Suppression**
|
||||
|
||||
After getting gradient magnitude and direction, a full scan of image is done to remove any unwanted
|
||||
pixels which may not constitute the edge. For this, at every pixel, pixel is checked if it is a
|
||||
local maximum in its neighborhood in the direction of gradient. Check the image below:
|
||||
|
||||

|
||||
|
||||
Point A is on the edge ( in vertical direction). Gradient direction is normal to the edge. Point B
|
||||
and C are in gradient directions. So point A is checked with point B and C to see if it forms a
|
||||
local maximum. If so, it is considered for next stage, otherwise, it is suppressed ( put to zero).
|
||||
|
||||
In short, the result you get is a binary image with "thin edges".
|
||||
|
||||
-# **Hysteresis Thresholding**
|
||||
|
||||
This stage decides which are all edges are really edges and which are not. For this, we need two
|
||||
threshold values, minVal and maxVal. Any edges with intensity gradient more than maxVal are sure to
|
||||
be edges and those below minVal are sure to be non-edges, so discarded. Those who lie between these
|
||||
two thresholds are classified edges or non-edges based on their connectivity. If they are connected
|
||||
to "sure-edge" pixels, they are considered to be part of edges. Otherwise, they are also discarded.
|
||||
See the image below:
|
||||
|
||||

|
||||
|
||||
The edge A is above the maxVal, so considered as "sure-edge". Although edge C is below maxVal, it is
|
||||
connected to edge A, so that also considered as valid edge and we get that full curve. But edge B,
|
||||
although it is above minVal and is in same region as that of edge C, it is not connected to any
|
||||
"sure-edge", so that is discarded. So it is very important that we have to select minVal and maxVal
|
||||
accordingly to get the correct result.
|
||||
|
||||
This stage also removes small pixels noises on the assumption that edges are long lines.
|
||||
|
||||
So what we finally get is strong edges in the image.
|
||||
|
||||
Canny Edge Detection in OpenCV
|
||||
------------------------------
|
||||
|
||||
We use the function: **cv.Canny(image, edges, threshold1, threshold2, apertureSize = 3, L2gradient = false)**
|
||||
@param image 8-bit input image.
|
||||
@param edges output edge map; single channels 8-bit image, which has the same size as image.
|
||||
@param threshold1 first threshold for the hysteresis procedure.
|
||||
@param threshold2 second threshold for the hysteresis procedure..
|
||||
@param apertureSize aperture size for the Sobel operator.
|
||||
@param L2gradient specifies the equation for finding gradient
|
||||
magnitude. If it is True, it uses the equation mentioned above which is more accurate, otherwise it uses this function: \f$Edge\_Gradient \; (G) = |G_x| + |G_y|\f$.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_canny.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
@@ -0,0 +1,52 @@
|
||||
Changing Colorspaces {#tutorial_js_colorspaces}
|
||||
====================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- In this tutorial, you will learn how to convert images from one color-space to another, like
|
||||
RGB \f$\leftrightarrow\f$ Gray, RGB \f$\leftrightarrow\f$ HSV etc.
|
||||
- You will learn following functions : **cv.cvtColor()**, **cv.inRange()** etc.
|
||||
|
||||
cvtColor
|
||||
--------------------
|
||||
|
||||
There are more than 150 color-space conversion methods available in OpenCV. But we will look into
|
||||
the most widely used one: RGB \f$\leftrightarrow\f$ Gray.
|
||||
|
||||
We use the function: **cv.cvtColor (src, dst, code, dstCn = 0)**
|
||||
@param src input image.
|
||||
@param dst output image of the same size and depth as src
|
||||
@param code color space conversion code(see **cv.ColorConversionCodes**).
|
||||
@param dstCn number of channels in the destination image; if the parameter is 0, the number of the channels is derived automatically from src and code.
|
||||
|
||||
For RGB \f$\rightarrow\f$ Gray conversion we use the code cv.COLOR_RGBA2GRAY.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_colorspaces_cvtColor.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
inRange
|
||||
---------------
|
||||
|
||||
Checks if array elements lie between the elements of two other arrays.
|
||||
|
||||
We use the function: **cv.inRange (src, lowerb, upperb, dst)**
|
||||
@param src first input image.
|
||||
@param lowerb inclusive lower boundary Mat of the same size as src.
|
||||
@param upperb inclusive upper boundary Mat of the same size as src.
|
||||
@param dst output image of the same size as src and cv.CV_8U type.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_colorspaces_inRange.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
@@ -0,0 +1,252 @@
|
||||
Contour Features {#tutorial_js_contour_features}
|
||||
================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- To find the different features of contours, like area, perimeter, centroid, bounding box etc
|
||||
- You will learn plenty of functions related to contours.
|
||||
|
||||
1. Moments
|
||||
----------
|
||||
|
||||
Image moments help you to calculate some features like center of mass of the object, area of the
|
||||
object etc. Check out the wikipedia page on [Image
|
||||
Moments](http://en.wikipedia.org/wiki/Image_moment)
|
||||
|
||||
We use the function: **cv.moments (array, binaryImage = false)**
|
||||
@param array raster image (single-channel, 8-bit or floating-point 2D array) or an array ( 1×N or N×1 ) of 2D points.
|
||||
@param binaryImage if it is true, all non-zero image pixels are treated as 1's. The parameter is used for images only.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_moments.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
From this moments, you can extract useful data like area, centroid etc. Centroid is given by the
|
||||
relations, \f$C_x = \frac{M_{10}}{M_{00}}\f$ and \f$C_y = \frac{M_{01}}{M_{00}}\f$. This can be done as
|
||||
follows:
|
||||
@code{.js}
|
||||
let cx = M.m10/M.m00
|
||||
let cy = M.m01/M.m00
|
||||
@endcode
|
||||
|
||||
2. Contour Area
|
||||
---------------
|
||||
|
||||
Contour area is given by the function **cv.contourArea()** or from moments, **M['m00']**.
|
||||
|
||||
We use the function: **cv.contourArea (contour, oriented = false)**
|
||||
@param contour input vector of 2D points (contour vertices)
|
||||
@param oriented oriented area flag. If it is true, the function returns a signed area value, depending on the contour orientation (clockwise or counter-clockwise). Using this feature you can determine orientation of a contour by taking the sign of an area. By default, the parameter is false, which means that the absolute value is returned.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_area.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
3. Contour Perimeter
|
||||
--------------------
|
||||
|
||||
It is also called arc length. It can be found out using **cv.arcLength()** function.
|
||||
|
||||
We use the function: **cv.arcLength (curve, closed)**
|
||||
@param curve input vector of 2D points.
|
||||
@param closed flag indicating whether the curve is closed or not.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_perimeter.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
4. Contour Approximation
|
||||
------------------------
|
||||
|
||||
It approximates a contour shape to another shape with less number of vertices depending upon the
|
||||
precision we specify. It is an implementation of [Douglas-Peucker
|
||||
algorithm](http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm). Check the wikipedia page
|
||||
for algorithm and demonstration.
|
||||
|
||||
We use the function: **cv.approxPolyDP (curve, approxCurve, epsilon, closed)**
|
||||
@param curve input vector of 2D points stored in cv.Mat.
|
||||
@param approxCurve result of the approximation. The type should match the type of the input curve.
|
||||
@param epsilon parameter specifying the approximation accuracy. This is the maximum distance between the original curve and its approximation.
|
||||
@param closed If true, the approximated curve is closed (its first and last vertices are connected). Otherwise, it is not closed.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_approxPolyDP.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
5. Convex Hull
|
||||
--------------
|
||||
|
||||
Convex Hull will look similar to contour approximation, but it is not (Both may provide same results
|
||||
in some cases). Here, **cv.convexHull()** function checks a curve for convexity defects and
|
||||
corrects it. Generally speaking, convex curves are the curves which are always bulged out, or
|
||||
at-least flat. And if it is bulged inside, it is called convexity defects. For example, check the
|
||||
below image of hand. Red line shows the convex hull of hand. The double-sided arrow marks shows the
|
||||
convexity defects, which are the local maximum deviations of hull from contours.
|
||||
|
||||

|
||||
|
||||
We use the function: **cv.convexHull (points, hull, clockwise = false, returnPoints = true)**
|
||||
@param points input 2D point set.
|
||||
@param hull output convex hull.
|
||||
@param clockwise orientation flag. If it is true, the output convex hull is oriented clockwise. Otherwise, it is oriented counter-clockwise. The assumed coordinate system has its X axis pointing to the right, and its Y axis pointing upwards.
|
||||
@param returnPoints operation flag. In case of a matrix, when the flag is true, the function returns convex hull points. Otherwise, it returns indices of the convex hull points.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_convexHull.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
6. Checking Convexity
|
||||
---------------------
|
||||
|
||||
There is a function to check if a curve is convex or not, **cv.isContourConvex()**. It just return
|
||||
whether True or False. Not a big deal.
|
||||
|
||||
@code{.js}
|
||||
cv.isContourConvex(cnt);
|
||||
@endcode
|
||||
|
||||
7. Bounding Rectangle
|
||||
---------------------
|
||||
|
||||
There are two types of bounding rectangles.
|
||||
|
||||
### 7.a. Straight Bounding Rectangle
|
||||
|
||||
It is a straight rectangle, it doesn't consider the rotation of the object. So area of the bounding
|
||||
rectangle won't be minimum.
|
||||
|
||||
We use the function: **cv.boundingRect (points)**
|
||||
@param points input 2D point set.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_boundingRect.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
### 7.b. Rotated Rectangle
|
||||
|
||||
Here, bounding rectangle is drawn with minimum area, so it considers the rotation also.
|
||||
|
||||
We use the function: **cv.minAreaRect (points)**
|
||||
@param points input 2D point set.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_minAreaRect.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
8. Minimum Enclosing Circle
|
||||
---------------------------
|
||||
|
||||
Next we find the circumcircle of an object using the function **cv.minEnclosingCircle()**. It is a
|
||||
circle which completely covers the object with minimum area.
|
||||
|
||||
We use the functions: **cv.minEnclosingCircle (points)**
|
||||
@param points input 2D point set.
|
||||
|
||||
**cv.circle (img, center, radius, color, thickness = 1, lineType = cv.LINE_8, shift = 0)**
|
||||
@param img image where the circle is drawn.
|
||||
@param center center of the circle.
|
||||
@param radius radius of the circle.
|
||||
@param color circle color.
|
||||
@param thickness thickness of the circle outline, if positive. Negative thickness means that a filled circle is to be drawn.
|
||||
@param lineType type of the circle boundary.
|
||||
@param shift number of fractional bits in the coordinates of the center and in the radius value.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_minEnclosingCircle.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
9. Fitting an Ellipse
|
||||
---------------------
|
||||
|
||||
Next one is to fit an ellipse to an object. It returns the rotated rectangle in which the ellipse is
|
||||
inscribed.
|
||||
We use the functions: **cv.fitEllipse (points)**
|
||||
@param points input 2D point set.
|
||||
|
||||
**cv.ellipse1 (img, box, color, thickness = 1, lineType = cv.LINE_8)**
|
||||
@param img image.
|
||||
@param box alternative ellipse representation via RotatedRect. This means that the function draws an ellipse inscribed in the rotated rectangle.
|
||||
@param color ellipse color.
|
||||
@param thickness thickness of the ellipse arc outline, if positive. Otherwise, this indicates that a filled ellipse sector is to be drawn.
|
||||
@param lineType type of the ellipse boundary.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_fitEllipse.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
10. Fitting a Line
|
||||
------------------
|
||||
|
||||
Similarly we can fit a line to a set of points. We can approximate a straight line to it.
|
||||
|
||||
We use the functions: **cv.fitLine (points, line, distType, param, reps, aeps)**
|
||||
@param points input 2D point set.
|
||||
@param line output line parameters. It should be a Mat of 4 elements[vx, vy, x0, y0], where [vx, vy] is a normalized vector collinear to the line and [x0, y0] is a point on the line.
|
||||
@param distType distance used by the M-estimator(see cv.DistanceTypes).
|
||||
@param param numerical parameter ( C ) for some types of distances. If it is 0, an optimal value is chosen.
|
||||
@param reps sufficient accuracy for the radius (distance between the coordinate origin and the line).
|
||||
@param aeps sufficient accuracy for the angle. 0.01 would be a good default value for reps and aeps.
|
||||
|
||||
**cv.line (img, pt1, pt2, color, thickness = 1, lineType = cv.LINE_8, shift = 0)**
|
||||
@param img image.
|
||||
@param pt1 first point of the line segment.
|
||||
@param pt2 second point of the line segment.
|
||||
@param color line color.
|
||||
@param thickness line thickness.
|
||||
@param lineType type of the line,.
|
||||
@param shift number of fractional bits in the point coordinates.
|
||||
|
||||
Try it
|
||||
------
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_features_fitLine.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
@@ -0,0 +1,110 @@
|
||||
Contour Properties {#tutorial_js_contour_properties}
|
||||
==================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
- Here we will learn to extract some frequently used properties of objects like Solidity, Equivalent
|
||||
Diameter, Mask image, Mean Intensity etc.
|
||||
|
||||
1. Aspect Ratio
|
||||
---------------
|
||||
|
||||
It is the ratio of width to height of bounding rect of the object.
|
||||
|
||||
\f[Aspect \; Ratio = \frac{Width}{Height}\f]
|
||||
@code{.js}
|
||||
let rect = cv.boundingRect(cnt);
|
||||
let aspectRatio = rect.width / rect.height;
|
||||
@endcode
|
||||
|
||||
2. Extent
|
||||
---------
|
||||
|
||||
Extent is the ratio of contour area to bounding rectangle area.
|
||||
|
||||
\f[Extent = \frac{Object \; Area}{Bounding \; Rectangle \; Area}\f]
|
||||
@code{.js}
|
||||
let area = cv.contourArea(cnt, false);
|
||||
let rect = cv.boundingRect(cnt));
|
||||
let rectArea = rect.width * rect.height;
|
||||
let extent = area / rectArea;
|
||||
@endcode
|
||||
|
||||
3. Solidity
|
||||
-----------
|
||||
|
||||
Solidity is the ratio of contour area to its convex hull area.
|
||||
|
||||
\f[Solidity = \frac{Contour \; Area}{Convex \; Hull \; Area}\f]
|
||||
@code{.js}
|
||||
let area = cv.contourArea(cnt, false);
|
||||
cv.convexHull(cnt, hull, false, true);
|
||||
let hullArea = cv.contourArea(hull, false);
|
||||
let solidity = area / hullArea;
|
||||
@endcode
|
||||
|
||||
4. Equivalent Diameter
|
||||
----------------------
|
||||
|
||||
Equivalent Diameter is the diameter of the circle whose area is same as the contour area.
|
||||
|
||||
\f[Equivalent \; Diameter = \sqrt{\frac{4 \times Contour \; Area}{\pi}}\f]
|
||||
@code{.js}
|
||||
let area = cv.contourArea(cnt, false);
|
||||
let equiDiameter = Math.sqrt(4 * area / Math.PI);
|
||||
@endcode
|
||||
|
||||
5. Orientation
|
||||
--------------
|
||||
|
||||
Orientation is the angle at which object is directed. Following method also gives the Major Axis and
|
||||
Minor Axis lengths.
|
||||
@code{.js}
|
||||
let rotatedRect = cv.fitEllipse(cnt);
|
||||
let angle = rotatedRect.angle;
|
||||
@endcode
|
||||
|
||||
6. Mask and Pixel Points
|
||||
------------------------
|
||||
|
||||
In some cases, we may need all the points which comprises that object.
|
||||
|
||||
We use the function: **cv.transpose (src, dst)**
|
||||
@param src input array.
|
||||
@param dst output array of the same type as src.
|
||||
|
||||
\htmlonly
|
||||
<iframe src="../../js_contour_properties_transpose.html" width="100%"
|
||||
onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
|
||||
</iframe>
|
||||
\endhtmlonly
|
||||
|
||||
7. Maximum Value, Minimum Value and their locations
|
||||
---------------------------------------------------
|
||||
|
||||
We use the function: **cv.minMaxLoc(src, mask)**
|
||||
@param src input single-channel array.
|
||||
@param mask optional mask used to select a sub-array.
|
||||
|
||||
@code{.js}
|
||||
let result = cv.minMaxLoc(src, mask);
|
||||
let minVal = result.minVal;
|
||||
let maxVal = result.maxVal;
|
||||
let minLoc = result.minLoc;
|
||||
let maxLoc = result.maxLoc;
|
||||
@endcode
|
||||
|
||||
8. Mean Color or Mean Intensity
|
||||
-------------------------------
|
||||
|
||||
Here, we can find the average color of an object. Or it can be average intensity of the object in
|
||||
grayscale mode. We again use the same mask to do it.
|
||||
|
||||
We use the function: **cv.mean (src, mask)**
|
||||
@param src input array that should have from 1 to 4 channels so that the result can be stored in Scalar.
|
||||
@param mask optional operation mask.
|
||||
|
||||
@code{.js}
|
||||
let average = cv.mean(src, mask);
|
||||
@endcode
|
||||