OpenCv.js(图像处理)学习历程

opencv.js官网

4.5.0文档

以下内容整理于opencv.js官网。

简介

OpenCV由Gary Bradski于1999年在英特尔创建。第一次发行是在2000年。OpenCV支持c++、Python、Java等多种编程语言,支持Windows、Linux、Os X、Android、iOS等平台。基于CUDA和OpenCL的高速GPU操作接口也在积极开发中。OpenCV.js将OpenCV带到开放的web平台,并使JavaScript程序员可以使用它。

图片处理 

读取图片

readImage.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello OpenCV.js</title>
</head>
<body>
<h2>读取图片</h2>
<p id="status">OpenCV.js is loading...</p>
<div>
 <div class="inputoutput">
 <img id="imageSrc" alt="No Image" />
 <div class="caption">imageSrc <input type="file" id="fileInput" name="file" /></div>
 </div>
 <div class="inputoutput">
 <canvas id="canvasOutput" ></canvas>
 <div class="caption">canvasOutput</div>
 </div>
</div>
<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();
};
var Module = {
 // https://emscripten.org/docs/api_reference/module.html#Module.onRuntimeInitialized
 onRuntimeInitialized() {
 document.getElementById('status').innerHTML = 'OpenCV.js is ready.';
 }
};
</script>
<!-- <script async src="https://docs.opencv.org/4.5.0/opencv.js" type="text/javascript"></script> -->
<script async src="opencvjs/opencv.js" type="text/javascript"></script>
<script src="opencvjs/utils.js" type="text/javascript"></script>
</body>
</html>

浏览器运行。 

灰度图

blackAWhite.html


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Adaptive Threshold Example</title>
<link href="opencvjs/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h2>IMAGE</h2>
<p></p>
<div>
<div class="control"><button id="tryIt" disabled>Start</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 type="text/javascript" src="opencvjs/opencv.js"></script>
<script src="opencvjs/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>

浏览器运行。 

 

 阈值

inRangeImage.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello OpenCV.js</title>
</head>
<body>
<h2></h2>
<p id="status">OpenCV.js is loading...</p>
<div>
 <div class="inputoutput">
 <img id="imageSrc" alt="No Image" />
 <div class="caption">imageSrc <input type="file" id="fileInput" name="file" /></div>
 </div>
 <div class="inputoutput">
 <canvas id="canvasOutput" ></canvas>
 <div class="caption">canvasOutput</div>
 </div>
</div>
<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 src = cv.imread('imageSrc');
 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();
};
var Module = {
 // https://emscripten.org/docs/api_reference/module.html#Module.onRuntimeInitialized
 onRuntimeInitialized() {
 document.getElementById('status').innerHTML = 'OpenCV.js is ready.';
 }
};
</script>
<script async src="opencvjs/opencv.js" type="text/javascript"></script>
<script src="opencvjs/utils.js" type="text/javascript"></script>
</body>
</html>

 

其它 

imageTemplate.html

 修改框内的代码即可对图片进行不同的操作,此代码适用于大部分的官网中有关图片操作的代码。 

视频处理 

 均值漂移


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CamShift Example</title>
<link href="opencvjs/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<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 type="text/javascript" src="opencvjs/opencv.js"></script>
<script src="opencvjs/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 = 'video/cup.mp4';
});
</script>
</body>
</html>

背景差分 

backgroundSubtraction.html


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="opencvjs/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<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 type="text/javascript" src="opencvjs/opencv.js"></script>
<script src="opencvjs/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');

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 = 'video/box.mp4';
});
</script>
</body>
</html>

卡纳德方法

LucasKanade.html


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="opencvjs/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<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 type="text/javascript" src="opencvjs/opencv.js"></script>
<script src="opencvjs/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 = 'video/box.mp4';
});
</script>
</body>
</html>

人脸识别

人脸识别_照片 


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Face Detection Example</title>
<link href="opencvjs/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div>
<div class="control"><button id="tryIt" disabled>Start</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" /></div>
</td>
<td>
<div class="caption">canvasOutput</div>
</td>
</tr>
</table>
</div>
<script type="text/javascript" src="opencvjs/opencv.js"></script>
<script src="opencvjs/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>

 

 以上测试图片来自百度。

可以看到,有的地方不是耳朵也会被标记成耳朵,原因是官方的数据集数据比较微小,数据不够准确,但是眼睛的地方能标记出来就已经达到我们的学习目的了,以后可以用更精确的数据集替换效果就会好很多。

人脸识别_相机 


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Face Detection Camera Example</title>
<link href="opencvjs/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<!-- <h2>Face Detection Camera Example</h2> -->
<div>
<div class="control"><button id="startAndStop">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 type="text/javascript" src="opencvjs/opencv.js"></script>
<script src="opencvjs/utils.js" type="text/javascript"></script>
<!-- <script src="opencvjs/adapter-5.0.4.js" type="text/javascript"></script> -->
<!-- <script src="opencvjs/known.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>

4.8.0文档

4.8.0相对于4.5.0新增了深度学习模块。

深度神经网络

 

选择相应的model,从对应的链接中得到对应的数据集文件,看第一块代码的配置项是否一致。 

 上传对应的文件,点击运行。

起初认为是时间问题,晚上挂了一段时间,早上起来依旧没有任何数据 ,打开浏览器审查页面,发现有很多报错,无论如何我都得不到想要的结果,这块就放弃了。

补充

完整文件

gitee获取

去掉文本代码区域

在实际开发中我们是不需要textarea的,所以必须去掉它。但是我尝试更改了html文件和js文件,没有成功,所以干脆直接让textarea区域:display:none。

<textarea class="code" rows="9" cols="100" id="codeEditor" spellcheck="false" style="display: none;"></textarea>

参考文献

代码哈士,opencv.js人脸识别简单

opencv.js官网的js文件不是真正的js文件,官网文档里需要建立其环境,这片文章介绍通过爬取得到官方的资源。 

opencv.js官网 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/64352.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习和OpenCV的对象检测(MobileNet SSD图像识别)

基于深度学习的对象检测时,我们主要分享以下三种主要的对象检测方法: Faster R-CNN(后期会来学习分享)你只看一次(YOLO,最新版本YOLO3,后期我们会分享)单发探测器(SSD,本节介绍,若你的电脑配置比较低,此方法比较适合R-CNN是使用深度学习进行物体检测的训练模型; 然而,…

【linux】安装pytorch3d

写在开头 不要看网上的博客安装&#xff0c;直接参考官方安装文档去安装。 坑 坑1&#xff1a;安装pytorch3d后torch.cuda用不了 使用下面的命令安装后 conda install pytorch3d会提示安装下面的包&#xff0c;注意pytorch和torchvision都是cpu版本的&#xff0c;这样就会…

参考RabbitMQ实现一个消息队列

文章目录 前言小小消息管家1.项目介绍2. 需求分析2.1 API2.2 消息应答2.3 网络通信协议设计 3. 开发环境4. 项目结构介绍4.1 配置信息 5. 项目演示 前言 消息队列的本质就是阻塞队列&#xff0c;它的最大用途就是用来实现生产者消费者模型&#xff0c;从而实现解耦合以及削峰填…

docker安装neo4j

参考文章&#xff1a; 1、Mac 本地以 docker 方式配置 neo4j_neo4j mac docker_Abandon_first的博客-CSDN博客 2、https://www.cnblogs.com/caoyusang/p/13610408.html 安装的时候&#xff0c;参考了以上文章。遇到了一些问题&#xff0c;记录下自己的安装过程&#xff1a; …

在centos7下通过docker 安装onlyoffice

因为需要调试网盘&#xff0c;所以今天安装一下centos7的onlyoffice 官方介绍如下&#xff1a; 为了方便&#xff0c;还是通过docker方式来安装onlyoffice了&#xff0c;这里我们采用社区版本了。 1、下载docker安装包 如下&#xff1a; docker pull onlyoffice/documentserv…

桌面端UI自动化测试如何让SplitButtonControl展开

原始SplitButtonControl图 从图中鼠标所指的控件属性为&#xff1a; ControlType&#xff08;控件类型&#xff09;: SplitButtonControl ClassName&#xff08;类名&#xff09;: SplitButton AutomationId&#xff08;自动化ID&#xff09;: esri_geoprocessing_Pyt…

m3u8怎么变成本地视频?一个小妙招教你轻松搞定

m3u8视频是一种流媒体视频格式&#xff0c;它将整个视频分成多个小文件&#xff0c;每个小文件的长度通常为几秒钟。这些小文件存储在服务器上&#xff0c;并通过网络传输到观众的设备上。当观众观看视频时&#xff0c;视频播放器会按照正确的顺序下载和播放这些小文件&#xf…

【Hystrix技术指南】(4)故障切换的运作流程

[每日一句] 也许你度过了很糟糕的一天&#xff0c;但这并不代表你会因此度过糟糕的一生。 [背景介绍] 分布式系统的规模和复杂度不断增加&#xff0c;随着而来的是对分布式系统可用性的要求越来越高。在各种高可用设计模式中&#xff0c;【熔断、隔离、降级、限流】是经常被使…

uni-app离线打包高德地图导入android studio不能正常显示

本人使用的uni-app SDK版本&#xff1a;Android-SDK3.8.7.81902_20230704 1.导入以上文件&#xff0c;依赖已经自动添加了 2.确保这个正常引入 3.修改AndroidMainifest.xml,添加自己的密钥

flask------消息闪现 flash

1介绍 flask提供了一个非常有用的flash()函数&#xff0c;它可以用来“闪现”需要提示给用户的消息&#xff0c;比如当用户登录成功后显示“欢迎回来&#xff01;”。在视图函数调用flash()函数&#xff0c;传入消息内容&#xff0c;flash&#xff08;&#xff09;函数把消息存…

win10 2022unity设置中文

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言解决方法 前言 在Edit->preferences里找不到language选项。 解决方法 【1】打开下面地址 注意 :把{version}换成你当前安装的版本&#xff0c;比如说如果…

textarea 标签如何创建多行文本输入框?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ textarea 的写法⭐ 代码含义⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、…

Harbor企业镜像仓库部署(本地)

简述&#xff1a; Docker 官方镜像仓库是用于管理公共镜像的地方&#xff0c;大家可以在上面找到想要的镜像&#xff0c;也可以把自己的镜像推送上去。但是有时候服务器无法访问互联网&#xff0c;或者不希望将自己的镜像放到互联网上&#xff0c;那么就需要用到 Docker Regis…

通过easyui实现动态控制表格字段显示、导出表格数据

前言 学过layui前端框架的都知道&#xff0c;layui默认帮我们实现了控制表格字段显示以及数据的导出功能。 1、控制表格字段显示 2、数据导出 3、导出为pdf&#xff1a;导出按钮的右边那个按钮就是打印pdf的 那么&#xff0c;easyui要怎么实现这些功能呢&#xff1f;这篇文章就…

深度学习中的优化算法

文章目录 前言一、优化和深度学习1.1 优化的目标1.2 深度学习中的优化挑战1.2.1 局部最小值1.2.2 鞍点1.2.3 梯度消失 二、梯度下降2.1 一维梯度下降2.1.1 学习率 2.2 多元梯度下降2.3 自适应方法2.3.1 牛顿法2.3.2 其他自适应方法 三、随机梯度下降3.1 随机梯度更新3.2 动态学…

了解Swarm 集群管理

Swarm 集群管理 简介 Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API&#xff0c;所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。 支持的工具包括但不限…

ubuntu服务器配置ftp服务

需求&#xff1a;配置ftp服务用于在windows电脑上直接浏览、下载、上传ubuntu服务器上的文件&#xff0c;用于文件共享&#xff0c;方便实用 效果&#xff1a;用户打开windows资源管理器后输入ftp://xxx.xxx.xxx.xxx &#xff08;公网IP地址&#xff09;后&#xff0c;即可浏览…

linux onlyOffice docker 离线部署

文章目录 前言1. 安装Docker容器2. 拉取镜像3. 验证 前言 docker 离线安装onlyoffice&#xff0c;如在线安装可直接跳过导出导入镜像步骤&#xff0c;拉取后直接运行。 1. 安装Docker容器 下载文件 wget https://download.docker.com/linux/static/stable/x86_64/docker-19…

在Linux中安装MySQL

在Linux中安装MySQL 检测当前系统中是否安装MySQL数据库 命令作用rpm -qa查询当前系统中安装的所有软件rpm -qa|grep mysql查询当前系统中安装的名称带mysql的软件rpm -qa | grep mariadb查询当前系统中安装的名称带mariadb的软件 RPM ( Red-Hat Package Manager )RPM软件包管理…

[golang gin框架] 45.Gin商城项目-微服务实战之后台Rbac微服务之角色权限关联

角色和权限的关联关系在前面文章中有讲解,见[golang gin框架] 14.Gin 商城项目-RBAC管理之角色和权限关联,角色授权,在这里通过微服务来实现角色对权限的授权操作,这里要实现的有两个功能,一个是进入授权,另一个是,授权提交操作,页面如下: 一.实现后台权限管理Rbac之角色权限关…