学了一段时间的神经网络,尝试了几个版本的yolo模型和其他类型神经网络模型。
前两天看到了js onnx运行时,就测试了下。
先试了试刚在测试的对抗网络,生成人脸……经过了几次尝试修改调用成功了,看上去效果还不错,于是就再试试yolov7了。
yolov7调用是比较顺利的,只是还需后续处理才能得到最后的结果。这个处理代码网上没找到现成的js代码,自己写写算了。
参考C++的代码写了下
function yolov7(data, score_threshold, nms_threshold) {
let netAnchors = [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]];
let netStride = [8, 16, 32, 64]
let confThreshold = score_threshold;
let datas = [];
for (let t in data) {
datas.push(data[t]);
}
datas.sort(function (a, b) { return b.dims[2] - a.dims[2]; });
let res = [];
for (let i = 0; i < datas.length; i++) {
res = res.concat(get(datas[i], netAnchors[i], netStride[i]));
}
res = nms(res, score_threshold, nms_threshold);
return res;
function sigmoid(v) {
return 1.0 / (1 + Math.exp(-v));
}
function getMaxIndex(data, start, len) {
let i = 0;
let v = data[start];
for (let j = 1; j < len; j++) {
if (data[start + j] > v) {
v = data[start + j];
i = j;
}
}
return { index: i, score: v };
}
function get(data, anchors, stride) {
let gh = data.dims[2];
let gw = data.dims[3];
let c = data.dims[4];
let classCount = c - 5;
let res = [];
let p = 0;
for (let i = 0; i < data.dims[1]; i++) {
let aw = anchors[i * 2];
let ah = anchors[i * 2 + 1];
for (let gy = 0; gy < gh; gy++) {
for (let gx = 0; gx < gw; gx++) {
let boxScore = sigmoid(data.data[p + 4]);
if (boxScore >= confThreshold) {
let indexScore = getMaxIndex(data.data, p + 5, classCount);
indexScore.score = sigmoid(indexScore.score);
if (indexScore.score >= confThreshold) {
let x = (sigmoid(data.data[p]) * 2 - 0.5 + gx) * stride;
let y = (sigmoid(data.data[p + 1]) * 2 - 0.5 + gy) * stride;
let w = Math.pow(sigmoid(data.data[p + 2]) * 2, 2) * aw;
let h = Math.pow(sigmoid(data.data[p + 3]) * 2, 2) * ah;
res.push({
x: (x - 0.5 * w),
y: (y - 0.5 * h),
w: w,
h: h,
index: indexScore.index,
score: indexScore.score
});
}
}
p += c;
}
}
}
return res;
}
function iou(a, b) {
var aa = a.w * a.h;
var ba = b.w * b.h;
var x = Math.max(a.x, b.x);
var y = Math.max(a.y, b.y);
var xx = Math.min(a.x + a.w, b.x + b.w);
var yy = Math.min(a.y + a.h, b.y + b.h);
var w = xx - x;
var h = yy - y;
if (w <= 0 || h <= 0) return 0;
var area = w * h;
return area / (aa + ba - area);
}
function nms(boxs, score_threshold, nms_threshold) {
let score_indexs = [];
for (var i = 0; i < boxs.length; i++) {
if (boxs[i].score > score_threshold)
score_indexs.push({ second: i, first: boxs[i].score });
}
score_indexs.sort(function (a, b) { return b.first - a.first });
let res = [];
let adaptive_threshold = nms_threshold;
for (let i = 0; i < score_indexs.length; i++) {
let idx = score_indexs[i].second;
let keep = true;
for (let k = 0; k < res.length && keep; k++) {
let k_idx = res[k];
let v = iou(boxs[idx], boxs[k_idx]);
keep = v <= adaptive_threshold;
}
if (keep) {
res.push(idx);
}
}
for (let i = 0; i < res.length; i++) {
res[i] = boxs[res[i]];
}
return res;
}
}
调用
以上调用是在 yolov7 tiny 的模型测试的,导出 onnx 时 --grid 参数=False
简单测试结果