import ResultPoint from '../../ResultPoint' ; import BitMatrix from '../BitMatrix' ; import MathUtils from './MathUtils' ; import NotFoundException from '../../NotFoundException' ; author David Olivier
  export default class WhiteRectangleDetector { private static INIT_SIZE = 10 ; private static CORR = 1 ; private height : number ; private width : number ; private leftInit : number ; private rightInit : number ; private downInit : number ; private upInit : number ; param image param initSize param x param y throws public constructor ( private image , initSize ? , x ? , y ? ) { this . height = image . getHeight ( ) ; this . width = image . getWidth ( ) ; if ( undefined === initSize || null === initSize ) { initSize = WhiteRectangleDetector . INIT_SIZE ; } if ( undefined === x || null === x ) { x = image . getWidth ( ) / 2 | 0 ; } if ( undefined === y || null === y ) { y = image . getHeight ( ) / 2 | 0 ; } const halfsize = initSize / 2 | 0 ; this . leftInit = x - halfsize ; this . rightInit = x + halfsize ; this . upInit = y - halfsize ; this . downInit = y + halfsize ; if ( this . upInit < 0 || this . leftInit < 0 || this . downInit >= this . height || this . rightInit >= this . width ) { throw new NotFoundException ( ) ; } } return { link throws public detect ( ) { let left = this . leftInit ; let right = this . rightInit ; let up = this . upInit ; let down = this . downInit ; let sizeExceeded = false ; let aBlackPointFoundOnBorder = true ; let atLeastOneBlackPointFoundOnBorder = false ; let atLeastOneBlackPointFoundOnRight = false ; let atLeastOneBlackPointFoundOnBottom = false ; let atLeastOneBlackPointFoundOnLeft = false ; let atLeastOneBlackPointFoundOnTop = false ; const width = this . width ; const height = this . height ; while ( aBlackPointFoundOnBorder ) { aBlackPointFoundOnBorder = false ; let rightBorderNotWhite = true ; while ( ( rightBorderNotWhite || ! atLeastOneBlackPointFoundOnRight ) && right < width ) { rightBorderNotWhite = this . containsBlackPoint ( up , down , right , false ) ; if ( rightBorderNotWhite ) { right ++ ; aBlackPointFoundOnBorder = true ; atLeastOneBlackPointFoundOnRight = true ; } else if ( ! atLeastOneBlackPointFoundOnRight ) { right ++ ; } } if ( right >= width ) { sizeExceeded = true ; break ; } let bottomBorderNotWhite = true ; while ( ( bottomBorderNotWhite || ! atLeastOneBlackPointFoundOnBottom ) && down < height ) { bottomBorderNotWhite = this . containsBlackPoint ( left , right , down , true ) ; if ( bottomBorderNotWhite ) { down ++ ; aBlackPointFoundOnBorder = true ; atLeastOneBlackPointFoundOnBottom = true ; } else if ( ! atLeastOneBlackPointFoundOnBottom ) { down ++ ; } } if ( down >= height ) { sizeExceeded = true ; break ; } let leftBorderNotWhite = true ; while ( ( leftBorderNotWhite || ! atLeastOneBlackPointFoundOnLeft ) && left >= 0 ) { leftBorderNotWhite = this . containsBlackPoint ( up , down , left , false ) ; if ( leftBorderNotWhite ) { left -- ; aBlackPointFoundOnBorder = true ; atLeastOneBlackPointFoundOnLeft = true ; } else if ( ! atLeastOneBlackPointFoundOnLeft ) { left -- ; } } if ( left < 0 ) { sizeExceeded = true ; break ; } let topBorderNotWhite = true ; while ( ( topBorderNotWhite || ! atLeastOneBlackPointFoundOnTop ) && up >= 0 ) { topBorderNotWhite = this . containsBlackPoint ( left , right , up , true ) ; if ( topBorderNotWhite ) { up -- ; aBlackPointFoundOnBorder = true ; atLeastOneBlackPointFoundOnTop = true ; } else if ( ! atLeastOneBlackPointFoundOnTop ) { up -- ; } } if ( up < 0 ) { sizeExceeded = true ; break ; } if ( aBlackPointFoundOnBorder ) { atLeastOneBlackPointFoundOnBorder = true ; } } if ( ! sizeExceeded && atLeastOneBlackPointFoundOnBorder ) { const maxSize = right - left ; let z = null ; for ( let i = 1 ; z === null && i < maxSize ; i ++ ) { z = this . getBlackPointOnSegment ( left , down - i , left + i , down ) ; } if ( z == null ) { throw new NotFoundException ( ) ; } let t = null ; for ( let i = 1 ; t === null && i < maxSize ; i ++ ) { t = this . getBlackPointOnSegment ( left , up + i , left + i , up ) ; } if ( t == null ) { throw new NotFoundException ( ) ; } let x = null ; for ( let i = 1 ; x === null && i < maxSize ; i ++ ) { x = this . getBlackPointOnSegment ( right , up + i , right - i , up ) ; } if ( x == null ) { throw new NotFoundException ( ) ; } let y = null ; for ( let i = 1 ; y === null && i < maxSize ; i ++ ) { y = this . getBlackPointOnSegment ( right , down - i , right - i , down ) ; } if ( y == null ) { throw new NotFoundException ( ) ; } return this . centerEdges ( y , z , x , t ) ; } else { throw new NotFoundException ( ) ; } } private getBlackPointOnSegment ( aX , aY , bX , bY ) { const dist = MathUtils . round ( MathUtils . distance ( aX , aY , bX , bY ) ) ; const xStep = ( bX - aX ) / dist ; const yStep = ( bY - aY ) / dist ; const image = this . image ; for ( let i = 0 ; i < dist ; i ++ ) { const x = MathUtils . round ( aX + i * xStep ) ; const y = MathUtils . round ( aY + i * yStep ) ; if ( image . get ( x , y ) ) { return new ResultPoint ( x , y ) ; } } return null ; } param y param z param x param t return { link private centerEdges ( y , z , x , t ) { const yi = y . getX ( ) ; const yj = y . getY ( ) ; const zi = z . getX ( ) ; const zj = z . getY ( ) ; const xi = x . getX ( ) ; const xj = x . getY ( ) ; const ti = t . getX ( ) ; const tj = t . getY ( ) ; const CORR = WhiteRectangleDetector . CORR ; if ( yi < this . width / 2.0 ) { return [ new ResultPoint ( ti - CORR , tj + CORR ) , new ResultPoint ( zi + CORR , zj + CORR ) , new ResultPoint ( xi - CORR , xj - CORR ) , new ResultPoint ( yi + CORR , yj - CORR ) ] ; } else { return [ new ResultPoint ( ti + CORR , tj + CORR ) , new ResultPoint ( zi + CORR , zj - CORR ) , new ResultPoint ( xi - CORR , xj + CORR ) , new ResultPoint ( yi - CORR , yj - CORR ) ] ; } } param a param b param fixed param horizontal return private containsBlackPoint ( a , b , fixed , horizontal ) { const image = this . image ; if ( horizontal ) { for ( let x = a ; x <= b ; x ++ ) { if ( image . get ( x , fixed ) ) { return true ; } } } else { for ( let y = a ; y <= b ; y ++ ) { if ( image . get ( fixed , y ) ) { return true ; } } } return false ; } }