convert ArDetector to ts

This commit is contained in:
Tamius Han 2021-02-18 22:29:23 +01:00
parent 7e49b493bb
commit a3bd8a8b7e
4 changed files with 249 additions and 188 deletions

View File

@ -500,7 +500,7 @@ class Settings {
return this.canStartExtension(site); return this.canStartExtension(site);
} }
canStartAutoAr(site) { canStartAutoAr(site?: string) {
// 'site' argument is only ever used when calling this function recursively for debugging // 'site' argument is only ever used when calling this function recursively for debugging
if (!site) { if (!site) {
site = window.location.hostname; site = window.location.hostname;

View File

@ -8,10 +8,54 @@ import GuardLine from './GuardLine';
// import DebugCanvas from './DebugCanvas'; // import DebugCanvas from './DebugCanvas';
import VideoAlignmentType from '../../../common/enums/VideoAlignmentType.enum'; import VideoAlignmentType from '../../../common/enums/VideoAlignmentType.enum';
import AspectRatioType from '../../../common/enums/AspectRatioType.enum'; import AspectRatioType from '../../../common/enums/AspectRatioType.enum';
import {sleep} from '../../lib/Util'; import {sleep} from '../Util';
import BrowserDetect from '../../conf/BrowserDetect'; import BrowserDetect from '../../conf/BrowserDetect';
import Logger from '../Logger';
import VideoData from '../video-data/VideoData';
import Settings from '../Settings';
class ArDetector { class ArDetector {
logger: Logger;
conf: VideoData;
video: HTMLVideoElement;
settings: Settings;
guardLine: GuardLine;
edgeDetector: EdgeDetect;
setupTimer: any;
sampleCols: any[];
sampleLines
canFallback: boolean = true;
fallbackMode: boolean = false;
blackLevel: number;
arid: string;
// ar detector starts in this state. running main() sets both to false
_paused: boolean;
_halted: boolean = true;
_exited: boolean = true;
private manualTickEnabled: boolean;
_nextTick: boolean;
canDoFallbackMode: boolean = false;
// helper objects
private attachedCanvas: HTMLCanvasElement;
canvas: HTMLCanvasElement;
private blackframeCanvas: HTMLCanvasElement;
private context: CanvasRenderingContext2D;
private blackframeContext: CanvasRenderingContext2D;
private canvasScaleFactor: number;
private detectionTimeoutEventCount: number;
canvasImageDataRowLength: number;
private noLetterboxCanvasReset: boolean;
private detectedAr: any;
private canvasDrawWindowHOffset: number;
private sampleCols_current: number;
constructor(videoData){ constructor(videoData){
this.logger = videoData.logger; this.logger = videoData.logger;
@ -19,34 +63,18 @@ class ArDetector {
this.video = videoData.video; this.video = videoData.video;
this.settings = videoData.settings; this.settings = videoData.settings;
this.setupTimer = null;
this.sampleCols = []; this.sampleCols = [];
this.canFallback = true;
this.fallbackMode = false;
this.blackLevel = this.settings.active.arDetect.blackbar.blackLevel; this.blackLevel = this.settings.active.arDetect.blackbar.blackLevel;
this.arid = (Math.random()*100).toFixed(); this.arid = (Math.random()*100).toFixed();
// ar detector starts in this state. running main() sets both to false
this._halted = true;
this._exited = true;
// we can tick manually, for debugging // we can tick manually, for debugging
this._manualTicks = false;
this._nextTick = false;
this.canDoFallbackMode = false;
this.drmNotificationShown = false;
this.logger.log('info', 'init', `[ArDetector::ctor] creating new ArDetector. arid: ${this.arid}`); this.logger.log('info', 'init', `[ArDetector::ctor] creating new ArDetector. arid: ${this.arid}`);
} }
setManualTick(manualTick) { setManualTick(manualTick) {
this._manualTicks = manualTick; this.manualTickEnabled = manualTick;
} }
tick() { tick() {
@ -68,19 +96,19 @@ class ArDetector {
} }
destroy(){ destroy(){
this.logger.log('info', 'init', `%c[ArDetect::destroy] <@${this.arid}> Destroying aard.`, _ard_console_stop, e); this.logger.log('info', 'init', `%c[ArDetect::destroy] <@${this.arid}> Destroying aard.`, _ard_console_stop);
// this.debugCanvas.destroy(); // this.debugCanvas.destroy();
this.stop(); this.stop();
} }
setup(cwidth, cheight){ setup(cwidth?: number, cheight?: number){
this.logger.log('info', 'init', `[ArDetect::setup] <@${this.arid}> Starting autodetection setup.`); this.logger.log('info', 'init', `[ArDetect::setup] <@${this.arid}> Starting autodetection setup.`);
// //
// [-1] check for zero-width and zero-height videos. If we detect this, we kick the proverbial // [-1] check for zero-width and zero-height videos. If we detect this, we kick the proverbial
// can some distance down the road. This problem will prolly fix itself soon. We'll also // can some distance down the road. This problem will prolly fix itself soon. We'll also
// not do any other setup until this issue is fixed // not do any other setup until this issue is fixed
// //
if(this.video.videoWidth === 0 || this.video.videoHeight === 0 ){ if (this.video.videoWidth === 0 || this.video.videoHeight === 0 ){
this.logger.log('warn', 'debug', `[ArDetect::setup] <@${this.arid}> This video has zero width or zero height. Dimensions: ${this.video.videoWidth} × ${this.video.videoHeight}`); this.logger.log('warn', 'debug', `[ArDetect::setup] <@${this.arid}> This video has zero width or zero height. Dimensions: ${this.video.videoWidth} × ${this.video.videoHeight}`);
this.scheduleInitRestart(); this.scheduleInitRestart();
@ -173,7 +201,7 @@ class ArDetector {
// //
try { try {
this.blackframeContext.drawWindow(window,0, 0, this.blackframeCanvas.width, this.blackframeCanvas.height, "rgba(0,0,128,1)"); (this.blackframeContext as any).drawWindow(window,0, 0, this.blackframeCanvas.width, this.blackframeCanvas.height, "rgba(0,0,128,1)");
this.canDoFallbackMode = true; this.canDoFallbackMode = true;
} catch (e) { } catch (e) {
this.canDoFallbackMode = false; this.canDoFallbackMode = false;
@ -292,7 +320,7 @@ class ArDetector {
// state from 'paused' to 'playing', we don't need to wait for the rest of the longer // state from 'paused' to 'playing', we don't need to wait for the rest of the longer
// paused state timeout to finish. // paused state timeout to finish.
if ( (!this._manualTicks && this.canTriggerFrameCheck(lastFrameCheckStartTime)) || this._nextTick) { if ( (!this.manualTickEnabled && this.canTriggerFrameCheck(lastFrameCheckStartTime)) || this._nextTick) {
this._nextTick = false; this._nextTick = false;
lastFrameCheckStartTime = Date.now(); lastFrameCheckStartTime = Date.now();
@ -344,7 +372,7 @@ class ArDetector {
} }
scheduleInitRestart(timeout, force_reset){ scheduleInitRestart(timeout?: number, force_reset?: boolean){
if(! timeout){ if(! timeout){
timeout = 100; timeout = 100;
} }
@ -481,7 +509,7 @@ class ArDetector {
// //
// we can only deny aspect ratio changes if we use automatic mode and if aspect ratio was set from here. // we can only deny aspect ratio changes if we use automatic mode and if aspect ratio was set from here.
let arDiff = trueAr - lastAr.ar; let arDiff = trueAr - lastAr.ratio;
if (arDiff < 0) if (arDiff < 0)
arDiff = -arDiff; arDiff = -arDiff;
@ -490,7 +518,7 @@ class ArDetector {
// ali je sprememba v mejah dovoljenega? Če da -> fertik // ali je sprememba v mejah dovoljenega? Če da -> fertik
// is ar variance within acceptable levels? If yes -> we done // is ar variance within acceptable levels? If yes -> we done
this.logger.log('info', 'arDetect', `%c[ArDetect::processAr] <@${this.arid}> New aspect ratio varies from the old one by this much:\n`,"color: #aaf","old Ar", lastAr.ar, "current ar", trueAr, "arDiff (absolute):",arDiff,"ar diff (relative to new ar)", arDiff_percent); this.logger.log('info', 'arDetect', `%c[ArDetect::processAr] <@${this.arid}> New aspect ratio varies from the old one by this much:\n`,"color: #aaf","old Ar", lastAr.ratio, "current ar", trueAr, "arDiff (absolute):",arDiff,"ar diff (relative to new ar)", arDiff_percent);
if (arDiff < trueAr * this.settings.active.arDetect.allowedArVariance){ if (arDiff < trueAr * this.settings.active.arDetect.allowedArVariance){
this.logger.log('info', 'arDetect', `%c[ArDetect::processAr] <@${this.arid}> Aspect ratio change denied — diff %: ${arDiff_percent}`, "background: #740; color: #fa2"); this.logger.log('info', 'arDetect', `%c[ArDetect::processAr] <@${this.arid}> Aspect ratio change denied — diff %: ${arDiff_percent}`, "background: #740; color: #fa2");
@ -500,12 +528,12 @@ class ArDetector {
} }
this.logger.log('info', 'debug', `%c[ArDetect::processAr] <@${this.arid}> Triggering aspect ratio change. New aspect ratio: ${trueAr}`, _ard_console_change); this.logger.log('info', 'debug', `%c[ArDetect::processAr] <@${this.arid}> Triggering aspect ratio change. New aspect ratio: ${trueAr}`, _ard_console_change);
this.conf.resizer.updateAr({type: AspectRatioType.Automatic, ratio: trueAr}, {type: AspectRatioType.Automatic, ratio: trueAr}); this.conf.resizer.updateAr({type: AspectRatioType.Automatic, ratio: trueAr});
} }
clearImageData(id) { clearImageData(id) {
if (ArrayBuffer.transfer) { if ((ArrayBuffer as any).transfer) {
ArrayBuffer.transfer(id, 0); (ArrayBuffer as any).transfer(id, 0);
} }
id = undefined; id = undefined;
} }
@ -579,7 +607,7 @@ class ArDetector {
this.fallbackMode = true; this.fallbackMode = true;
try { try {
this.context.drawWindow(window, this.canvasDrawWindowHOffset, 0, this.canvas.width, this.canvas.height, "rgba(0,0,128,1)"); (this.context as any).drawWindow(window, this.canvasDrawWindowHOffset, 0, this.canvas.width, this.canvas.height, "rgba(0,0,128,1)");
} catch (e) { } catch (e) {
this.logger.log('error', 'arDetect', `%c[ArDetect::frameCheck] can't draw image on canvas with fallback mode either. This error is prolly only temporary.`, "color:#000; backgroud:#f51;", e); this.logger.log('error', 'arDetect', `%c[ArDetect::frameCheck] can't draw image on canvas with fallback mode either. This error is prolly only temporary.`, "color:#000; backgroud:#f51;", e);
return; // it's prolly just a fluke, so we do nothing special here return; // it's prolly just a fluke, so we do nothing special here
@ -680,8 +708,6 @@ class ArDetector {
this.guardLine.reset(); this.guardLine.reset();
} }
triggerTimeout = this.getTimeout(baseTimeout, startTime);
this.scheduleFrameCheck(triggerTimeout);
this.clearImageData(imageData); this.clearImageData(imageData);
return; return;
} }
@ -741,7 +767,7 @@ class ArDetector {
this.logger.log('error', 'arDetect', `%c[ArDetect::frameCheck] There was a problem setting blackbar. Doing nothing. Error:`, e); this.logger.log('error', 'arDetect', `%c[ArDetect::frameCheck] There was a problem setting blackbar. Doing nothing. Error:`, e);
try { try {
this.guardline.reset(); this.guardLine.reset();
} catch (e) { } catch (e) {
// no guardline, no bigge // no guardline, no bigge
} }
@ -780,7 +806,7 @@ class ArDetector {
let cumulativeValue = 0; let cumulativeValue = 0;
let blackPixelCount = 0; let blackPixelCount = 0;
const bfImageData = this.blackframeContext.getImageData(0, 0, cols, rows).data; const bfImageData = this.blackframeContext.getImageData(0, 0, cols, rows).data;
const blackTreshold = this.blackLevel + this.settings.active.arDetect.blackbar.frameTreshold; const blackTreshold = this.blackLevel + this.settings.active.arDetect.blackbar.frameThreshold;
// we do some recon for letterbox and pillarbox. While this can't determine whether letterbox/pillarbox exists // we do some recon for letterbox and pillarbox. While this can't determine whether letterbox/pillarbox exists
@ -788,7 +814,7 @@ class ArDetector {
let rowMax = new Array(rows).fill(0); let rowMax = new Array(rows).fill(0);
let colMax = new Array(cols).fill(0); let colMax = new Array(cols).fill(0);
let r, c; let r: number, c: number;
for (let i = 0; i < bfImageData.length; i+= 4) { for (let i = 0; i < bfImageData.length; i+= 4) {

View File

@ -1,13 +1,33 @@
import Debug from '../../conf/Debug'; import Debug from '../../conf/Debug';
import Settings from '../Settings';
import ArDetector from './ArDetector';
export type GuardLineBar = {
top?: number;
bottom?: number;
}
export type ImageCheckResult = {
success: boolean;
}
class GuardLine { class GuardLine {
blackbar: GuardLineBar;
imageBar: GuardLineBar;
aard: ArDetector;
settings: Settings;
blackbarThreshold: number;
imageThreshold: number;
// ardConf — reference to ArDetector that has current GuardLine instance // ardConf — reference to ArDetector that has current GuardLine instance
constructor(ardConf){ constructor (ardConf){
this.blackbar = {top: undefined, bottom: undefined}; this.blackbar = {top: undefined, bottom: undefined};
this.imageBar = {top: undefined, bottom: undefined}; this.imageBar = {top: undefined, bottom: undefined};
this.conf = ardConf; this.aard = ardConf;
this.settings = ardConf.settings; this.settings = ardConf.settings;
} }
@ -33,7 +53,7 @@ class GuardLine {
// to odstrani vse neveljavne nastavitve in vse možnosti, ki niso smiselne // 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 // this removes any configs with invalid values or values that dont make sense
if (bbTop < 0 || bbBottom >= this.conf.canvas.height ){ if (bbTop < 0 || bbBottom >= this.aard.canvas.height ){
throw {error: "INVALID_SETTINGS_IN_GUARDLINE", bbTop, bbBottom} throw {error: "INVALID_SETTINGS_IN_GUARDLINE", bbTop, bbBottom}
} }
@ -51,7 +71,7 @@ class GuardLine {
check(image, fallbackMode){ check(image, fallbackMode){
// izračunaj enkrat in shrani na objekt // izračunaj enkrat in shrani na objekt
// calculate once and save object-instance-wide // calculate once and save object-instance-wide
this.blackbarThreshold = this.conf.blackLevel + this.settings.active.arDetect.blackbar.threshold; this.blackbarThreshold = this.aard.blackLevel + this.settings.active.arDetect.blackbar.threshold;
this.imageThreshold = this.blackbarThreshold + this.settings.active.arDetect.blackbar.imageThreshold; this.imageThreshold = this.blackbarThreshold + this.settings.active.arDetect.blackbar.imageThreshold;
// dejansko testiranje // dejansko testiranje
@ -95,7 +115,7 @@ class GuardLine {
return { success: true }; return { success: true };
} }
var offset = parseInt(this.conf.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2; var offset = (this.aard.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
var offenders = []; var offenders = [];
var offenderCount = -1; // doing it this way means first offender has offenderCount==0. Ez index. var offenderCount = -1; // doing it this way means first offender has offenderCount==0. Ez index.
@ -112,28 +132,28 @@ class GuardLine {
else{ else{
// fallback mode is a bit different // fallback mode is a bit different
edge_upper = 0; edge_upper = 0;
edge_lower = this.conf.canvas.height - 1; edge_lower = this.aard.canvas.height - 1;
} }
var rowStart, rowEnd; var rowStart, rowEnd;
// <<<=======| checking upper row |========>>> // <<<=======| checking upper row |========>>>
rowStart = ((edge_upper * this.conf.canvas.width) << 2) + offset; rowStart = ((edge_upper * this.aard.canvas.width) << 2) + offset;
rowEnd = rowStart + ( this.conf.canvas.width << 2 ) - (offset * 2); rowEnd = rowStart + ( this.aard.canvas.width << 2 ) - (offset * 2);
if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) { if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) {
offenderCount = this._gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount); // offenderCount = this._gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount);
} else { } else {
offenderCount = this._gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount); offenderCount = this._gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount);
} }
// <<<=======| checking lower row |========>>> // <<<=======| checking lower row |========>>>
rowStart = ((edge_lower * this.conf.canvas.width) << 2) + offset; rowStart = ((edge_lower * this.aard.canvas.width) << 2) + offset;
rowEnd = rowStart + ( this.conf.canvas.width << 2 ) - (offset * 2); rowEnd = rowStart + ( this.aard.canvas.width << 2 ) - (offset * 2);
if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) { if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) {
offenderCount = this._gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount); // offenderCount = this._gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount);
} else { } else {
offenderCount = this._gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount); offenderCount = this._gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount);
} }
@ -156,11 +176,11 @@ class GuardLine {
return {success: false, offenders: ret}; return {success: false, offenders: ret};
} }
imageCheck(image){ imageCheck(image, fallbackMode?: boolean): ImageCheckResult {
if(!this.imageBar.top || !this.imageBar.bottom) if(!this.imageBar.top || !this.imageBar.bottom)
return { success: false }; return { success: false };
var offset = (this.conf.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2; var offset = (this.aard.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
// TODO: implement logo check. // TODO: implement logo check.
@ -181,35 +201,35 @@ class GuardLine {
// robu (eden izmed robov je lahko v celoti črn) // 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 // 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) // on one edge (one of the edges can be black as long as both aren't)
var successThreshold = (this.conf.canvas.width * this.settings.active.arDetect.guardLine.imageTestThreshold); var successThreshold = (this.aard.canvas.width * this.settings.active.arDetect.guardLine.imageTestThreshold);
var rowStart, rowEnd; var rowStart, rowEnd;
// <<<=======| checking upper row |========>>> // <<<=======| checking upper row |========>>>
rowStart = ((edge_upper * this.conf.canvas.width) << 2) + offset; rowStart = ((edge_upper * this.aard.canvas.width) << 2) + offset;
rowEnd = rowStart + ( this.conf.canvas.width << 2 ) - (offset * 2); rowEnd = rowStart + ( this.aard.canvas.width << 2 ) - (offset * 2);
var res = false; var res = false;
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){ if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
res = this._ti_debugCheckRow(image, rowStart, rowEnd, successThreshold); // res = this._ti_debugCheckRow(image, rowStart, rowEnd, successThreshold);
} else { } else {
res = this._ti_checkRow(image, rowStart, rowEnd,successThreshold); res = this._ti_checkRow(image, rowStart, rowEnd,successThreshold);
} }
if(res) if (res) {
return {success: true}; return {success: true};
}
// <<<=======| checking lower row |========>>> // <<<=======| checking lower row |========>>>
rowStart = ((edge_lower * this.conf.canvas.width) << 2) + offset; rowStart = ((edge_lower * this.aard.canvas.width) << 2) + offset;
// rowEnd = rowStart + ( this.conf.canvas.width << 2 ) - (offset * 2); // rowEnd = rowStart + ( this.conf.canvas.width << 2 ) - (offset * 2);
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){ if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
res = this._ti_debugCheckRow(image, rowStart, rowEnd, successThreshold); // res = this._ti_debugCheckRow(image, rowStart, rowEnd, successThreshold);
} else { } else {
res = this._ti_checkRow(image, rowStart, rowEnd,successThreshold); res = this._ti_checkRow(image, rowStart, rowEnd,successThreshold);
} }
@ -246,35 +266,35 @@ class GuardLine {
return offenderCount; return offenderCount;
} }
_gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount){ // _gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount){
var firstOffender = -1; // var firstOffender = -1;
for(var i = rowStart; i < rowEnd; i+=4){ // for(var i = rowStart; i < rowEnd; i+=4){
// we track sections that go over what's supposed to be a black line, so we can suggest more // // we track sections that go over what's supposed to be a black line, so we can suggest more
// columns to sample // // columns to sample
if(image[i] > this.blackbarThreshold || image[i+1] > this.blackbarThreshold || image[i+2] > this.blackbarThreshold){ // if(image[i] > this.blackbarThreshold || image[i+1] > this.blackbarThreshold || image[i+2] > this.blackbarThreshold){
this.conf.debugCanvas.trace(i, DebugCanvasClasses.VIOLATION); // this.aard.debugCanvas.trace(i, DebugCanvasClasses.VIOLATION);
if(firstOffender < 0){ // if(firstOffender < 0){
firstOffender = (i - rowStart) >> 2; // firstOffender = (i - rowStart) >> 2;
offenderCount++; // offenderCount++;
offenders.push({x: firstOffender, width: 1}); // offenders.push({x: firstOffender, width: 1});
} // }
else{ // else{
offenders[offenderCount].width++ // offenders[offenderCount].width++
} // }
} // }
else{ // else{
this.conf.debugCanvas.trace(i, DebugCanvasClasses.GUARDLINE_BLACKBAR); // this.aard.debugCanvas.trace(i, DebugCanvasClasses.GUARDLINE_BLACKBAR);
// is that a black pixel again? Let's reset the 'first offender' // // is that a black pixel again? Let's reset the 'first offender'
firstOffender = -1; // firstOffender = -1;
} // }
} // }
return offenderCount; // return offenderCount;
} // }
_ti_checkRow(image, rowStart, rowEnd, successThreshold) { _ti_checkRow(image, rowStart, rowEnd, successThreshold): boolean {
for(var i = rowStart; i < rowEnd; i+=4){ for(var i = rowStart; i < rowEnd; i+=4){
if(image[i] > this.imageThreshold || image[i+1] > this.imageThreshold || image[i+2] > this.imageThreshold){ if(image[i] > this.imageThreshold || image[i+1] > this.imageThreshold || image[i+2] > this.imageThreshold){
if(successThreshold --<= 0){ if(successThreshold --<= 0){
@ -286,20 +306,20 @@ class GuardLine {
return false; return false;
} }
_ti_debugCheckRow(image, rowStart, rowEnd, successThreshold) { // _ti_debugCheckRow(image, rowStart, rowEnd, successThreshold) {
for(var i = rowStart; i < rowEnd; i+=4){ // for(var i = rowStart; i < rowEnd; i+=4){
if(image[i] > this.imageThreshold || image[i+1] > this.imageThreshold || image[i+2] > this.imageThreshold){ // if(image[i] > this.imageThreshold || image[i+1] > this.imageThreshold || image[i+2] > this.imageThreshold){
this.conf.debugCanvas.trace(i, DebugCanvasClasses.GUARDLINE_IMAGE); // this.aard.debugCanvas.trace(i, DebugCanvasClasses.GUARDLINE_IMAGE);
if(successThreshold --<= 0){ // if(successThreshold --<= 0){
return true; // return true;
} // }
} else { // } else {
this.conf.debugCanvas.trace(i, DebugCanvasClasses.WARN); // this.aard.debugCanvas.trace(i, DebugCanvasClasses.WARN);
} // }
} // }
return false; // return false;
} // }
} }
export default GuardLine; export default GuardLine;

View File

@ -3,12 +3,27 @@ import EdgeStatus from './enums/EdgeStatusEnum';
import EdgeDetectQuality from './enums/EdgeDetectQualityEnum'; import EdgeDetectQuality from './enums/EdgeDetectQualityEnum';
import EdgeDetectPrimaryDirection from './enums/EdgeDetectPrimaryDirectionEnum'; import EdgeDetectPrimaryDirection from './enums/EdgeDetectPrimaryDirectionEnum';
import AntiGradientMode from '../../../../common/enums/AntiGradientMode.enum'; import AntiGradientMode from '../../../../common/enums/AntiGradientMode.enum';
import ArDetector from '../ArDetector';
import Logger from '../../Logger';
import Settings from '../../Settings';
if (Debug.debug) { if (Debug.debug) {
console.log("Loading EdgeDetect.js"); console.log("Loading EdgeDetect.js");
} }
class EdgeDetect{ class EdgeDetect{
conf: ArDetector;
logger: Logger;
settings: Settings;
// helper stuff
private sampleWidthBase: number;
private halfSample: number;
private detectionThreshold: number;
private colsThreshold: number;
private blackbarThreshold: number;
private imageThreshold: number;
constructor(ardConf){ constructor(ardConf){
this.conf = ardConf; this.conf = ardConf;
@ -41,7 +56,7 @@ class EdgeDetect{
// edges = fastCandidates; // todo: processing // edges = fastCandidates; // todo: processing
// } else { // } else {
edgeCandidates = this.edgeDetect(image, fastCandidates); edgeCandidates = this.edgeDetect(image, fastCandidates);
bars = this.edgePostprocess(edgeCandidates, this.conf.canvas.height); bars = this.edgePostprocess(edgeCandidates);
// } // }
} catch (e) { } catch (e) {
this.logger.log('error', 'arDetect', '%c[EdgeDetect::findBars] find bars failed.', 'background: #f00, color: #000', e); this.logger.log('error', 'arDetect', '%c[EdgeDetect::findBars] find bars failed.', 'background: #f00, color: #000', e);
@ -259,7 +274,7 @@ class EdgeDetect{
loopEnd = sampleRow_black + sampleEnd; loopEnd = sampleRow_black + sampleEnd;
if (Debug.debugCanvas.enabled){ if (Debug.debugCanvas.enabled){
blackEdgeViolation = this._blackbarTest_dbg(image, sampleRow_black + sampleStart, loopEnd); // blackEdgeViolation = this._blackbarTest_dbg(image, sampleRow_black + sampleStart, loopEnd);
} else { } else {
blackEdgeViolation = this._blackbarTest(image, sampleRow_black + sampleStart, loopEnd); blackEdgeViolation = this._blackbarTest(image, sampleRow_black + sampleStart, loopEnd);
} }
@ -274,7 +289,7 @@ class EdgeDetect{
loopEnd = sampleRow_color + sampleEnd; loopEnd = sampleRow_color + sampleEnd;
if (Debug.debugCanvas.enabled) { if (Debug.debugCanvas.enabled) {
this._imageTest_dbg(image, sampleRow_color + sampleStart, loopEnd, sample.black, edgeCandidatesTop) // this._imageTest_dbg(image, sampleRow_color + sampleStart, loopEnd, sample.black, edgeCandidatesTop)
} else { } else {
this._imageTest(image, sampleRow_color + sampleStart, loopEnd, sample.black, edgeCandidatesTop); this._imageTest(image, sampleRow_color + sampleStart, loopEnd, sample.black, edgeCandidatesTop);
} }
@ -302,7 +317,7 @@ class EdgeDetect{
loopEnd = sampleRow_black + sampleEnd; loopEnd = sampleRow_black + sampleEnd;
if(Debug.debugCanvas.enabled){ if(Debug.debugCanvas.enabled){
blackEdgeViolation = this._blackbarTest_dbg(image, sampleRow_black + sampleStart, loopEnd); // blackEdgeViolation = this._blackbarTest_dbg(image, sampleRow_black + sampleStart, loopEnd);
} else { } else {
blackEdgeViolation = this._blackbarTest(image, sampleRow_black + sampleStart, loopEnd); blackEdgeViolation = this._blackbarTest(image, sampleRow_black + sampleStart, loopEnd);
} }
@ -317,7 +332,7 @@ class EdgeDetect{
loopEnd = sampleRow_color + sampleEnd; loopEnd = sampleRow_color + sampleEnd;
if(Debug.debugCanvas.enabled) { if(Debug.debugCanvas.enabled) {
this._imageTest_dbg(image, sampleRow_color + sampleStart, loopEnd, sample.black, edgeCandidatesBottom); // this._imageTest_dbg(image, sampleRow_color + sampleStart, loopEnd, sample.black, edgeCandidatesBottom);
} else { } else {
this._imageTest(image, sampleRow_color + sampleStart, loopEnd, sample.black, edgeCandidatesBottom); this._imageTest(image, sampleRow_color + sampleStart, loopEnd, sample.black, edgeCandidatesBottom);
} }
@ -1095,62 +1110,62 @@ class EdgeDetect{
} }
} }
_columnTest_dbgc(image, top, bottom, colsIn, colsOut, reverseSearchDirection){ // _columnTest_dbgc(image, top, bottom, colsIn, colsOut, reverseSearchDirection){
var tmpI; // var tmpI;
if(reverseSearchDirection){ // if(reverseSearchDirection){
for(var i = bottom - this.conf.canvasImageDataRowLength; i >= top; i-= this.conf.canvasImageDataRowLength){ // for(var i = bottom - this.conf.canvasImageDataRowLength; i >= top; i-= this.conf.canvasImageDataRowLength){
for(var col of colsIn){ // for(var col of colsIn){
tmpI = i + (col << 2); // tmpI = i + (col << 2);
if( image[tmpI] > this.blackbarThreshold || // if( image[tmpI] > this.blackbarThreshold ||
image[tmpI + 1] > this.blackbarThreshold || // image[tmpI + 1] > this.blackbarThreshold ||
image[tmpI + 2] > this.blackbarThreshold ){ // image[tmpI + 2] > this.blackbarThreshold ){
var bottom = (i / this.conf.canvasImageDataRowLength) + 1; // var bottom = (i / this.conf.canvasImageDataRowLength) + 1;
colsOut.push({ // colsOut.push({
col: col, // col: col,
bottom: bottom // bottom: bottom
}); // });
colsIn.splice(colsIn.indexOf(col), 1); // colsIn.splice(colsIn.indexOf(col), 1);
this.conf.debugCanvas.trace(tmpI,DebugCanvasClasses.EDGEDETECT_CANDIDATE); // this.conf.debugCanvas.trace(tmpI,DebugCanvasClasses.EDGEDETECT_CANDIDATE);
} // }
else{ // else{
this.conf.debugCanvas.trace(tmpI, DebugCanvasClasses.EDGEDETECT_ONBLACK); // this.conf.debugCanvas.trace(tmpI, DebugCanvasClasses.EDGEDETECT_ONBLACK);
} // }
} // }
if(colsIn.length < this.colsThreshold) // if(colsIn.length < this.colsThreshold)
break; // break;
} // }
} else { // } else {
for(var i = top; i < bottom; i+= this.conf.canvasImageDataRowLength){ // for(var i = top; i < bottom; i+= this.conf.canvasImageDataRowLength){
for(var col of colsIn){ // for(var col of colsIn){
tmpI = i + (col << 2); // tmpI = i + (col << 2);
if( image[tmpI] > this.blackbarThreshold || // if( image[tmpI] > this.blackbarThreshold ||
image[tmpI + 1] > this.blackbarThreshold || // image[tmpI + 1] > this.blackbarThreshold ||
image[tmpI + 2] > this.blackbarThreshold ){ // image[tmpI + 2] > this.blackbarThreshold ){
colsOut.push({ // colsOut.push({
col: col, // col: col,
top: (i / this.conf.canvasImageDataRowLength) - 1 // top: (i / this.conf.canvasImageDataRowLength) - 1
}); // });
colsIn.splice(colsIn.indexOf(col), 1); // colsIn.splice(colsIn.indexOf(col), 1);
this.conf.debugCanvas.trace(tmpI, DebugCanvasClasses.EDGEDETECT_CANDIDATE); // this.conf.debugCanvas.trace(tmpI, DebugCanvasClasses.EDGEDETECT_CANDIDATE);
if(tmpI-1 > 0){ // if(tmpI-1 > 0){
this.conf.debugCanvas.trace(tmpI - 1, DebugCanvasClasses.EDGEDETECT_CANDIDATE_SECONDARY); // this.conf.debugCanvas.trace(tmpI - 1, DebugCanvasClasses.EDGEDETECT_CANDIDATE_SECONDARY);
} // }
if(tmpI+1 < image.length){ // if(tmpI+1 < image.length){
this.conf.debugCanvas.trace(tmpI + 1, DebugCanvasClasses.EDGEDETECT_CANDIDATE_SECONDARY); // this.conf.debugCanvas.trace(tmpI + 1, DebugCanvasClasses.EDGEDETECT_CANDIDATE_SECONDARY);
} // }
} else { // } else {
this.conf.debugCanvas.trace(tmpI, DebugCanvasClasses.EDGEDETECT_ONBLACK); // this.conf.debugCanvas.trace(tmpI, DebugCanvasClasses.EDGEDETECT_ONBLACK);
} // }
} // }
if(colsIn.length < this.colsThreshold) // if(colsIn.length < this.colsThreshold)
break; // break;
} // }
} // }
} // }
_blackbarTest(image, start, end){ _blackbarTest(image, start, end){
for(var i = start; i < end; i += 4){ for(var i = start; i < end; i += 4){
@ -1163,20 +1178,20 @@ class EdgeDetect{
return false; // no violation return false; // no violation
} }
_blackbarTest_dbg(image, start, end){ // _blackbarTest_dbg(image, start, end){
for(var i = start; i < end; i += 4){ // for(var i = start; i < end; i += 4){
if( image[i ] > this.blackbarThreshold || // if( image[i ] > this.blackbarThreshold ||
image[i+1] > this.blackbarThreshold || // image[i+1] > this.blackbarThreshold ||
image[i+2] > this.blackbarThreshold ){ // image[i+2] > this.blackbarThreshold ){
this.conf.debugCanvas.trace(i, DebugCanvasClasses.VIOLATION) // this.conf.debugCanvas.trace(i, DebugCanvasClasses.VIOLATION)
return true; // return true;
} else { // } else {
this.conf.debugCanvas.trace(i, DebugCanvasClasses.EDGEDETECT_BLACKBAR) // this.conf.debugCanvas.trace(i, DebugCanvasClasses.EDGEDETECT_BLACKBAR)
} // }
} // }
return false; // no violation // return false; // no violation
} // }
_imageTest(image, start, end, sampleOffset, edgeCandidates){ _imageTest(image, start, end, sampleOffset, edgeCandidates){
var detections = 0; var detections = 0;
@ -1198,28 +1213,28 @@ class EdgeDetect{
} }
} }
_imageTest_dbg(image, start, end, sampleOffset, edgeCandidates){ // _imageTest_dbg(image, start, end, sampleOffset, edgeCandidates){
var detections = 0; // var detections = 0;
for(var i = start; i < end; i += 4){ // for(var i = start; i < end; i += 4){
if( image[i ] > this.blackbarThreshold || // if( image[i ] > this.blackbarThreshold ||
image[i+1] > this.blackbarThreshold || // image[i+1] > this.blackbarThreshold ||
image[i+2] > this.blackbarThreshold ){ // image[i+2] > this.blackbarThreshold ){
++detections; // ++detections;
this.conf.debugCanvas.trace(i, DebugCanvasClasses.EDGEDETECT_IMAGE); // this.conf.debugCanvas.trace(i, DebugCanvasClasses.EDGEDETECT_IMAGE);
} else { // } else {
this.conf.debugCanvas.trace(i, DebugCanvasClasses.WARN); // this.conf.debugCanvas.trace(i, DebugCanvasClasses.WARN);
} // }
} // }
if(detections >= this.detectionThreshold){ // if(detections >= this.detectionThreshold){
if(edgeCandidates[sampleOffset] != undefined) // if(edgeCandidates[sampleOffset] != undefined)
edgeCandidates[sampleOffset].count++; // edgeCandidates[sampleOffset].count++;
else{ // else{
edgeCandidates[sampleOffset] = {offset: sampleOffset, count: 1}; // edgeCandidates[sampleOffset] = {offset: sampleOffset, count: 1};
edgeCandidates.count++; // edgeCandidates.count++;
} // }
} // }
} // }
} }