Otsun menetelmä on harmaasävykuvan binarisointikynnys - algoritmi , jota käytetään tietokoneiden hahmontunnistuksessa ja kuvankäsittelyssä mustavalkokuvien tuottamiseksi.
Algoritmi mahdollistaa kahden luokan ("hyödyllinen" ja "tausta") pikselien erottamisen laskemalla sellainen kynnys, että luokan sisäinen varianssi on minimaalinen [1] . Otsu-menetelmällä on myös parannettu versio useiden kuvatasojen tukemiseksi [2] , jota kutsutaan multi-Otsu-menetelmäksi .
Useista venäjänkielisistä lähteistä löytyy erilaisia tapoja kirjoittaa kirjoittajan sukunimi Nobuyuki Otsu ( englanniksi ), esimerkiksi Otsu- menetelmä ja Otsu-menetelmä .
Otsu-menetelmä etsii kynnystä, joka pienentää luokan sisäistä varianssia , joka määritellään kahden luokan varianssien painotetuksi summaksi:
jossa painot ovat kahden kynnysarvon t erottaman luokan todennäköisyyksiä, on näiden luokkien varianssi.
Otsu osoitti, että varianssin minimoiminen luokan sisällä vastaa luokkien välisen varianssin maksimoimista : [1]
joka ilmaistaan todennäköisyyksien ja aritmeettisen keskiarvon luokassa , joka puolestaan voidaan päivittää iteratiivisesti . Tämä idea johti tehokkaaseen algoritmiin.
Annettu harmaasävykuva Toistolaskuri
Tässä funktiossa pixelsNumber-argumentti on kuvan pikselien kokonaismäärä ja histogrammi-argumentti on 8-bittisen harmaasävykuvan histogrammi, joka esitetään yksiulotteisena taulukkona, jossa elementin numero koodaa harmaasävynumeron, ja kentän arvo koodaa pikselien määrän kyseisellä harmaasävyllä.
funktio otsu ( histogrammi , pikselinluku ) { var summa = 0 , summaB = 0 , wB = 0 , wF = 0 , mB , mF , max = 0 , välillä , kynnys = 0 ; for ( var i = 0 ; i < 256 ; ++ i ) { wB += histogrammi [ i ]; if ( wB == 0 ) jatka ; wF = pikselinluku - wB ; if ( wF == 0 ) tauko ; summaB += i * histogrammi [ i ]; mB = summaB / wB ; mF = ( summa - summaB ) / wF ; välillä = wB * wF * Math . pow ( mB - mF , 2 ); if ( välillä > max ) { max = välillä ; kynnys = i ; } } paluukynnys ; _ } // Testaa: avaa mikä tahansa kuva selaimessa ja suorita koodi konsolissa var im = document . getElementsByTagName ( 'img' )[ 0 ] , cnv = asiakirja . createElement ( 'canvas' ) , ctx = cnv . getContext ( '2d' ); cnv . leveys = im . leveys ; cnv . korkeus = im . korkeus ; ctx . piirtokuva ( im , 0 , 0 ); var imData = ctx . getImageData ( 0 , 0 , cnv . leveys , cnv . korkeus ) , histogrammi = Array ( 256 ) , i , punainen , vihreä , sininen , harmaa ; kun ( i = 0 ; i < 256 ; ++ i ) histogrammi [ i ] = 0 ; for ( i = 0 ; i < imData . data . pituus ; i += 4 ) { punainen = imData . data [ i ]; sininen = imdata . data [ i + 1 ]; vihreä = imData . data [ i + 2 ]; // alfa = imData.data[i + 3]; // https://en.wikipedia.org/wiki/Harmaasävy harmaa = punainen * .2126 + vihreä * .7152 + sininen * .0722 ; histogrammi [ Math . pyöreä ( harmaa )] += 1 ; } var threshold = otsu ( histogrammi , imData . data . pituus / 4 ); konsoli . loki ( "kynnys =%s" , kynnys ); for ( i = 0 ; i < imData . data . pituus ; i += 4 ) { imData . data [ i ] = imData . data [ i + 1 ] = imData . data [ i + 2 ] = imData . data [ i ] >= kynnys ? 255 : 0 ; // opasiteetti 255 = 100 % imData . data [ i + 3 ] = 255 ; } ctx . putImageData ( imData , 0 , 0 ); asiakirja . kehoa . appendChild ( cnv ); konsoli . loki ( "valmis" );Tämän koodin suorittamisen tulos konsolissa näkyy täällä .