2018-12-31 01:03:07 +01:00
|
|
|
import Debug from '../../conf/Debug';
|
2021-02-18 22:29:23 +01:00
|
|
|
import Settings from '../Settings';
|
|
|
|
import ArDetector from './ArDetector';
|
|
|
|
|
|
|
|
export type GuardLineBar = {
|
|
|
|
top?: number;
|
|
|
|
bottom?: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
export type ImageCheckResult = {
|
|
|
|
success: boolean;
|
|
|
|
}
|
2018-12-31 01:03:07 +01:00
|
|
|
|
2018-05-10 21:39:24 +02:00
|
|
|
class GuardLine {
|
2021-02-18 22:29:23 +01:00
|
|
|
blackbar: GuardLineBar;
|
|
|
|
imageBar: GuardLineBar;
|
|
|
|
|
|
|
|
aard: ArDetector;
|
|
|
|
settings: Settings;
|
|
|
|
|
|
|
|
blackbarThreshold: number;
|
|
|
|
imageThreshold: number;
|
|
|
|
|
|
|
|
|
2018-05-10 21:39:24 +02:00
|
|
|
// ardConf — reference to ArDetector that has current GuardLine instance
|
2021-02-18 22:29:23 +01:00
|
|
|
constructor (ardConf){
|
2018-05-10 21:39:24 +02:00
|
|
|
this.blackbar = {top: undefined, bottom: undefined};
|
|
|
|
this.imageBar = {top: undefined, bottom: undefined};
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
this.aard = ardConf;
|
2018-08-05 23:48:56 +02:00
|
|
|
this.settings = ardConf.settings;
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
reset() {
|
|
|
|
this.blackbar = {top: undefined, bottom: undefined};
|
|
|
|
this.imageBar = {top: undefined, bottom: undefined};
|
|
|
|
}
|
|
|
|
|
2018-07-11 00:01:44 +02:00
|
|
|
setBlackbarManual(blackbarConf, imagebarConf){
|
|
|
|
// ni lepo uporabljat tega, ampak pri fallback mode nastavljamo blackbar stuff na roke
|
|
|
|
// it's not nice to use this, but we're setting these values manually in fallbackMode
|
|
|
|
if (blackbarConf) {
|
|
|
|
this.blackbar = blackbarConf;
|
|
|
|
}
|
|
|
|
if (imagebarConf) {
|
|
|
|
this.imageBar = imagebarConf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-10 21:39:24 +02:00
|
|
|
setBlackbar(bbconf){
|
2021-02-18 22:38:32 +01:00
|
|
|
let bbTop = bbconf.top - this.settings.active.arDetect.guardLine.edgeTolerancePx;
|
|
|
|
let bbBottom = bbconf.bottom + this.settings.active.arDetect.guardLine.edgeTolerancePx;
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
// to odstrani vse neveljavne nastavitve in vse možnosti, ki niso smiselne
|
|
|
|
// this removes any configs with invalid values or values that dont make sense
|
2021-02-18 22:29:23 +01:00
|
|
|
if (bbTop < 0 || bbBottom >= this.aard.canvas.height ){
|
2019-10-29 18:15:46 +01:00
|
|
|
throw {error: "INVALID_SETTINGS_IN_GUARDLINE", bbTop, bbBottom}
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.blackbar = {
|
|
|
|
top: bbTop,
|
|
|
|
bottom: bbBottom
|
|
|
|
}
|
|
|
|
|
|
|
|
this.imageBar = {
|
2018-08-05 23:48:56 +02:00
|
|
|
top: bbconf.top + 1 + this.settings.active.arDetect.guardLine.edgeTolerancePx,
|
|
|
|
bottom: bbconf.bottom - 1 - this.settings.active.arDetect.guardLine.edgeTolerancePx
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
check(image, fallbackMode){
|
|
|
|
// izračunaj enkrat in shrani na objekt
|
|
|
|
// calculate once and save object-instance-wide
|
2021-02-18 22:29:23 +01:00
|
|
|
this.blackbarThreshold = this.aard.blackLevel + this.settings.active.arDetect.blackbar.threshold;
|
2019-02-22 23:02:48 +01:00
|
|
|
this.imageThreshold = this.blackbarThreshold + this.settings.active.arDetect.blackbar.imageThreshold;
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
// dejansko testiranje
|
|
|
|
// actual checks
|
2021-02-18 22:38:32 +01:00
|
|
|
let guardLineResult = this.guardLineCheck(image, fallbackMode);
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
// Zaznali smo kršitev črnega dela, zato nam ni treba preveriti, ali je slika
|
|
|
|
// prisotna. Vemo namreč, da se je razmerje stranic zmanjšalo.
|
|
|
|
//
|
|
|
|
// blackbar violation detected. We don't even need to check for presence of image
|
|
|
|
// as aspect ratio just decreased
|
|
|
|
if(! guardLineResult.success) {
|
|
|
|
return {
|
|
|
|
blackbarFail: true,
|
|
|
|
offenders: guardLineResult.offenders,
|
|
|
|
imageFail: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:38:32 +01:00
|
|
|
let imageCheckResult = this.imageCheck(image, fallbackMode);
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
return {
|
|
|
|
blackbarFail: false,
|
2018-05-15 20:36:22 +02:00
|
|
|
imageFail: ! imageCheckResult.success
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// don't use methods below this line outside this class
|
|
|
|
guardLineCheck(image, fallbackMode){
|
|
|
|
// this test tests for whether we crop too aggressively
|
|
|
|
|
|
|
|
// if this test is passed, then aspect ratio probably didn't change from wider to narrower. However, further
|
|
|
|
// checks are needed to determine whether aspect ratio got wider.
|
|
|
|
// if this test fails, it returns a list of offending points.
|
|
|
|
|
|
|
|
// if the upper edge is null, then edge hasn't been detected before. This test is pointless, therefore it
|
|
|
|
// should succeed by default. Also need to check bottom, for cases where only one edge is known
|
|
|
|
|
|
|
|
if(! fallbackMode && (! this.blackbar.top || ! this.blackbar.bottom)) {
|
2018-05-15 20:36:22 +02:00
|
|
|
return { success: true };
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
|
|
|
|
2021-02-18 22:38:32 +01:00
|
|
|
let offset = (this.aard.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
2018-05-10 21:39:24 +02:00
|
|
|
|
2021-02-18 22:38:32 +01:00
|
|
|
let offenders = [];
|
|
|
|
let offenderCount = -1; // doing it this way means first offender has offenderCount==0. Ez index.
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
// TODO: implement logo check.
|
|
|
|
|
|
|
|
// preglejmo obe vrstici
|
|
|
|
// check both rows
|
2021-02-18 22:38:32 +01:00
|
|
|
let edge_lower, edge_upper;
|
|
|
|
|
2018-05-10 21:39:24 +02:00
|
|
|
if(! fallbackMode){
|
2021-02-18 22:38:32 +01:00
|
|
|
edge_upper = this.blackbar.top;
|
|
|
|
edge_lower = this.blackbar.bottom;
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
2021-02-18 22:38:32 +01:00
|
|
|
else {
|
2018-05-10 21:39:24 +02:00
|
|
|
// fallback mode is a bit different
|
|
|
|
edge_upper = 0;
|
2021-02-18 22:29:23 +01:00
|
|
|
edge_lower = this.aard.canvas.height - 1;
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
|
|
|
|
2021-02-18 22:38:32 +01:00
|
|
|
let rowStart, rowEnd;
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
// <<<=======| checking upper row |========>>>
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
rowStart = ((edge_upper * this.aard.canvas.width) << 2) + offset;
|
|
|
|
rowEnd = rowStart + ( this.aard.canvas.width << 2 ) - (offset * 2);
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) {
|
2021-02-18 22:29:23 +01:00
|
|
|
// offenderCount = this._gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount);
|
2018-05-10 21:39:24 +02:00
|
|
|
} else {
|
|
|
|
offenderCount = this._gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount);
|
|
|
|
}
|
|
|
|
// <<<=======| checking lower row |========>>>
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
rowStart = ((edge_lower * this.aard.canvas.width) << 2) + offset;
|
|
|
|
rowEnd = rowStart + ( this.aard.canvas.width << 2 ) - (offset * 2);
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) {
|
2021-02-18 22:29:23 +01:00
|
|
|
// offenderCount = this._gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount);
|
2018-05-10 21:39:24 +02:00
|
|
|
} else {
|
|
|
|
offenderCount = this._gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
// če nismo našli nobenih prekrškarjev, vrnemo uspeh. Drugače vrnemo seznam prekrškarjev
|
|
|
|
// vrnemo tabelo, ki vsebuje sredinsko točko vsakega prekrškarja (x + width*0.5)
|
|
|
|
//
|
|
|
|
// if we haven't found any offenders, we return success. Else we return list of offenders
|
|
|
|
// we return array of middle points of offenders (x + (width * 0.5) for every offender)
|
|
|
|
|
|
|
|
if(offenderCount == -1){
|
|
|
|
return {success: true};
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:38:32 +01:00
|
|
|
let ret = new Array(offenders.length);
|
|
|
|
for(let o in offenders){
|
2018-05-10 21:39:24 +02:00
|
|
|
ret[o] = offenders[o].x + (offenders[o].width * 0.25);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {success: false, offenders: ret};
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
imageCheck(image, fallbackMode?: boolean): ImageCheckResult {
|
2018-05-16 20:59:39 +02:00
|
|
|
if(!this.imageBar.top || !this.imageBar.bottom)
|
2018-05-10 21:39:24 +02:00
|
|
|
return { success: false };
|
2018-08-20 22:45:43 +02:00
|
|
|
|
2021-02-18 22:38:32 +01:00
|
|
|
let offset = (this.aard.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
// TODO: implement logo check.
|
|
|
|
|
|
|
|
|
|
|
|
// preglejmo obe vrstici - tukaj po pravilih ne bi smeli iti prek mej platna. ne rabimo preverjati
|
|
|
|
// check both rows - by the rules and definitions, we shouldn't go out of bounds here. no need to check, then
|
|
|
|
|
|
|
|
// if(fallbackMode){
|
2021-02-18 22:38:32 +01:00
|
|
|
// let edge_upper = this.settings.active.arDetect.fallbackMode.noTriggerZonePx;
|
|
|
|
// let edge_lower = this.conf.canvas.height - this.settings.active.arDetect.fallbackMode.noTriggerZonePx - 1;
|
2018-05-10 21:39:24 +02:00
|
|
|
// }
|
|
|
|
// else{
|
2021-02-18 22:38:32 +01:00
|
|
|
let edge_upper = this.imageBar.top;
|
|
|
|
let edge_lower = this.imageBar.bottom;
|
2018-05-10 21:39:24 +02:00
|
|
|
// }
|
|
|
|
|
|
|
|
// koliko pikslov rabimo zaznati, da je ta funkcija uspe. Tu dovoljujemo tudi, da so vsi piksli na enem
|
|
|
|
// robu (eden izmed robov je lahko v celoti črn)
|
|
|
|
// how many non-black pixels we need to consider this check a success. We only need to detect enough pixels
|
|
|
|
// on one edge (one of the edges can be black as long as both aren't)
|
2021-02-18 22:38:32 +01:00
|
|
|
let successThreshold = (this.aard.canvas.width * this.settings.active.arDetect.guardLine.imageTestThreshold);
|
|
|
|
let rowStart, rowEnd;
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
|
|
|
|
// <<<=======| checking upper row |========>>>
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
rowStart = ((edge_upper * this.aard.canvas.width) << 2) + offset;
|
|
|
|
rowEnd = rowStart + ( this.aard.canvas.width << 2 ) - (offset * 2);
|
2018-05-10 21:39:24 +02:00
|
|
|
|
2021-02-18 22:38:32 +01:00
|
|
|
let res = false;
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
|
2021-02-18 22:29:23 +01:00
|
|
|
// res = this._ti_debugCheckRow(image, rowStart, rowEnd, successThreshold);
|
2018-05-10 21:39:24 +02:00
|
|
|
} else {
|
2019-02-22 23:02:48 +01:00
|
|
|
res = this._ti_checkRow(image, rowStart, rowEnd,successThreshold);
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
if (res) {
|
2018-05-10 21:39:24 +02:00
|
|
|
return {success: true};
|
2021-02-18 22:29:23 +01:00
|
|
|
}
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
// <<<=======| checking lower row |========>>>
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
rowStart = ((edge_lower * this.aard.canvas.width) << 2) + offset;
|
2018-05-16 20:26:55 +02:00
|
|
|
// rowEnd = rowStart + ( this.conf.canvas.width << 2 ) - (offset * 2);
|
2018-05-10 21:39:24 +02:00
|
|
|
|
2018-05-15 20:36:22 +02:00
|
|
|
|
2018-05-10 21:39:24 +02:00
|
|
|
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
|
2021-02-18 22:29:23 +01:00
|
|
|
// res = this._ti_debugCheckRow(image, rowStart, rowEnd, successThreshold);
|
2018-05-10 21:39:24 +02:00
|
|
|
} else {
|
2019-02-22 23:02:48 +01:00
|
|
|
res = this._ti_checkRow(image, rowStart, rowEnd,successThreshold);
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return {success: res};
|
|
|
|
}
|
|
|
|
|
|
|
|
// pomožne metode
|
|
|
|
// helper methods
|
|
|
|
|
|
|
|
|
|
|
|
_gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount){
|
2021-02-18 22:38:32 +01:00
|
|
|
let firstOffender = -1;
|
|
|
|
for(let i = rowStart; i < rowEnd; i+=4){
|
2018-05-10 21:39:24 +02:00
|
|
|
|
|
|
|
// we track sections that go over what's supposed to be a black line, so we can suggest more
|
|
|
|
// columns to sample
|
2019-02-22 23:02:48 +01:00
|
|
|
if(image[i] > this.blackbarThreshold || image[i+1] > this.blackbarThreshold || image[i+2] > this.blackbarThreshold){
|
2018-05-10 21:39:24 +02:00
|
|
|
if(firstOffender < 0){
|
|
|
|
firstOffender = (i - rowStart) >> 2;
|
|
|
|
offenderCount++;
|
|
|
|
offenders.push({x: firstOffender, width: 1});
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
offenders[offenderCount].width++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
// is that a black pixel again? Let's reset the 'first offender'
|
|
|
|
firstOffender = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return offenderCount;
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
// _gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount){
|
2021-02-18 22:38:32 +01:00
|
|
|
// let firstOffender = -1;
|
|
|
|
// for(let i = rowStart; i < rowEnd; i+=4){
|
2018-05-10 21:39:24 +02:00
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
// // we track sections that go over what's supposed to be a black line, so we can suggest more
|
|
|
|
// // columns to sample
|
|
|
|
// if(image[i] > this.blackbarThreshold || image[i+1] > this.blackbarThreshold || image[i+2] > this.blackbarThreshold){
|
|
|
|
// this.aard.debugCanvas.trace(i, DebugCanvasClasses.VIOLATION);
|
|
|
|
// if(firstOffender < 0){
|
|
|
|
// firstOffender = (i - rowStart) >> 2;
|
|
|
|
// offenderCount++;
|
|
|
|
// offenders.push({x: firstOffender, width: 1});
|
|
|
|
// }
|
|
|
|
// else{
|
|
|
|
// offenders[offenderCount].width++
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// else{
|
|
|
|
// this.aard.debugCanvas.trace(i, DebugCanvasClasses.GUARDLINE_BLACKBAR);
|
|
|
|
// // is that a black pixel again? Let's reset the 'first offender'
|
|
|
|
// firstOffender = -1;
|
|
|
|
// }
|
2018-05-10 21:39:24 +02:00
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
// }
|
2018-05-10 21:39:24 +02:00
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
// return offenderCount;
|
|
|
|
// }
|
2018-05-10 21:39:24 +02:00
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
_ti_checkRow(image, rowStart, rowEnd, successThreshold): boolean {
|
2021-02-18 22:38:32 +01:00
|
|
|
for(let i = rowStart; i < rowEnd; i+=4){
|
2019-02-22 23:02:48 +01:00
|
|
|
if(image[i] > this.imageThreshold || image[i+1] > this.imageThreshold || image[i+2] > this.imageThreshold){
|
|
|
|
if(successThreshold --<= 0){
|
2018-05-10 21:39:24 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
// _ti_debugCheckRow(image, rowStart, rowEnd, successThreshold) {
|
2021-02-18 22:38:32 +01:00
|
|
|
// for(let i = rowStart; i < rowEnd; i+=4){
|
2021-02-18 22:29:23 +01:00
|
|
|
// if(image[i] > this.imageThreshold || image[i+1] > this.imageThreshold || image[i+2] > this.imageThreshold){
|
|
|
|
// this.aard.debugCanvas.trace(i, DebugCanvasClasses.GUARDLINE_IMAGE);
|
|
|
|
// if(successThreshold --<= 0){
|
|
|
|
// return true;
|
|
|
|
// }
|
|
|
|
// } else {
|
|
|
|
// this.aard.debugCanvas.trace(i, DebugCanvasClasses.WARN);
|
|
|
|
// }
|
|
|
|
// }
|
2018-05-10 21:39:24 +02:00
|
|
|
|
2021-02-18 22:29:23 +01:00
|
|
|
// return false;
|
|
|
|
// }
|
2018-05-10 21:39:24 +02:00
|
|
|
}
|
2018-12-31 01:03:07 +01:00
|
|
|
|
|
|
|
export default GuardLine;
|