自作しているFEHツールで、入力したマップ画像がどのマップ種なのかを自動判別したかったので、OpenCV.js で差の絶対値の総和を計算して相関を取る処理を書いてみました。cv.Mat 要素の総和を取る関数が OpenCV.js には見当たらなかったので仕方なく自前で計算しています。
let src1 = cv.imread(sourceCanvas1);
let src2 = cv.imread(sourceCanvas2);
let dst = new cv.Mat();
// 差の絶対値を計算
cv.absdiff(src1, src2, dst);
// 差の絶対値の総和を計算
let channels = dst.channels();
let sum = 0;
for (let y = 0; y < dst.rows; ++y) {
for (let x = 0; x < dst.cols; ++x) {
for (let c = 0; c < channels; ++c) {
sum += dst.ucharPtr(y, x)[c];
}
}
}
console.log(`sum = ${sum}`);
src1.delete();
src2.delete();
dst.delete();
しかし、これでは処理速度が大分遅くて実用に耐えない感じになってしまいました。
そこで、以下のようにして高速化したところ実用に耐える速度になりました。具体的には、事前に画像を縮小して全体の処理負荷を削減した、自前で画像処理をしている総和計算部分の負荷を減らすために差の絶対値画像をグレースケールに変換した2点になります。
let src1 = cv.imread(sourceCanvas1);
let src2 = cv.imread(sourceCanvas2);
// 高速化のために画像を縮小してから差の絶対値を取る(精度が落ちるので適度に)
let shrinkDiv = 4;
cv.resize(src1, src1, new cv.Size(src1.cols / shrinkDiv, src1.rows / shrinkDiv), 0, 0, cv.INTER_AREA);
cv.resize(src2, src2, new cv.Size(src1.cols, src1.rows), 0, 0, cv.INTER_AREA);
let dst = new cv.Mat();
cv.absdiff(src1, src2, dst);
// 高速化のためにグレースケールに変換し、1チャンネルのみで総和を計算する
cv.cvtColor(dst, dst, cv.COLOR_RGBA2GRAY, 0);
let channels = 1;
let sum = 0;
for (let y = 0; y < dst.rows; ++y) {
for (let x = 0; x < dst.cols; ++x) {
for (let c = 0; c < channels; ++c) {
sum += dst.ucharPtr(y, x)[c];
}
}
}
console.log(`sum = ${sum}`);
src1.delete();
src2.delete();
dst.delete();
コメント(1 件)
1(ID: 1445989647) 2022-01-26 14:19 something like: diffSum = diffGray.data.reduce(function(accumulator, currentValue) { return accumulator + currentValue; }, 0); will avoid the loop |