|
| 1 | +/** |
| 2 | + * Please refer to the python version of "YOLO object detection with OpenCV" by Adrian Rosebrock. |
| 3 | + * For more detail: https://www.pyimagesearch.com/2018/11/12/yolo-object-detection-with-opencv/ |
| 4 | + */ |
| 5 | +const fs = require("fs"); |
| 6 | +const path = require("path"); |
| 7 | +const { cv, drawBlueRect, runVideoDetection } = require("./utils"); |
| 8 | + |
| 9 | +if (!cv.xmodules.dnn) { |
| 10 | + throw new Error("exiting: opencv4nodejs compiled without dnn module"); |
| 11 | +} |
| 12 | + |
| 13 | +// replace with path where you unzipped darknet model |
| 14 | +const darknetPath = "../data/dnn/yolo-object-detection"; |
| 15 | + |
| 16 | +const cfgFile = path.resolve(darknetPath, "yolov3-tiny.cfg"); |
| 17 | +const weightsFile = path.resolve(darknetPath, "yolov3-tiny.weights"); |
| 18 | +const labelsFile = path.resolve(darknetPath, "coco.names"); |
| 19 | + |
| 20 | +if ( |
| 21 | + !fs.existsSync(weightsFile) || |
| 22 | + !fs.existsSync(cfgFile) || |
| 23 | + !fs.existsSync(labelsFile) |
| 24 | +) { |
| 25 | + console.log("could not find darknet model"); |
| 26 | + console.log("download the model from: https://pjreddie.com/darknet/yolo/"); |
| 27 | + throw new Error("exiting"); |
| 28 | +} |
| 29 | + |
| 30 | +// set webcam port |
| 31 | +const webcamPort = 0; |
| 32 | + |
| 33 | +const minConfidence = 0.5; |
| 34 | +const nmsThreshold = 0.3; |
| 35 | + |
| 36 | +// read classNames and store them in an array |
| 37 | +const labels = fs |
| 38 | + .readFileSync(labelsFile) |
| 39 | + .toString() |
| 40 | + .split("\n"); |
| 41 | + |
| 42 | +// initialize tensorflow darknet model from modelFile |
| 43 | +const net = cv.readNetFromDarknet(cfgFile, weightsFile); |
| 44 | + |
| 45 | +const classifyImg = img => { |
| 46 | + // object detection model works with 416 x 416 images |
| 47 | + const size = new cv.Size(416, 416); |
| 48 | + const vec3 = new cv.Vec(0, 0, 0); |
| 49 | + const [imgHeight, imgWidth] = img.sizes; |
| 50 | + |
| 51 | + // network accepts blobs as input |
| 52 | + const inputBlob = cv.blobFromImage(img, 1 / 255.0, size, vec3, true, true); |
| 53 | + net.setInput(inputBlob); |
| 54 | + |
| 55 | + // specify two layers "yolo_16" and "yolo_23" |
| 56 | + const layerNames = ["yolo_16", "yolo_23"]; |
| 57 | + |
| 58 | + console.time("net.forward"); |
| 59 | + // forward pass input through entire network |
| 60 | + const layerOutputs = net.forward(layerNames); |
| 61 | + console.timeEnd("net.forward"); |
| 62 | + |
| 63 | + let boxes = []; |
| 64 | + let confidences = []; |
| 65 | + let classIDs = []; |
| 66 | + |
| 67 | + layerOutputs.forEach(mat => { |
| 68 | + const output = mat.getDataAsArray(); |
| 69 | + output.forEach(detection => { |
| 70 | + const scores = detection.slice(5); |
| 71 | + const classId = scores.indexOf(Math.max(...scores)); |
| 72 | + const confidence = scores[classId]; |
| 73 | + |
| 74 | + if (confidence > minConfidence) { |
| 75 | + const box = detection.slice(0, 4); |
| 76 | + |
| 77 | + const centerX = parseInt(box[0] * imgWidth); |
| 78 | + const centerY = parseInt(box[1] * imgHeight); |
| 79 | + const width = parseInt(box[2] * imgWidth); |
| 80 | + const height = parseInt(box[3] * imgHeight); |
| 81 | + |
| 82 | + const x = parseInt(centerX - width / 2); |
| 83 | + const y = parseInt(centerY - height / 2); |
| 84 | + |
| 85 | + boxes.push(new cv.Rect(x, y, width, height)); |
| 86 | + confidences.push(confidence); |
| 87 | + classIDs.push(classId); |
| 88 | + |
| 89 | + const indices = cv.NMSBoxes( |
| 90 | + boxes, |
| 91 | + confidences, |
| 92 | + minConfidence, |
| 93 | + nmsThreshold |
| 94 | + ); |
| 95 | + |
| 96 | + indices.forEach(i => { |
| 97 | + const rect = boxes[i]; |
| 98 | + const imgRect = new cv.Rect(rect.x, rect.y, rect.width, rect.height); |
| 99 | + drawBlueRect(img, imgRect); |
| 100 | + const text = labels[classIDs[i]]; |
| 101 | + img.putText( |
| 102 | + text, |
| 103 | + new cv.Point(rect.x, rect.y + 0.1 * imgHeight), |
| 104 | + cv.FONT_ITALIC, |
| 105 | + 2, |
| 106 | + { |
| 107 | + color: new cv.Vec(255, 0, 0), |
| 108 | + thickness: 2 |
| 109 | + } |
| 110 | + ); |
| 111 | + drawBlueRect(img, imgRect); |
| 112 | + }); |
| 113 | + } |
| 114 | + }); |
| 115 | + }); |
| 116 | + |
| 117 | + cv.imshow("Darknet YOLO Object Detection", img); |
| 118 | +}; |
| 119 | + |
| 120 | +runVideoDetection(webcamPort, classifyImg); |
0 commit comments