Creating streamAndDetect script that will stream from rtsp source and detect persons
This commit is contained in:
parent
4fe8f3e0ec
commit
53c1b162ae
@ -1,2 +1,3 @@
|
|||||||
REF_IMAGE_DIR=
|
REF_IMAGE_DIR=
|
||||||
TRAINED_MODEL_DIR=
|
TRAINED_MODEL_DIR=
|
||||||
|
OUT_DIR=
|
66
scripts/streamAndDetect.ts
Normal file
66
scripts/streamAndDetect.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { Rtsp } from "rtsp-stream/lib";
|
||||||
|
import { FaceMatcher, nets } from "@vladmandic/face-api";
|
||||||
|
import * as faceapi from "@vladmandic/face-api";
|
||||||
|
import canvas from "canvas";
|
||||||
|
import fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
|
import dotenv from "dotenv-extended";
|
||||||
|
import { getFaceDetectorOptions, saveFile } from "../src/common";
|
||||||
|
require("@tensorflow/tfjs-node");
|
||||||
|
|
||||||
|
const { Canvas, Image, ImageData } = canvas;
|
||||||
|
//@ts-ignore
|
||||||
|
faceapi.env.monkeyPatch({ Canvas, Image, ImageData });
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
dotenv.load({
|
||||||
|
silent: false,
|
||||||
|
errorOnMissing: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const modelDir = process.env.TRAINED_MODEL_DIR as string;
|
||||||
|
|
||||||
|
const rtsp = new Rtsp("rtsp://brandon:asdf1234@192.168.1.229/live", {
|
||||||
|
rate: 10,
|
||||||
|
});
|
||||||
|
const faceDetectionNet = nets.ssdMobilenetv1;
|
||||||
|
|
||||||
|
await faceDetectionNet.loadFromDisk(path.join(__dirname, "../weights"));
|
||||||
|
await nets.faceLandmark68Net.loadFromDisk(path.join(__dirname, "../weights"));
|
||||||
|
await nets.faceRecognitionNet.loadFromDisk(
|
||||||
|
path.join(__dirname, "../weights")
|
||||||
|
);
|
||||||
|
|
||||||
|
const files = fs.readdirSync(modelDir);
|
||||||
|
const matchers: Array<FaceMatcher> = [];
|
||||||
|
for (const file of files) {
|
||||||
|
const raw = fs.readFileSync(path.join(modelDir, file), "utf-8");
|
||||||
|
const content = JSON.parse(raw);
|
||||||
|
matchers.push(FaceMatcher.fromJSON(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
rtsp.on("data", async (data: Buffer) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = data.toString("base64");
|
||||||
|
const input = await canvas.loadImage(data, "base64");
|
||||||
|
const resultsQuery = await faceapi
|
||||||
|
.detectAllFaces(input, getFaceDetectorOptions(faceDetectionNet))
|
||||||
|
.withFaceLandmarks()
|
||||||
|
.withFaceDescriptors();
|
||||||
|
|
||||||
|
for (const res of resultsQuery) {
|
||||||
|
for (const matcher of matchers) {
|
||||||
|
const bestMatch = matcher.findBestMatch(res.descriptor);
|
||||||
|
console.log(bestMatch.label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
rtsp.on("error", (err) => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
rtsp.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
@ -2,9 +2,10 @@ import * as faceapi from "@vladmandic/face-api";
|
|||||||
import canvas from "canvas";
|
import canvas from "canvas";
|
||||||
import fs, { lstatSync } from "fs";
|
import fs, { lstatSync } from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { LabeledFaceDescriptors, TNetInput } from "@vladmandic/face-api";
|
import { TNetInput } from "@vladmandic/face-api";
|
||||||
import * as mime from "mime-types";
|
import * as mime from "mime-types";
|
||||||
import dotenv from "dotenv-extended";
|
import dotenv from "dotenv-extended";
|
||||||
|
import { getFaceDetectorOptions } from "../src/common";
|
||||||
require("@tensorflow/tfjs-node");
|
require("@tensorflow/tfjs-node");
|
||||||
|
|
||||||
const { Canvas, Image, ImageData } = canvas;
|
const { Canvas, Image, ImageData } = canvas;
|
||||||
@ -90,19 +91,4 @@ const main = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// SsdMobilenetv1Options
|
|
||||||
const minConfidence = 0.5;
|
|
||||||
|
|
||||||
// TinyFaceDetectorOptions
|
|
||||||
const inputSize = 408;
|
|
||||||
const scoreThreshold = 0.5;
|
|
||||||
|
|
||||||
function getFaceDetectorOptions(net: faceapi.NeuralNetwork<any>) {
|
|
||||||
return net === faceapi.nets.ssdMobilenetv1
|
|
||||||
? new faceapi.SsdMobilenetv1Options({ minConfidence })
|
|
||||||
: new faceapi.TinyFaceDetectorOptions({ inputSize, scoreThreshold });
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseDir = path.resolve(__dirname, "../out");
|
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
25
src/common.ts
Normal file
25
src/common.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import * as faceapi from "@vladmandic/face-api";
|
||||||
|
import * as path from "path";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
// SsdMobilenetv1Options
|
||||||
|
export const minConfidence = 0.5;
|
||||||
|
|
||||||
|
// TinyFaceDetectorOptions
|
||||||
|
export const inputSize = 408;
|
||||||
|
export const scoreThreshold = 0.5;
|
||||||
|
|
||||||
|
export const getFaceDetectorOptions = (net: faceapi.NeuralNetwork<any>) => {
|
||||||
|
return net === faceapi.nets.ssdMobilenetv1
|
||||||
|
? new faceapi.SsdMobilenetv1Options({ minConfidence })
|
||||||
|
: new faceapi.TinyFaceDetectorOptions({ inputSize, scoreThreshold });
|
||||||
|
};
|
||||||
|
|
||||||
|
export function saveFile(fileName: string, buf: Buffer) {
|
||||||
|
const baseDir = process.env.OUT_DIR as string;
|
||||||
|
if (!fs.existsSync(baseDir)) {
|
||||||
|
fs.mkdirSync(baseDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(path.resolve(baseDir, fileName), buf);
|
||||||
|
}
|
21
src/index.ts
21
src/index.ts
@ -1,20 +1 @@
|
|||||||
import { Rtsp } from "rtsp-stream/lib";
|
console.log("Hello World");
|
||||||
|
|
||||||
const main = async () => {
|
|
||||||
const rtsp = new Rtsp("rtsp://brandon:asdf1234@192.168.1.229/live", {
|
|
||||||
rate: 10,
|
|
||||||
});
|
|
||||||
|
|
||||||
rtsp.on("data", async (data: Buffer) => {
|
|
||||||
console.log();
|
|
||||||
process.exit(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
rtsp.on("error", (err) => {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
rtsp.start();
|
|
||||||
};
|
|
||||||
|
|
||||||
main();
|
|
||||||
|
@ -59,5 +59,6 @@
|
|||||||
/* Advanced Options */
|
/* Advanced Options */
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||||
}
|
},
|
||||||
|
"include": ["./src"]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user