Rewrote column test, again (todo: actually analyse results)
This commit is contained in:
parent
d51ce8add7
commit
eaa1a0975a
@ -539,60 +539,300 @@ class EdgeDetect{
|
|||||||
// helper functions
|
// helper functions
|
||||||
|
|
||||||
|
|
||||||
_columnTest2(image, top, bottom, colsIn, colsOut, reverseSearchDirection) {
|
// Column tests
|
||||||
let tmpI;
|
// Here's a fun thing. I reckon this bit of code could potentially run often enough that L1/L2 cache misses
|
||||||
let edgeDetectCount = 0;
|
// could really start to add up (especially if I figure the RAM usage problem which causes insane RAM usage
|
||||||
if(reverseSearchDirection){
|
// if you run this 30-60 times a second)
|
||||||
for(var i = bottom - this.conf.canvasImageDataRowLength; i >= top; i-= this.conf.canvasImageDataRowLength){
|
//
|
||||||
for(let c = 0; c < colsIn.length; c++){
|
// so here's two functions. _columnTest3_cross has some optimization that tries to minimize cache misses,
|
||||||
if (colsIn[c].blackFound && colsIn[c].imageFound) {
|
// but the problem is that I don't actually know 100% what I'm doing so it might be pointless. It scans the
|
||||||
// če smo našli obe točki, potem ne pregledujemo več.
|
// image array line-by-line, rather than column-by-column. This has some advantages (e.g. we can end the
|
||||||
// if we found both points, we don't continue anymore
|
// search for letterbox early), and some disadvantages (the code is a mess)
|
||||||
|
//
|
||||||
|
// some time later down the line, I might actually implement _columnTest3_singleCol, which does shit in the
|
||||||
|
// opposite direction (column-by-column rather than row-by-row)
|
||||||
|
_columnTest3_cross(image, top, bottom, colsIn, colsOut, reverseSearchDirection) {
|
||||||
|
// this function is such a /r/badcode bait.
|
||||||
|
//
|
||||||
|
// this is the shit we do to avoid function calls and one extra if sentence/code repetition
|
||||||
|
// pretend I was drunk when I wrote this
|
||||||
|
let tmpi, lastTmpI = 0, edgeDetectCount = 0, edgeDetectColsLeft = colsIn.length;
|
||||||
|
let tmpVal = 0;
|
||||||
|
let increment, arrayStart, arrayEnd;
|
||||||
|
|
||||||
|
let loopCond, loopComparator, loopIndex;
|
||||||
|
|
||||||
|
if (reverseSearchDirection) {
|
||||||
|
increment = -this.conf.canvasImageDataRowLength;
|
||||||
|
arrayStart = bottom - this.conf.canvasImageDataRowLength;
|
||||||
|
arrayEnd = top;
|
||||||
|
|
||||||
|
// this is a hack so we get pointer-like things rather than values
|
||||||
|
loopCond = {compare: {i: arrayEnd}, index: {i: 0}}
|
||||||
|
loopComparator = loopCond.index;
|
||||||
|
loopIndex = loopCond.compare;
|
||||||
|
} else {
|
||||||
|
increment = this.conf.canvasImageDataRowLength;
|
||||||
|
arrayStart = top;
|
||||||
|
arrayEnd = bottom;
|
||||||
|
|
||||||
|
// this is a hack so we get pointer-like things rather than values
|
||||||
|
loopCond = {compare: {i: arrayEnd}, index: {i: 0}}
|
||||||
|
loopComparator = loopCond.compare;
|
||||||
|
loopIndex = loopCond.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep temporary column data in a separate column array:
|
||||||
|
const colsTmp = new Array(colsIn.length);
|
||||||
|
for (let i = 0; i < colsTmp.length; i++) {
|
||||||
|
colsTmp[i] = {
|
||||||
|
blackFound: false,
|
||||||
|
imageFound: false, // misleading name — also true if we ran over gradientSampleSize pixels from image
|
||||||
|
// whether that actually count as an image depends on how aggressive gradientDetection is
|
||||||
|
lastValue: -1,
|
||||||
|
diffIndex: 0,
|
||||||
|
diffs: new Array(this.settings.active.arDetect.blackbar.gradientSampleSize).fill(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Things to keep in mind: loopCond.index.i is always index.
|
||||||
|
// loopIndex.i could actually be loopCond.compare.i (comparator) and
|
||||||
|
// loopComparator.i could actually be loopCond.index.i (real index)
|
||||||
|
for (loopCond.index.i = arrayStart; loopIndex.i < loopComparator.i; loopCond.index.i += increment) {
|
||||||
|
|
||||||
|
// če smo našli toliko mejnih točk, da s preostalimi stolpci ne moremo doseči naše meje, potem prenehamo
|
||||||
|
// if we found enough edge points so that we couldn't top that limit with remaining columns, then we stop
|
||||||
|
// searching forward
|
||||||
|
edgeDetectColsLeft -= edgeDetectCount;
|
||||||
|
if (edgeDetectColsLeft < this.colsThreshold || edgeDetectCount >= this.colsThreshold) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
edgeDetectCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// če v eni vrstici dobimo dovolj točk, ki grejo čez našo mejo zaznavanja, potem bomo nehali
|
||||||
|
// the first line that goes over our detection treshold wins
|
||||||
|
for (let c = 0; c < colsIn.length; c++) {
|
||||||
|
|
||||||
|
// there's really no point in checking this column if we already found image point
|
||||||
|
if (colsTmp[c].imageFound) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpI = loopCond.index.i + (colsIn[c].value << 2);
|
||||||
|
|
||||||
|
// najprej preverimo, če je piksel presegel mejo črnega robu
|
||||||
|
// first we check whether blackbarThreshold was exceeded
|
||||||
|
if (! colsTmp[c].blackFound) {
|
||||||
|
if( image[tmpI] > this.blackbarThreshold ||
|
||||||
|
image[tmpI + 1] > this.blackbarThreshold ||
|
||||||
|
image[tmpI + 2] > this.blackbarThreshold ){
|
||||||
|
|
||||||
|
colsOut[c].black = ~~(i / this.conf.canvasImageDataRowLength); // note — this value is off by one
|
||||||
|
colsOut[c].col = colsIn[c].value;
|
||||||
|
colsTmp[c].blackFound = true;
|
||||||
|
|
||||||
|
// prisili, da se zanka izvede še enkrat ter preveri,
|
||||||
|
// ali trenuten piksel preseže tudi imageThreshold
|
||||||
|
//
|
||||||
|
// force the loop to repeat this step and check whether
|
||||||
|
// current pixel exceeds imageThreshold as well
|
||||||
|
c--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tmpI = i + (colsIn[c].value << 2);
|
} else {
|
||||||
|
// če smo dobili piksel, ki presega blackbar, preverimo do gradientSampleSize dodatnih pikslov.
|
||||||
|
// ko dobimo piksel čez imageTreshold oz. gradientSampleSize, nastavimo imageFound. Ali je to veljavno
|
||||||
|
// bomo preverili v koraku analize, ki sledi kasneje
|
||||||
|
//
|
||||||
|
// if we found a pixel that exceeds blackbar, we check up to gradientSampleSize additional pixels.
|
||||||
|
// when we get a pixel over imageTreshold or gradientSampleSize, we flip the imageFound. We'll bother
|
||||||
|
// with whether that's legit in analysis step, which will follow soon (tm)
|
||||||
|
|
||||||
// najprej preverimo, če je piksel presegel mejo črnega robu
|
if (image[tmpI] > this.imageThreshold ||
|
||||||
// first we check whether blackbarThreshold was exceeded
|
image[tmpI + 1] > this.imageThreshold ||
|
||||||
if(! colsIn[c].blackFound) {
|
image[tmpI + 2] > this.imageThreshold ){
|
||||||
if( image[tmpI] > this.blackbarThreshold ||
|
|
||||||
image[tmpI + 1] > this.blackbarThreshold ||
|
colsOut[c].image = ~~(i / this.conf.canvasImageDataRowLength)
|
||||||
image[tmpI + 2] > this.blackbarThreshold ){
|
|
||||||
|
|
||||||
colsOut[c].black = (i / this.conf.canvasImageDataRowLength) - 1;
|
|
||||||
colsOut[c].col = colsIn[c].value;
|
|
||||||
colsIn[c].blackFound = 1;
|
|
||||||
|
|
||||||
// prisili, da se zanka izvede še enkrat ter preveri,
|
|
||||||
// ali trenuten piksel preseže tudi imageThreshold
|
|
||||||
//
|
|
||||||
// force the loop to repeat this step and check whether
|
|
||||||
// current pixel exceeds imageThreshold as well
|
|
||||||
c--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (colsIn[c].blackFound++ > this.settings.active.arDetect.blackbar.gradientSampleSize) {
|
|
||||||
colsIn[c].imageFound = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// zatem preverimo, če je piksel presegel mejo, po kateri sklepamo, da
|
|
||||||
// predstavlja sliko. Preverimo samo, če smo v stolpcu že presegli
|
|
||||||
// blackThreshold
|
|
||||||
//
|
|
||||||
// then we check whether pixel exceeded imageThreshold
|
|
||||||
if (image[tmpI] > this.imageThreshold ||
|
|
||||||
image[tmpI + 1] > this.imageThreshold ||
|
|
||||||
image[tmpI + 2] > this.imageThreshold ){
|
|
||||||
|
|
||||||
colsOut[c].image = (i / this.conf.canvasImageDataRowLength)
|
colsTmp[c].imageFound = true;
|
||||||
colsIn[c].imageFound = true;
|
edgeDetectCount++;
|
||||||
edgeDetectCount++;
|
}
|
||||||
|
|
||||||
|
// v vsakem primeru shranimo razliko med prejšnjim in trenutnim pikslom za kasnejšo analizo
|
||||||
|
// in any case, save the difference between the current and the previous pixel for later analysis
|
||||||
|
|
||||||
|
colsTmp[c].lastValue = image[tmpI] + image[tmpI+1] + image[tmpI+2];
|
||||||
|
if (colsTmp[c].diffIndex !== 0) {
|
||||||
|
colsTmp[c].diffs[colsTmp.diffIndex] = colsTmp[c].lastValue - colsTmp[c].diffs[diffIndex - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
cols[c].diffIndex++;
|
||||||
|
if (colsTmp[c].diffIndex > this.settings.active.arDetect.blackbar.gradientSampleSize) {
|
||||||
|
colsTmp[c].imageFound = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_columnTest3_singleCol(image, top, bottom, colsIn, colsOut, reverseSearchDirection) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_columnTest2(image, top, bottom, colsIn, colsOut, reverseSearchDirection) {
|
||||||
|
let tmpI;
|
||||||
|
let lastTmpI = 0;
|
||||||
|
let edgeDetectCount = 0;
|
||||||
|
for(const c in colsOut) {
|
||||||
|
c.diffs = [];
|
||||||
|
}
|
||||||
|
if (reverseSearchDirection) {
|
||||||
|
if (this.settings.active.arDetect.blackbar.antiGradientMode === AntiGradientMode.Disabled) {
|
||||||
|
// todo: remove gradient detection code from this branch
|
||||||
|
for(var i = bottom - this.conf.canvasImageDataRowLength; i >= top; i-= this.conf.canvasImageDataRowLength){
|
||||||
|
for(let c = 0; c < colsIn.length; c++){
|
||||||
|
if (colsIn[c].blackFound && colsIn[c].imageFound) {
|
||||||
|
// če smo našli obe točki, potem ne pregledujemo več.
|
||||||
|
// if we found both points, we don't continue anymore
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmpI = i + (colsIn[c].value << 2);
|
||||||
|
|
||||||
|
// najprej preverimo, če je piksel presegel mejo črnega robu
|
||||||
|
// first we check whether blackbarThreshold was exceeded
|
||||||
|
if(! colsIn[c].blackFound) {
|
||||||
|
if( image[tmpI] > this.blackbarThreshold ||
|
||||||
|
image[tmpI + 1] > this.blackbarThreshold ||
|
||||||
|
image[tmpI + 2] > this.blackbarThreshold ){
|
||||||
|
|
||||||
|
colsOut[c].black = (i / this.conf.canvasImageDataRowLength) - 1;
|
||||||
|
colsOut[c].col = colsIn[c].value;
|
||||||
|
colsIn[c].blackFound = 1;
|
||||||
|
|
||||||
|
// prisili, da se zanka izvede še enkrat ter preveri,
|
||||||
|
// ali trenuten piksel preseže tudi imageThreshold
|
||||||
|
//
|
||||||
|
// force the loop to repeat this step and check whether
|
||||||
|
// current pixel exceeds imageThreshold as well
|
||||||
|
c--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (colsIn[c].blackFound++ > this.settings.active.arDetect.blackbar.gradientSampleSize) {
|
||||||
|
colsIn[c].imageFound = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// zatem preverimo, če je piksel presegel mejo, po kateri sklepamo, da
|
||||||
|
// predstavlja sliko. Preverimo samo, če smo v stolpcu že presegli
|
||||||
|
// blackThreshold
|
||||||
|
//
|
||||||
|
// then we check whether pixel exceeded imageThreshold
|
||||||
|
if (image[tmpI] > this.imageThreshold ||
|
||||||
|
image[tmpI + 1] > this.imageThreshold ||
|
||||||
|
image[tmpI + 2] > this.imageThreshold ){
|
||||||
|
|
||||||
|
colsOut[c].image = (i / this.conf.canvasImageDataRowLength)
|
||||||
|
colsIn[c].imageFound = true;
|
||||||
|
edgeDetectCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(edgeDetectCount >= this.colsThreshold) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(edgeDetectCount >= this.colsThreshold) {
|
} else {
|
||||||
break;
|
// anti-gradient detection
|
||||||
|
for(var i = bottom - this.conf.canvasImageDataRowLength; i >= top; i-= this.conf.canvasImageDataRowLength){
|
||||||
|
for(let c = 0; c < colsIn.length; c++){
|
||||||
|
if (colsIn[c].blackFound && colsIn[c].imageFound) {
|
||||||
|
// če smo našli obe točki, potem ne pregledujemo več.
|
||||||
|
// if we found both points, we don't continue anymore.
|
||||||
|
|
||||||
|
if (colsIn[c].analysisDone) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colsOut[c].diffs.length < 5) {
|
||||||
|
colsIn[c].analysisDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// average analysis — if steps between pixels are roughly equal, we're looking at a gradient
|
||||||
|
let sum_avg = 0;
|
||||||
|
for (let i = 2; i <= colsOut[c].diffs; i++) {
|
||||||
|
sum_avg += colsOut[c].diffs[i-1] - colsOut[c].diffs[i];
|
||||||
|
}
|
||||||
|
sum_avg /= colsOut[c].diffs.length - 2;
|
||||||
|
|
||||||
|
for (let i = 2; i <= colsOut[c].diffs; i++) {
|
||||||
|
sum_avg += colsOut[c].diffs[i-1] - colsOut[c].diffs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpI = i + (colsIn[c].value << 2);
|
||||||
|
|
||||||
|
// najprej preverimo, če je piksel presegel mejo črnega robu
|
||||||
|
// first we check whether blackbarThreshold was exceeded
|
||||||
|
if(! colsIn[c].blackFound) {
|
||||||
|
if( image[tmpI] > this.blackbarThreshold ||
|
||||||
|
image[tmpI + 1] > this.blackbarThreshold ||
|
||||||
|
image[tmpI + 2] > this.blackbarThreshold ){
|
||||||
|
|
||||||
|
colsOut[c].black = (i / this.conf.canvasImageDataRowLength) - 1;
|
||||||
|
colsOut[c].col = colsIn[c].value;
|
||||||
|
colsIn[c].blackFound = 1;
|
||||||
|
|
||||||
|
// prisili, da se zanka izvede še enkrat ter preveri,
|
||||||
|
// ali trenuten piksel preseže tudi imageThreshold
|
||||||
|
//
|
||||||
|
// force the loop to repeat this step and check whether
|
||||||
|
// current pixel exceeds imageThreshold as well
|
||||||
|
c--;
|
||||||
|
colsOut[c].lastImageValue = image[tmpI] + image[tmpI+1] + image[tmpI+2];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// če smo dobili piksel, ki presega blackbar, preverimo do gradientSampleSize dodatnih pikslov.
|
||||||
|
// ko dobimo piksel čez imageTreshold oz. gradientSampleSize, izračunamo ali gre za gradient.
|
||||||
|
if (colsIn[c].blackFound++ > this.settings.active.arDetect.blackbar.gradientSampleSize) {
|
||||||
|
colsIn[c].imageFound = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// zatem preverimo, če je piksel presegel mejo, po kateri sklepamo, da
|
||||||
|
// predstavlja sliko. Preverimo samo, če smo v stolpcu že presegli
|
||||||
|
// blackThreshold
|
||||||
|
//
|
||||||
|
// then we check whether pixel exceeded imageThreshold
|
||||||
|
if (image[tmpI] > this.imageThreshold ||
|
||||||
|
image[tmpI + 1] > this.imageThreshold ||
|
||||||
|
image[tmpI + 2] > this.imageThreshold ){
|
||||||
|
|
||||||
|
colsOut[c].image = (i / this.conf.canvasImageDataRowLength)
|
||||||
|
|
||||||
|
|
||||||
|
colsIn[c].imageFound = true;
|
||||||
|
edgeDetectCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// shranimo razliko med prejšnjim in trenutnim pikslom za kasnejšo analizo
|
||||||
|
// save difference between current and previous pixel for later analysis
|
||||||
|
const imageValue = image[tmpI] + image[tmpI+1] + image[tmpI+2];
|
||||||
|
colsOut[c].diffs.push(imageValue - colsOut[c].lastImage);
|
||||||
|
colsOut[c].lastImageValue = imageValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(edgeDetectCount >= this.colsThreshold) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user