GenExLib v10
CC++ knihovna
Referencnı prırucka
B Kovar J Schier M Kunes
ccopy UTIA vvi Leden 2014
TA01010931 ndash GenEx - System pro podporu vyhodnocovanı metody FISH
Obsah
1 Uvod 3
2 Instalace 421 Instalace OpenCV v220 422 Instalace GenExLib v10 523 Konfigurace Visual Studio 2012 6
3 Metodologie a implementace 1031 Predzpracovanı obrazu 10
311 Korekce obrazoveho sumu 10312 Jasove korekce 11
32 Detekce bunecnych jader a signalu 1233 Popis segmentovanych objektu 2034 Prıznaky 22
4 Prıklady pouzitı 24
5 Reference funkcı 2851 Class Preprocessing 2852 Class Binarize 2953 Class Cell 2954 Class Stat 3055 Class LogFile 3156 Class Visualization 3257 Class Config 32
6 Zaver 33
Literatura 34
2
1
Uvod
Cılem projektu GenEx1 je vyvinout prototyp snımacıho zarızenı a obsluzneho software propodporu vyhodnocovanı analyzy FISH (fluorescencnı in-situ hybridizace) se zamerenımna vyhledavanı nızkofrekvencnıch mozaikovych aberacı Snımacı zarızenı je vyvıjeno s tımze ho bude mozne pouzıt i pro vyhodnocovanı jinych fluorescencnıch analyz Da se tedypredpokladat ze nektere casti metodologie popsane v kapitole 3 bude mozne znovupouzıt v jinych aplikacıch Z tohoto duvodu je aplikace zpracovanı obrazu vyvıjena veforme CC++ knihovny Pri implementaci teto knihovny jsme se snazili
bull vytvorit snadno pouzitelnou CC++ knihovnu pro zpracovanı obrazu z fluorescen-cnıho mikroskopu
bull knihovnu ktera bude univerzalne pouzitelna i pro jine ulohy zpracovanı obrazu vmikroskopii
bull ktera nebude omezena licencnımi poplatky (a to vcetne externıch knihoven)
bull bude optimalizovana pro snımacı zarızenı vyvıjene na pracovisti Camea
Zakladnı informace o instalaci pouzitych metodach a jejich implementacıch ctenar na-lezne v kapitolach 2 a 3 V kapitole 4 uvadıme prıklad aplikace ktera s pouzitım knihovnyGenExLib v obraze detekuje bunecna jadra spocıta zakladnı charakteristiky detekovanychobjektu a vysledky (vystupnı obraz a tabulka prıznaku) ulozı na disk pocıtace Kapitola 5pak prinası referencnı popis pouzitych C++ trıd metod a atributu Shrnutı zakladnıchvlastnostı teto knihovny a jejı dalsı vyvoj uvadıme v zaveru teto prırucky
1GenEx - System pro podporu vyhodnocovanı metody FISH Projekt TA01010931 programu AlfaTechnologicka agentura CR httpwwwtacrcz
3
2
Instalace
Knihovna GenExLib vyuzıva funkcı knihovny OpenCV2 Tato knihovna je vytvarena podBSD licencı a je zdarma dostupna jak pro akademicke tak komercnı projekty V soucasneverzi (243) obsahuje vıce nez 2500 optimalizovanych algoritmu pro zpracovanı obrazuv realnem case Je mozne ji pouzıvat v programovacıch jazycıch CC++ Python a brzotake v Java pod operacnımi systemy Windows Linux Android a Mac V tomto textupredpokladame pouzitı obou knihoven pod operacnım systemem Windows Vsechny do-porucenı se tak tykajı instalace a pouzıvanı pod tımto operacnım systemem
Pro vyvoj knihovny GenExLib byla pouzita verze OpenCV 220 Instalace teto verzeknihovny na pocıtac kde bude pouzıvana knihovna GenExLib je nezbytna Dale pred-pokladame ze je na pocıtaci nainstalovano nektere z vyvojovych prostredı (doporuceneje Microsoft Visual Studio) prıpadne alespon kompilator jazyka CC++
21 Instalace OpenCV v220
Poslednı stabilnı verze ale i verze predchozı je mozne zıskat na strankach projektuOpenCV na webove adrese httpsourceforgenetprojectsopencvlibraryfilesJedna se o instalacnı balıcky ktere byly predem zkompilovany a optimalizovany propouzitı s Microsoft Visual Studio 2010 a novejsım Prubeh instalace je znazornen naObrazku 1
Pri instalaci doporucujeme zvolit
1 Add OpenCV to the system PATH for all users (Obrazek 1-b)
2 Destination folder COpenCV22 (Obrazek 1-c) prıpadne korenovy adresar jinehodisku
3 Zvolıme plnou instalaci (Obrazek 1-d)
Vzhledem k tomu ze se do systemove promenne PATH pridava cesta k binarnım souborumOpenCV tak je doporucen restart pocıtace Tım je OpenCV nainstalovano a pripravenok pouzitı Dodejme ze pokrocilejsı uzivatel pravdepodobne zvolı moznost stazenı nej-novejsıch verzı zdrojovych kodu z SVN repozitare3 OpenCV a vlastnı preklad knihovnyPotrebne informace jak takovou instalaci provest nalezne uzivatel na webovych strankachOpenCV (httpopencvwillowgaragecomwiki)
2Open Source Computer Vision3httpcodeopencvorgsvnopencvtrunkopencv
4
(a) (b)
(c) (d)
(e)
Obrazek 1 Instalace OpenCV
22 Instalace GenExLib v10
Knihovna GenExLib je distribuovana ve formatu ZIP archivu a prelozena pro 32bitovouverzi operacnıho systemu Windows Je dostupna partnerum projektu GenEx na internıchwebovych strankach a to vcetne zdrojovych kodu Ostatnım pak na vyzadanı bez zdro-jovych kodu Archiv obsahuje adresare uvedene v tabulce 1 Vlastnı instalace pak spocıva
5
v rozbalenı archivu na disk pocıtace
DOC DokumentaceEXAMPLES Prelozene demonstracnı programy Pro jejich spustenı je
treba mıt nainstalovany MSVC run-time a OpenCVINCLUDE Include soubory knihovny GenExLibLIB Staticka verze knihovny v debug a release verziSRC Zdrojove kody knihovny a demo aplikacı
Tabulka 1 Adresarova struktura distribuce GenExLib
23 Konfigurace Visual Studio 2012
Knihovnu GenExLib je mozne pouzıvat v libovolnem CC++ projektu Visual StudiaKonfiguraci Visual Studia 2012 pro pouzitı s touto knihovnou si ukazeme na demoaplikaci uvedene v kapitole 4 Predpokladejme ze na pocıtaci mame spravne nainstalovanovyvojove prostredı Microsoft Visual Studio4 knihovnu OpenCV ve verzi 220 a adre-sar s knihovnou GenExLib Zacneme tım ze ve Visual Studiu vytvorıme novy projekt(Obrazek 2 a 3)
Obrazek 2 Vytvorenı noveho projektu ve Visual Studiu 2012
1 z menu zvolıme File New Project
2 v levem panelu pod Visual C++ vybereme Win32
3 ve stredu dialogu zvolıme Win32 Console Application
4httpwwwmicrosoftcomvisualstudioengdownloads
6
Obrazek 3 Vytvorenı noveho projektu ve Visual Studiu 2012
4 zvolıme jmeno projektu napr GenExLibTest
5 na strane Overview zvolıme Next
6 a v Application settings jako typ aplikace Console Application
7 dale muzeme zvolit podporu predkompilovanych hlavickovych souboru prıpadneknihovny MFC
8 volbou Finish vytvorıme projekt
Obrazek 4 Pridanı adresaru s include soubory
7
Tım mame vytvoreny prazdny projekt ktery budeme dal upravovat Zacneme tım zevytvoreny zdrojovy kod (soubor GenExLibTestcpp) upravıme tak aby odpovıdal vypisuz kapitoly 4 Pokud se nynı pokusıme projekt prelozit tak skoncı chybovou hlaskou zenenı mozne nalezt nektere hlavickove soubory definovane v prvnıch radcıch zdrojovehokodu Upravme tedy konfiguraci projektu Zvolme
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties CC++
3 a pak ve strednı casti dialogu Additional Include Directories
4 a pridame adresare ve kterych jsou hlavickove soubory OpenCV a GenExLib
Obrazek 5 Konfigurace linkeru ndash pridanı dalsıch adresaru s knihovnami
Nynı pokud projekt prelozıme tak zjistıme ze nenı mozne prilinkovat knihovnyOpenCV a GenExLib Zvolme tedy
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties Linker General
3 a pak ve strednı casti dialogu Additional Library Directories
4 a pridame adresare ve kterych jsou potrebne knihovny
5 ty pak specifikujeme v Configuration Properties Linker Input v kolonce Ad-ditional Dependencies
8
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
Obsah
1 Uvod 3
2 Instalace 421 Instalace OpenCV v220 422 Instalace GenExLib v10 523 Konfigurace Visual Studio 2012 6
3 Metodologie a implementace 1031 Predzpracovanı obrazu 10
311 Korekce obrazoveho sumu 10312 Jasove korekce 11
32 Detekce bunecnych jader a signalu 1233 Popis segmentovanych objektu 2034 Prıznaky 22
4 Prıklady pouzitı 24
5 Reference funkcı 2851 Class Preprocessing 2852 Class Binarize 2953 Class Cell 2954 Class Stat 3055 Class LogFile 3156 Class Visualization 3257 Class Config 32
6 Zaver 33
Literatura 34
2
1
Uvod
Cılem projektu GenEx1 je vyvinout prototyp snımacıho zarızenı a obsluzneho software propodporu vyhodnocovanı analyzy FISH (fluorescencnı in-situ hybridizace) se zamerenımna vyhledavanı nızkofrekvencnıch mozaikovych aberacı Snımacı zarızenı je vyvıjeno s tımze ho bude mozne pouzıt i pro vyhodnocovanı jinych fluorescencnıch analyz Da se tedypredpokladat ze nektere casti metodologie popsane v kapitole 3 bude mozne znovupouzıt v jinych aplikacıch Z tohoto duvodu je aplikace zpracovanı obrazu vyvıjena veforme CC++ knihovny Pri implementaci teto knihovny jsme se snazili
bull vytvorit snadno pouzitelnou CC++ knihovnu pro zpracovanı obrazu z fluorescen-cnıho mikroskopu
bull knihovnu ktera bude univerzalne pouzitelna i pro jine ulohy zpracovanı obrazu vmikroskopii
bull ktera nebude omezena licencnımi poplatky (a to vcetne externıch knihoven)
bull bude optimalizovana pro snımacı zarızenı vyvıjene na pracovisti Camea
Zakladnı informace o instalaci pouzitych metodach a jejich implementacıch ctenar na-lezne v kapitolach 2 a 3 V kapitole 4 uvadıme prıklad aplikace ktera s pouzitım knihovnyGenExLib v obraze detekuje bunecna jadra spocıta zakladnı charakteristiky detekovanychobjektu a vysledky (vystupnı obraz a tabulka prıznaku) ulozı na disk pocıtace Kapitola 5pak prinası referencnı popis pouzitych C++ trıd metod a atributu Shrnutı zakladnıchvlastnostı teto knihovny a jejı dalsı vyvoj uvadıme v zaveru teto prırucky
1GenEx - System pro podporu vyhodnocovanı metody FISH Projekt TA01010931 programu AlfaTechnologicka agentura CR httpwwwtacrcz
3
2
Instalace
Knihovna GenExLib vyuzıva funkcı knihovny OpenCV2 Tato knihovna je vytvarena podBSD licencı a je zdarma dostupna jak pro akademicke tak komercnı projekty V soucasneverzi (243) obsahuje vıce nez 2500 optimalizovanych algoritmu pro zpracovanı obrazuv realnem case Je mozne ji pouzıvat v programovacıch jazycıch CC++ Python a brzotake v Java pod operacnımi systemy Windows Linux Android a Mac V tomto textupredpokladame pouzitı obou knihoven pod operacnım systemem Windows Vsechny do-porucenı se tak tykajı instalace a pouzıvanı pod tımto operacnım systemem
Pro vyvoj knihovny GenExLib byla pouzita verze OpenCV 220 Instalace teto verzeknihovny na pocıtac kde bude pouzıvana knihovna GenExLib je nezbytna Dale pred-pokladame ze je na pocıtaci nainstalovano nektere z vyvojovych prostredı (doporuceneje Microsoft Visual Studio) prıpadne alespon kompilator jazyka CC++
21 Instalace OpenCV v220
Poslednı stabilnı verze ale i verze predchozı je mozne zıskat na strankach projektuOpenCV na webove adrese httpsourceforgenetprojectsopencvlibraryfilesJedna se o instalacnı balıcky ktere byly predem zkompilovany a optimalizovany propouzitı s Microsoft Visual Studio 2010 a novejsım Prubeh instalace je znazornen naObrazku 1
Pri instalaci doporucujeme zvolit
1 Add OpenCV to the system PATH for all users (Obrazek 1-b)
2 Destination folder COpenCV22 (Obrazek 1-c) prıpadne korenovy adresar jinehodisku
3 Zvolıme plnou instalaci (Obrazek 1-d)
Vzhledem k tomu ze se do systemove promenne PATH pridava cesta k binarnım souborumOpenCV tak je doporucen restart pocıtace Tım je OpenCV nainstalovano a pripravenok pouzitı Dodejme ze pokrocilejsı uzivatel pravdepodobne zvolı moznost stazenı nej-novejsıch verzı zdrojovych kodu z SVN repozitare3 OpenCV a vlastnı preklad knihovnyPotrebne informace jak takovou instalaci provest nalezne uzivatel na webovych strankachOpenCV (httpopencvwillowgaragecomwiki)
2Open Source Computer Vision3httpcodeopencvorgsvnopencvtrunkopencv
4
(a) (b)
(c) (d)
(e)
Obrazek 1 Instalace OpenCV
22 Instalace GenExLib v10
Knihovna GenExLib je distribuovana ve formatu ZIP archivu a prelozena pro 32bitovouverzi operacnıho systemu Windows Je dostupna partnerum projektu GenEx na internıchwebovych strankach a to vcetne zdrojovych kodu Ostatnım pak na vyzadanı bez zdro-jovych kodu Archiv obsahuje adresare uvedene v tabulce 1 Vlastnı instalace pak spocıva
5
v rozbalenı archivu na disk pocıtace
DOC DokumentaceEXAMPLES Prelozene demonstracnı programy Pro jejich spustenı je
treba mıt nainstalovany MSVC run-time a OpenCVINCLUDE Include soubory knihovny GenExLibLIB Staticka verze knihovny v debug a release verziSRC Zdrojove kody knihovny a demo aplikacı
Tabulka 1 Adresarova struktura distribuce GenExLib
23 Konfigurace Visual Studio 2012
Knihovnu GenExLib je mozne pouzıvat v libovolnem CC++ projektu Visual StudiaKonfiguraci Visual Studia 2012 pro pouzitı s touto knihovnou si ukazeme na demoaplikaci uvedene v kapitole 4 Predpokladejme ze na pocıtaci mame spravne nainstalovanovyvojove prostredı Microsoft Visual Studio4 knihovnu OpenCV ve verzi 220 a adre-sar s knihovnou GenExLib Zacneme tım ze ve Visual Studiu vytvorıme novy projekt(Obrazek 2 a 3)
Obrazek 2 Vytvorenı noveho projektu ve Visual Studiu 2012
1 z menu zvolıme File New Project
2 v levem panelu pod Visual C++ vybereme Win32
3 ve stredu dialogu zvolıme Win32 Console Application
4httpwwwmicrosoftcomvisualstudioengdownloads
6
Obrazek 3 Vytvorenı noveho projektu ve Visual Studiu 2012
4 zvolıme jmeno projektu napr GenExLibTest
5 na strane Overview zvolıme Next
6 a v Application settings jako typ aplikace Console Application
7 dale muzeme zvolit podporu predkompilovanych hlavickovych souboru prıpadneknihovny MFC
8 volbou Finish vytvorıme projekt
Obrazek 4 Pridanı adresaru s include soubory
7
Tım mame vytvoreny prazdny projekt ktery budeme dal upravovat Zacneme tım zevytvoreny zdrojovy kod (soubor GenExLibTestcpp) upravıme tak aby odpovıdal vypisuz kapitoly 4 Pokud se nynı pokusıme projekt prelozit tak skoncı chybovou hlaskou zenenı mozne nalezt nektere hlavickove soubory definovane v prvnıch radcıch zdrojovehokodu Upravme tedy konfiguraci projektu Zvolme
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties CC++
3 a pak ve strednı casti dialogu Additional Include Directories
4 a pridame adresare ve kterych jsou hlavickove soubory OpenCV a GenExLib
Obrazek 5 Konfigurace linkeru ndash pridanı dalsıch adresaru s knihovnami
Nynı pokud projekt prelozıme tak zjistıme ze nenı mozne prilinkovat knihovnyOpenCV a GenExLib Zvolme tedy
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties Linker General
3 a pak ve strednı casti dialogu Additional Library Directories
4 a pridame adresare ve kterych jsou potrebne knihovny
5 ty pak specifikujeme v Configuration Properties Linker Input v kolonce Ad-ditional Dependencies
8
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
1
Uvod
Cılem projektu GenEx1 je vyvinout prototyp snımacıho zarızenı a obsluzneho software propodporu vyhodnocovanı analyzy FISH (fluorescencnı in-situ hybridizace) se zamerenımna vyhledavanı nızkofrekvencnıch mozaikovych aberacı Snımacı zarızenı je vyvıjeno s tımze ho bude mozne pouzıt i pro vyhodnocovanı jinych fluorescencnıch analyz Da se tedypredpokladat ze nektere casti metodologie popsane v kapitole 3 bude mozne znovupouzıt v jinych aplikacıch Z tohoto duvodu je aplikace zpracovanı obrazu vyvıjena veforme CC++ knihovny Pri implementaci teto knihovny jsme se snazili
bull vytvorit snadno pouzitelnou CC++ knihovnu pro zpracovanı obrazu z fluorescen-cnıho mikroskopu
bull knihovnu ktera bude univerzalne pouzitelna i pro jine ulohy zpracovanı obrazu vmikroskopii
bull ktera nebude omezena licencnımi poplatky (a to vcetne externıch knihoven)
bull bude optimalizovana pro snımacı zarızenı vyvıjene na pracovisti Camea
Zakladnı informace o instalaci pouzitych metodach a jejich implementacıch ctenar na-lezne v kapitolach 2 a 3 V kapitole 4 uvadıme prıklad aplikace ktera s pouzitım knihovnyGenExLib v obraze detekuje bunecna jadra spocıta zakladnı charakteristiky detekovanychobjektu a vysledky (vystupnı obraz a tabulka prıznaku) ulozı na disk pocıtace Kapitola 5pak prinası referencnı popis pouzitych C++ trıd metod a atributu Shrnutı zakladnıchvlastnostı teto knihovny a jejı dalsı vyvoj uvadıme v zaveru teto prırucky
1GenEx - System pro podporu vyhodnocovanı metody FISH Projekt TA01010931 programu AlfaTechnologicka agentura CR httpwwwtacrcz
3
2
Instalace
Knihovna GenExLib vyuzıva funkcı knihovny OpenCV2 Tato knihovna je vytvarena podBSD licencı a je zdarma dostupna jak pro akademicke tak komercnı projekty V soucasneverzi (243) obsahuje vıce nez 2500 optimalizovanych algoritmu pro zpracovanı obrazuv realnem case Je mozne ji pouzıvat v programovacıch jazycıch CC++ Python a brzotake v Java pod operacnımi systemy Windows Linux Android a Mac V tomto textupredpokladame pouzitı obou knihoven pod operacnım systemem Windows Vsechny do-porucenı se tak tykajı instalace a pouzıvanı pod tımto operacnım systemem
Pro vyvoj knihovny GenExLib byla pouzita verze OpenCV 220 Instalace teto verzeknihovny na pocıtac kde bude pouzıvana knihovna GenExLib je nezbytna Dale pred-pokladame ze je na pocıtaci nainstalovano nektere z vyvojovych prostredı (doporuceneje Microsoft Visual Studio) prıpadne alespon kompilator jazyka CC++
21 Instalace OpenCV v220
Poslednı stabilnı verze ale i verze predchozı je mozne zıskat na strankach projektuOpenCV na webove adrese httpsourceforgenetprojectsopencvlibraryfilesJedna se o instalacnı balıcky ktere byly predem zkompilovany a optimalizovany propouzitı s Microsoft Visual Studio 2010 a novejsım Prubeh instalace je znazornen naObrazku 1
Pri instalaci doporucujeme zvolit
1 Add OpenCV to the system PATH for all users (Obrazek 1-b)
2 Destination folder COpenCV22 (Obrazek 1-c) prıpadne korenovy adresar jinehodisku
3 Zvolıme plnou instalaci (Obrazek 1-d)
Vzhledem k tomu ze se do systemove promenne PATH pridava cesta k binarnım souborumOpenCV tak je doporucen restart pocıtace Tım je OpenCV nainstalovano a pripravenok pouzitı Dodejme ze pokrocilejsı uzivatel pravdepodobne zvolı moznost stazenı nej-novejsıch verzı zdrojovych kodu z SVN repozitare3 OpenCV a vlastnı preklad knihovnyPotrebne informace jak takovou instalaci provest nalezne uzivatel na webovych strankachOpenCV (httpopencvwillowgaragecomwiki)
2Open Source Computer Vision3httpcodeopencvorgsvnopencvtrunkopencv
4
(a) (b)
(c) (d)
(e)
Obrazek 1 Instalace OpenCV
22 Instalace GenExLib v10
Knihovna GenExLib je distribuovana ve formatu ZIP archivu a prelozena pro 32bitovouverzi operacnıho systemu Windows Je dostupna partnerum projektu GenEx na internıchwebovych strankach a to vcetne zdrojovych kodu Ostatnım pak na vyzadanı bez zdro-jovych kodu Archiv obsahuje adresare uvedene v tabulce 1 Vlastnı instalace pak spocıva
5
v rozbalenı archivu na disk pocıtace
DOC DokumentaceEXAMPLES Prelozene demonstracnı programy Pro jejich spustenı je
treba mıt nainstalovany MSVC run-time a OpenCVINCLUDE Include soubory knihovny GenExLibLIB Staticka verze knihovny v debug a release verziSRC Zdrojove kody knihovny a demo aplikacı
Tabulka 1 Adresarova struktura distribuce GenExLib
23 Konfigurace Visual Studio 2012
Knihovnu GenExLib je mozne pouzıvat v libovolnem CC++ projektu Visual StudiaKonfiguraci Visual Studia 2012 pro pouzitı s touto knihovnou si ukazeme na demoaplikaci uvedene v kapitole 4 Predpokladejme ze na pocıtaci mame spravne nainstalovanovyvojove prostredı Microsoft Visual Studio4 knihovnu OpenCV ve verzi 220 a adre-sar s knihovnou GenExLib Zacneme tım ze ve Visual Studiu vytvorıme novy projekt(Obrazek 2 a 3)
Obrazek 2 Vytvorenı noveho projektu ve Visual Studiu 2012
1 z menu zvolıme File New Project
2 v levem panelu pod Visual C++ vybereme Win32
3 ve stredu dialogu zvolıme Win32 Console Application
4httpwwwmicrosoftcomvisualstudioengdownloads
6
Obrazek 3 Vytvorenı noveho projektu ve Visual Studiu 2012
4 zvolıme jmeno projektu napr GenExLibTest
5 na strane Overview zvolıme Next
6 a v Application settings jako typ aplikace Console Application
7 dale muzeme zvolit podporu predkompilovanych hlavickovych souboru prıpadneknihovny MFC
8 volbou Finish vytvorıme projekt
Obrazek 4 Pridanı adresaru s include soubory
7
Tım mame vytvoreny prazdny projekt ktery budeme dal upravovat Zacneme tım zevytvoreny zdrojovy kod (soubor GenExLibTestcpp) upravıme tak aby odpovıdal vypisuz kapitoly 4 Pokud se nynı pokusıme projekt prelozit tak skoncı chybovou hlaskou zenenı mozne nalezt nektere hlavickove soubory definovane v prvnıch radcıch zdrojovehokodu Upravme tedy konfiguraci projektu Zvolme
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties CC++
3 a pak ve strednı casti dialogu Additional Include Directories
4 a pridame adresare ve kterych jsou hlavickove soubory OpenCV a GenExLib
Obrazek 5 Konfigurace linkeru ndash pridanı dalsıch adresaru s knihovnami
Nynı pokud projekt prelozıme tak zjistıme ze nenı mozne prilinkovat knihovnyOpenCV a GenExLib Zvolme tedy
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties Linker General
3 a pak ve strednı casti dialogu Additional Library Directories
4 a pridame adresare ve kterych jsou potrebne knihovny
5 ty pak specifikujeme v Configuration Properties Linker Input v kolonce Ad-ditional Dependencies
8
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
2
Instalace
Knihovna GenExLib vyuzıva funkcı knihovny OpenCV2 Tato knihovna je vytvarena podBSD licencı a je zdarma dostupna jak pro akademicke tak komercnı projekty V soucasneverzi (243) obsahuje vıce nez 2500 optimalizovanych algoritmu pro zpracovanı obrazuv realnem case Je mozne ji pouzıvat v programovacıch jazycıch CC++ Python a brzotake v Java pod operacnımi systemy Windows Linux Android a Mac V tomto textupredpokladame pouzitı obou knihoven pod operacnım systemem Windows Vsechny do-porucenı se tak tykajı instalace a pouzıvanı pod tımto operacnım systemem
Pro vyvoj knihovny GenExLib byla pouzita verze OpenCV 220 Instalace teto verzeknihovny na pocıtac kde bude pouzıvana knihovna GenExLib je nezbytna Dale pred-pokladame ze je na pocıtaci nainstalovano nektere z vyvojovych prostredı (doporuceneje Microsoft Visual Studio) prıpadne alespon kompilator jazyka CC++
21 Instalace OpenCV v220
Poslednı stabilnı verze ale i verze predchozı je mozne zıskat na strankach projektuOpenCV na webove adrese httpsourceforgenetprojectsopencvlibraryfilesJedna se o instalacnı balıcky ktere byly predem zkompilovany a optimalizovany propouzitı s Microsoft Visual Studio 2010 a novejsım Prubeh instalace je znazornen naObrazku 1
Pri instalaci doporucujeme zvolit
1 Add OpenCV to the system PATH for all users (Obrazek 1-b)
2 Destination folder COpenCV22 (Obrazek 1-c) prıpadne korenovy adresar jinehodisku
3 Zvolıme plnou instalaci (Obrazek 1-d)
Vzhledem k tomu ze se do systemove promenne PATH pridava cesta k binarnım souborumOpenCV tak je doporucen restart pocıtace Tım je OpenCV nainstalovano a pripravenok pouzitı Dodejme ze pokrocilejsı uzivatel pravdepodobne zvolı moznost stazenı nej-novejsıch verzı zdrojovych kodu z SVN repozitare3 OpenCV a vlastnı preklad knihovnyPotrebne informace jak takovou instalaci provest nalezne uzivatel na webovych strankachOpenCV (httpopencvwillowgaragecomwiki)
2Open Source Computer Vision3httpcodeopencvorgsvnopencvtrunkopencv
4
(a) (b)
(c) (d)
(e)
Obrazek 1 Instalace OpenCV
22 Instalace GenExLib v10
Knihovna GenExLib je distribuovana ve formatu ZIP archivu a prelozena pro 32bitovouverzi operacnıho systemu Windows Je dostupna partnerum projektu GenEx na internıchwebovych strankach a to vcetne zdrojovych kodu Ostatnım pak na vyzadanı bez zdro-jovych kodu Archiv obsahuje adresare uvedene v tabulce 1 Vlastnı instalace pak spocıva
5
v rozbalenı archivu na disk pocıtace
DOC DokumentaceEXAMPLES Prelozene demonstracnı programy Pro jejich spustenı je
treba mıt nainstalovany MSVC run-time a OpenCVINCLUDE Include soubory knihovny GenExLibLIB Staticka verze knihovny v debug a release verziSRC Zdrojove kody knihovny a demo aplikacı
Tabulka 1 Adresarova struktura distribuce GenExLib
23 Konfigurace Visual Studio 2012
Knihovnu GenExLib je mozne pouzıvat v libovolnem CC++ projektu Visual StudiaKonfiguraci Visual Studia 2012 pro pouzitı s touto knihovnou si ukazeme na demoaplikaci uvedene v kapitole 4 Predpokladejme ze na pocıtaci mame spravne nainstalovanovyvojove prostredı Microsoft Visual Studio4 knihovnu OpenCV ve verzi 220 a adre-sar s knihovnou GenExLib Zacneme tım ze ve Visual Studiu vytvorıme novy projekt(Obrazek 2 a 3)
Obrazek 2 Vytvorenı noveho projektu ve Visual Studiu 2012
1 z menu zvolıme File New Project
2 v levem panelu pod Visual C++ vybereme Win32
3 ve stredu dialogu zvolıme Win32 Console Application
4httpwwwmicrosoftcomvisualstudioengdownloads
6
Obrazek 3 Vytvorenı noveho projektu ve Visual Studiu 2012
4 zvolıme jmeno projektu napr GenExLibTest
5 na strane Overview zvolıme Next
6 a v Application settings jako typ aplikace Console Application
7 dale muzeme zvolit podporu predkompilovanych hlavickovych souboru prıpadneknihovny MFC
8 volbou Finish vytvorıme projekt
Obrazek 4 Pridanı adresaru s include soubory
7
Tım mame vytvoreny prazdny projekt ktery budeme dal upravovat Zacneme tım zevytvoreny zdrojovy kod (soubor GenExLibTestcpp) upravıme tak aby odpovıdal vypisuz kapitoly 4 Pokud se nynı pokusıme projekt prelozit tak skoncı chybovou hlaskou zenenı mozne nalezt nektere hlavickove soubory definovane v prvnıch radcıch zdrojovehokodu Upravme tedy konfiguraci projektu Zvolme
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties CC++
3 a pak ve strednı casti dialogu Additional Include Directories
4 a pridame adresare ve kterych jsou hlavickove soubory OpenCV a GenExLib
Obrazek 5 Konfigurace linkeru ndash pridanı dalsıch adresaru s knihovnami
Nynı pokud projekt prelozıme tak zjistıme ze nenı mozne prilinkovat knihovnyOpenCV a GenExLib Zvolme tedy
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties Linker General
3 a pak ve strednı casti dialogu Additional Library Directories
4 a pridame adresare ve kterych jsou potrebne knihovny
5 ty pak specifikujeme v Configuration Properties Linker Input v kolonce Ad-ditional Dependencies
8
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
(a) (b)
(c) (d)
(e)
Obrazek 1 Instalace OpenCV
22 Instalace GenExLib v10
Knihovna GenExLib je distribuovana ve formatu ZIP archivu a prelozena pro 32bitovouverzi operacnıho systemu Windows Je dostupna partnerum projektu GenEx na internıchwebovych strankach a to vcetne zdrojovych kodu Ostatnım pak na vyzadanı bez zdro-jovych kodu Archiv obsahuje adresare uvedene v tabulce 1 Vlastnı instalace pak spocıva
5
v rozbalenı archivu na disk pocıtace
DOC DokumentaceEXAMPLES Prelozene demonstracnı programy Pro jejich spustenı je
treba mıt nainstalovany MSVC run-time a OpenCVINCLUDE Include soubory knihovny GenExLibLIB Staticka verze knihovny v debug a release verziSRC Zdrojove kody knihovny a demo aplikacı
Tabulka 1 Adresarova struktura distribuce GenExLib
23 Konfigurace Visual Studio 2012
Knihovnu GenExLib je mozne pouzıvat v libovolnem CC++ projektu Visual StudiaKonfiguraci Visual Studia 2012 pro pouzitı s touto knihovnou si ukazeme na demoaplikaci uvedene v kapitole 4 Predpokladejme ze na pocıtaci mame spravne nainstalovanovyvojove prostredı Microsoft Visual Studio4 knihovnu OpenCV ve verzi 220 a adre-sar s knihovnou GenExLib Zacneme tım ze ve Visual Studiu vytvorıme novy projekt(Obrazek 2 a 3)
Obrazek 2 Vytvorenı noveho projektu ve Visual Studiu 2012
1 z menu zvolıme File New Project
2 v levem panelu pod Visual C++ vybereme Win32
3 ve stredu dialogu zvolıme Win32 Console Application
4httpwwwmicrosoftcomvisualstudioengdownloads
6
Obrazek 3 Vytvorenı noveho projektu ve Visual Studiu 2012
4 zvolıme jmeno projektu napr GenExLibTest
5 na strane Overview zvolıme Next
6 a v Application settings jako typ aplikace Console Application
7 dale muzeme zvolit podporu predkompilovanych hlavickovych souboru prıpadneknihovny MFC
8 volbou Finish vytvorıme projekt
Obrazek 4 Pridanı adresaru s include soubory
7
Tım mame vytvoreny prazdny projekt ktery budeme dal upravovat Zacneme tım zevytvoreny zdrojovy kod (soubor GenExLibTestcpp) upravıme tak aby odpovıdal vypisuz kapitoly 4 Pokud se nynı pokusıme projekt prelozit tak skoncı chybovou hlaskou zenenı mozne nalezt nektere hlavickove soubory definovane v prvnıch radcıch zdrojovehokodu Upravme tedy konfiguraci projektu Zvolme
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties CC++
3 a pak ve strednı casti dialogu Additional Include Directories
4 a pridame adresare ve kterych jsou hlavickove soubory OpenCV a GenExLib
Obrazek 5 Konfigurace linkeru ndash pridanı dalsıch adresaru s knihovnami
Nynı pokud projekt prelozıme tak zjistıme ze nenı mozne prilinkovat knihovnyOpenCV a GenExLib Zvolme tedy
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties Linker General
3 a pak ve strednı casti dialogu Additional Library Directories
4 a pridame adresare ve kterych jsou potrebne knihovny
5 ty pak specifikujeme v Configuration Properties Linker Input v kolonce Ad-ditional Dependencies
8
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
v rozbalenı archivu na disk pocıtace
DOC DokumentaceEXAMPLES Prelozene demonstracnı programy Pro jejich spustenı je
treba mıt nainstalovany MSVC run-time a OpenCVINCLUDE Include soubory knihovny GenExLibLIB Staticka verze knihovny v debug a release verziSRC Zdrojove kody knihovny a demo aplikacı
Tabulka 1 Adresarova struktura distribuce GenExLib
23 Konfigurace Visual Studio 2012
Knihovnu GenExLib je mozne pouzıvat v libovolnem CC++ projektu Visual StudiaKonfiguraci Visual Studia 2012 pro pouzitı s touto knihovnou si ukazeme na demoaplikaci uvedene v kapitole 4 Predpokladejme ze na pocıtaci mame spravne nainstalovanovyvojove prostredı Microsoft Visual Studio4 knihovnu OpenCV ve verzi 220 a adre-sar s knihovnou GenExLib Zacneme tım ze ve Visual Studiu vytvorıme novy projekt(Obrazek 2 a 3)
Obrazek 2 Vytvorenı noveho projektu ve Visual Studiu 2012
1 z menu zvolıme File New Project
2 v levem panelu pod Visual C++ vybereme Win32
3 ve stredu dialogu zvolıme Win32 Console Application
4httpwwwmicrosoftcomvisualstudioengdownloads
6
Obrazek 3 Vytvorenı noveho projektu ve Visual Studiu 2012
4 zvolıme jmeno projektu napr GenExLibTest
5 na strane Overview zvolıme Next
6 a v Application settings jako typ aplikace Console Application
7 dale muzeme zvolit podporu predkompilovanych hlavickovych souboru prıpadneknihovny MFC
8 volbou Finish vytvorıme projekt
Obrazek 4 Pridanı adresaru s include soubory
7
Tım mame vytvoreny prazdny projekt ktery budeme dal upravovat Zacneme tım zevytvoreny zdrojovy kod (soubor GenExLibTestcpp) upravıme tak aby odpovıdal vypisuz kapitoly 4 Pokud se nynı pokusıme projekt prelozit tak skoncı chybovou hlaskou zenenı mozne nalezt nektere hlavickove soubory definovane v prvnıch radcıch zdrojovehokodu Upravme tedy konfiguraci projektu Zvolme
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties CC++
3 a pak ve strednı casti dialogu Additional Include Directories
4 a pridame adresare ve kterych jsou hlavickove soubory OpenCV a GenExLib
Obrazek 5 Konfigurace linkeru ndash pridanı dalsıch adresaru s knihovnami
Nynı pokud projekt prelozıme tak zjistıme ze nenı mozne prilinkovat knihovnyOpenCV a GenExLib Zvolme tedy
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties Linker General
3 a pak ve strednı casti dialogu Additional Library Directories
4 a pridame adresare ve kterych jsou potrebne knihovny
5 ty pak specifikujeme v Configuration Properties Linker Input v kolonce Ad-ditional Dependencies
8
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
Obrazek 3 Vytvorenı noveho projektu ve Visual Studiu 2012
4 zvolıme jmeno projektu napr GenExLibTest
5 na strane Overview zvolıme Next
6 a v Application settings jako typ aplikace Console Application
7 dale muzeme zvolit podporu predkompilovanych hlavickovych souboru prıpadneknihovny MFC
8 volbou Finish vytvorıme projekt
Obrazek 4 Pridanı adresaru s include soubory
7
Tım mame vytvoreny prazdny projekt ktery budeme dal upravovat Zacneme tım zevytvoreny zdrojovy kod (soubor GenExLibTestcpp) upravıme tak aby odpovıdal vypisuz kapitoly 4 Pokud se nynı pokusıme projekt prelozit tak skoncı chybovou hlaskou zenenı mozne nalezt nektere hlavickove soubory definovane v prvnıch radcıch zdrojovehokodu Upravme tedy konfiguraci projektu Zvolme
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties CC++
3 a pak ve strednı casti dialogu Additional Include Directories
4 a pridame adresare ve kterych jsou hlavickove soubory OpenCV a GenExLib
Obrazek 5 Konfigurace linkeru ndash pridanı dalsıch adresaru s knihovnami
Nynı pokud projekt prelozıme tak zjistıme ze nenı mozne prilinkovat knihovnyOpenCV a GenExLib Zvolme tedy
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties Linker General
3 a pak ve strednı casti dialogu Additional Library Directories
4 a pridame adresare ve kterych jsou potrebne knihovny
5 ty pak specifikujeme v Configuration Properties Linker Input v kolonce Ad-ditional Dependencies
8
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
Tım mame vytvoreny prazdny projekt ktery budeme dal upravovat Zacneme tım zevytvoreny zdrojovy kod (soubor GenExLibTestcpp) upravıme tak aby odpovıdal vypisuz kapitoly 4 Pokud se nynı pokusıme projekt prelozit tak skoncı chybovou hlaskou zenenı mozne nalezt nektere hlavickove soubory definovane v prvnıch radcıch zdrojovehokodu Upravme tedy konfiguraci projektu Zvolme
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties CC++
3 a pak ve strednı casti dialogu Additional Include Directories
4 a pridame adresare ve kterych jsou hlavickove soubory OpenCV a GenExLib
Obrazek 5 Konfigurace linkeru ndash pridanı dalsıch adresaru s knihovnami
Nynı pokud projekt prelozıme tak zjistıme ze nenı mozne prilinkovat knihovnyOpenCV a GenExLib Zvolme tedy
1 z menu Project Properties
2 v levem panelu zvolıme Configuration Properties Linker General
3 a pak ve strednı casti dialogu Additional Library Directories
4 a pridame adresare ve kterych jsou potrebne knihovny
5 ty pak specifikujeme v Configuration Properties Linker Input v kolonce Ad-ditional Dependencies
8
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
Obrazek 6 Konfigurace linkeru ndash specifikace dalsıch knihoven
9
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
3
Metodologie a implementace
V teto kapitole bude popsana knihovna GenExLib z pohledu pouzitych metod algo-ritmu a jejich implementacı v jazyce CC++ s pouzitım knihovny OpenCV U ctenarepredpokladame alespon zakladnı znalosti v oblasti zpracovanı obrazu a programovanıPodrobny popis a vysvetlenı pouzıvanych pojmu a metod lze nalezt v odborne literaturenaprıklad [1 2 3] Vsechny popisovane algoritmy jsou implementovany jako metodyv trıdach CPreprocessing CBinarize CCell a CStat Reference jednotlivych metod jsouuvedeny v kapitole 5 Obecny postup konstrukce objektu dane trıdy a volanı metod pakje tato
1 include rdquoGenExLibhrdquo
2
3 int main(int argc TCHARlowast argv[])
4 5 Cclass name lowastobject name = new Cclass name(ltconstructor parametersgt)
6 ltoutputgt = object nameminusgtobject method(ltmethod parametersgt)
7 delete object name
9 return
10
31 Predzpracovanı obrazu
Kvalita snımku z fluorescencnıho mikroskopu se muze menit a to i v ramci jednoho vzorkuMuze dochazet ke zmenam v rozlozenı jasu ruzne hladine obrazoveho sumu vznikleho prisnımanı obrazu atp Duvodem mohou byt residua fluoroforu v pozadı snımku nevyhnu-telna i pri presnem dodrzenı predepsaneho laboratornıho postupu prıpravy vzorku Dalsıvliv zcela jiste bude mıt konstrukce snımacıho zarızenı a drobne zmeny expozicnıho nasta-venı kamery v prubehu snımanı vzorku Vzhledem k tomu ze se tyto odchylky projevı vevsech barevnych kanalech tak je vhodne tyto zmeny potlacit a minimalizovat tım jejichvliv na dalsı algoritmy
311 Korekce obrazoveho sumu
Sum v obraze muzeme potlacit tım ze obrazrdquorozmazemeldquo pouzitım jednoducheho fil-
tru Nejpouzıvanejsı filtr je linearnı ve kterem se vystupnı hodnota pixelu na pozici
10
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
[i j] oznacme ji g(i j) spocte jako vazeny soucet vstupnıch pixelu f(i j) v urcitemobdelnıkovem okolı δ bodu [i j]
g(i j) =sumklisinδ
f(i+ l j + l)h(k l) (1)
Tato matematicka operace (1) je oznacovana jako konvoluce funkce f s konvolucnımjadrem h kde konvolucnı jadro obsahuje koeficienty (vahy) filtru V knihovne GenExLibjsou implementovany tyto metody odstranenı sumu
1 BLUR - linearnı konvoluce s h(k l) = 1hwmiddothh
forallk l kde hw a hh jsou dimenze obdel-nıkoveho konvolucnıho jadra h
2 GAUSSIAN - linearnı konvoluce s gaussovskym konvolucnım jadrem
3 MEDIAN - hodnota g(i j) je stanovena jako median z ctvercoveho okolı hodnotfunkce f(i j)
4 BILATERAL - jednoducha metoda odstranenı sumu ktera neovlivnı hrany v obrazeBlizsı popis je mozne najıt naprıklad zde [4]
Pro ilustraci pouzitı techto metod pro potlacenı sumu uvedeme prıklad kodu
1 include rdquoGenExLibhrdquo
2
4 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
5 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
6 IplImagelowast pOutBlur = cvCloneImage(pSrcImage)
7 IplImagelowast pOutGaussian = cvCloneImage(pSrcImage)
8 IplImagelowast pOutMedian = cvCloneImage(pSrcImage)
9 IplImagelowast pOutBilateral = cvCloneImage(pSrcImage)
11 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
12 pOutBlur = imgproc minusgt Blur(33)
13 pOutGaussian = imgproc minusgt Gaussian(7720)
14 pOutMedian = imgproc minusgt Median(55)
15 pOutBilateral = imgproc minusgt Bilateral(55300300)
16 delete imgproc
17
312 Jasove korekce
Rozlozenı jasu v jednotlivych snımcıch i u stejneho vzorku se muze lisit Zakladnı (a castojedinou) globalnı informaci o rozlozenı jasu v obraze nam dava histogram Histogrammuzeme chapat jako cetnosti vyskytu jednotlivych urovnı jasu v obraze Lze jej tedypouzıt jako odhad hustoty pravdepodobnosti rozlozenı jasu v obraze Na zaklade tetoinformace muzeme
1 menit dynamicky rozsah jasu (histogram stretching) a
11
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
2 vyrovnat rozlozenı jasu (histogram equalization)
Histogram stretching
Predpokladejme ze sedotonovy obraz v jednom z barevnych kanalu obsahuje urovne sedeod InL do InH My pozadujeme aby vysledkem teto transformace byl obraz kde tytourovne sede budou mezi OutL a OutH Vysledkem tedy bude obraz s vyssım nebo nizsımrozsahem urovnı jasu a tedy i vyssım nebo nizsım kontrastem Tuto transformaci lzepopsat touto rovnicı
g(i j) =OutH minusOutLInH minus InL
(f(i j)minus InL) +OutL (2)
kde f(i j) je intenzita jasu vstupnıho obrazu na pozici i j a g(i j) intenzita jasu potransformaci
Histogram equalisation
Ekvalizace histogramu je algoritmus ktery zmenı rozlozenı jasu v obraze tak aby se v nemvsechny urovne vyskytovaly priblizne se stejnou cetnostı Ekvalizace umoznuje u obrazus vysokym kontrastem zvyraznit spatne rozeznatelne detaily s nızkym kontrastem Tatotransformace je definovana rovnicı
He(j) =qk minus q0M middotN
jsumi=0
Hin(i) + q0 (3)
kde Hin je puvodnı histogram He ekvalizovany histogram q0 az qk je rozsah pozadovanychurovnı sede v transformovanem obraze se sırkou M a vyskou N pixelu Prıklad zdrojovehokodu pro ekvalizaci histogramu a korekci kontrastu
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pEqvImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
6 IplImagelowast pStrImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
8 CPreprocessinglowast imgproc = new CPreprocessing(pSrcImage)
9 pOutImage = imgproc minusgt EqualizeHist(pSrcImage)
10 pStrImage = imgproc minusgt StretchHist(pSrcImage30180)
11 delete imgproc
12
32 Detekce bunecnych jader a signalu
Pri detekci bunecnych jader a fluorescencnıch signalu vyuzijeme skutecnosti ze bunecnajadra a metafaznı shluky jsou patrne zejmena v modrem (DAPI) barevnem kanalu signaly
12
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
(a) Barevny obraz (b) Cerveny kanal (c) Zeleny kanal (d) Modry kanal
Obrazek 7 Separace barevneho obrazu do 8bitovych RGB kanalu
pak dle zvoleneho barviva v cervenem nebo zelenem kanalu (Obrazek 7) Z uvedenehoobrazku je zrejme ze jsou bunecna jadra i signaly vzhledem k temer homogennımu pozadıdostatecne kontrastnı Tento predpoklad potvrzuje i histogram rozlozenı jasu v modremkanale kde je pozadı definovano vyraznym maximem (Obrazek 8) To je dano tım ze v
(a) Modry kanal (b) Cerveny kanal
Obrazek 8 Histogram rozlozenı jasu v modrem a cervenem kanale
obou prıpadech je plocha pozadı vetsı nez plocha objektu v popredı Za povsimnutı stojıze signaly vzhledem k zanedbatelne plose nejsou v histogramu cerveneho kanalu identifi-kovatelne jako lokalnı maximum S tım budeme muset pri volbe vhodne segmentacnı me-tody pocıtat Na zaklade vyse uvedenych skutecnostı jsme jako segmentacnı metodu zvo-lili prahovanı Pokrocile segmentacnı algoritmy zalozene na modelech a optimalizacnıchmetodach (level-sets aktivnı kontury atp) prıpadne statistickych metodach nejsou vknihovne GenExLib ve verzi 10 implementovane
Segmentace prahovanım transformuje (binarizuje) vstupnı obraz na objekty v popredıb(i j) = 1 a na pozadı b(i j) = 0
b(i j) =
1 kdyz f(i j) ge T (4)
0 kdyz f(i j) lt T (5)
Vzhledem k tomu ze pocet segmentovanych objektu (a tedy i plocha popredı) nenı kon-stantnı tak nenı mozne pouzıt metody zalozene na pevnem prahu Z tohoto duvodujsme se zamerily na metody u kterych je prah stanoven adaptivne budrsquo analyzou his-
13
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
togramu nebo statistickou optimalizacı Pri experimentech se nam osvedcily tyto dvemetody vypoctu prahu
1 OTSU [5] a
2 Triangle [6]
OTSUSedotonovy obraz obsahuje celkem M times N pixelu s urovnemi sedi od [1 middot middot middot L] Pocetpixelu s urovnı sedi i oznacme fi Potom pravdepodobnost vyskytu urovne sedi i vobraze bude definovana
pi =fi
M middotN(6)
V prıpade prahovanı s jednım prahem budou urovne sedi rozdeleny do dvou trıd ndash trıdaC1 s urovnemi sedi [1 middot middot middot t] a trıda C2 s urovnemi sedi [t + 1 middot middot middot L] Potom distribucepravdepodobnostı pro jednotlive intenzity bude pro tyto trıdy
C1 = p1ω1(t) middot middot middot ptω1(t) (7)
C2 = pt+1ω2(t) middot middot middot pLω2(t) (8)
kde
ω1(t) =tsumi=1
pi a ω2(t) =Lsum
i=t+1
pi (9)
Dale strednı hodnoty intenzity pro tyto dve trıdy jsou
micro1(t) =tsumi=1
i middot piω1(t)
micro2(t) =Lsum
i=t+1
i middot piω2(t)
(10)
Pokud microT bude strednı hodnota intenzity jasu v celem obrazku pak je zrejme ze ω1micro1 +ω2micro2 = microT a ω1 + ω2 = 1 Vazeny prumer rozptylu intenzit mezi trıdou C1 a C2 pak jedefinovan rovnicı
σ2ω = ω1(micro1 minus microT )2 + ω2(micro2 minus microT )2 (11)
Otsu overil ze optimalnı prah tlowast zıskame tehdy kdyz σ2ω bude minimalnı
tlowast = ArgMaxσ2ω(t) 1 le t le L (12)
Pokracujme tım jak je tato metoda vypoctu segmentacnıho prahu implementovana
1 IplImagelowast CBinarizeOTSU(void)
2 3 if (m pImage == NULL)
4 return NULL
5 else 6 IplImagelowast imgBin = cvCreateImage(cvSize(m pImageminusgtwidthm pImageminusgtheight)
7 IPL DEPTH 8U1)
8 const int GRAYLEVEL = 256
9 define MAX BRIGHTNESS 255
10 int hist [GRAYLEVEL]
14
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
11 double prob[GRAYLEVEL]
12 double omega[GRAYLEVEL] prob of graylevels
13 double myu[GRAYLEVEL] mean value for separation
14 double max sigma
15 double sigma[GRAYLEVEL] interminusclass variance
16 int threshold threshold for binarization
17 Histogram generation
18 memset((intlowast) hist 0 GRAYLEVEL lowast sizeof(int) )
19 CvSize size = cvGetSize(m pImage)
20 for (int i = 0 i lt sizeheight ++i) 21 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
22 i lowast m pImageminusgtwidthStep)
23 for (int j = 0 j lt sizewidth ++j) 24 int k = (int)((unsigned char) lowast(pData+j))
25 hist [k]++
26 27 28 int area = sizewidth lowast size height
29 calculation of probability density
30 for (int i = 0 i lt GRAYLEVEL ++i )
31 prob[i ] = (double) ((double)hist[i] (double)area)
32 omega amp myu generation
33 omega[0] = prob[0]
34 myu[0] = 00
35 for (int i = 1 i lt GRAYLEVEL i++) 36 omega[i] = omega[iminus1] + prob[i]
37 myu[i] = myu[iminus1] + (ilowastprob[i])
38 39 sigma maximization
40 minusminus sigma stands for interminusclass variance and determines optimal threshold value
41 threshold = 0
42 max sigma = 00
43 for (int i = 0 i lt GRAYLEVELminus1 i++) 44 if (omega[i] = 00 ampamp omega[i] = 10) 45 sigma[i ] = ((myu[(GRAYLEVELminus1)]lowastomega[i] minus myu[i]) lowast46 (myu[GRAYLEVELminus1]lowastomega[i] minus myu[i])) (omega[i]lowast(10 minus omega[i]))
47 48 else
49 sigma[i ] = 00
50 if (sigma[i ] gt max sigma) 51 max sigma = sigma[i]
52 threshold = i
53 54 55 binarization output into imgBin
56 for (int y = 0 y lt sizeheight ++y) 57 unsigned charlowast pData = (unsigned charlowast) (m pImageminusgtimageData +
58 (y lowast m pImageminusgtwidthStep))
15
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
59 unsigned charlowast pDataBin = (unsigned charlowast) (imgBinminusgtimageData +
60 (y lowast imgBinminusgtwidthStep))
61 for (int x = 0 x lt sizewidth ++x) 62 if ( lowast(pData+x) gt threshold)63 lowast(pDataBin+x) = MAX BRIGHTNESS
64 65 else
66 lowast(pDataBin+x) = 0
67 68 69 return imgBin
70 71
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
8 pBinImage = binarizeminusgtOTSU()
9 delete(binarize)
10
Z rovnic 78 a obrazku 8(a) je zrejme ze tato segmentacnı metoda je vhodna pro obrazve kterem jsou objekty v popredı dostatecne velke tedy v histogramu identifikovatelnejako lokalnı maximum To nenı splneno v prıpade segmentace signalu jejichz velikostje v porovnanı s pozadım zanedbatelna Z tohoto duvodu tato metoda pri segmentacisignalu selhava zvlaste pokud pozadı nenı dostatecne homogennı ndash naprıklad vlivemnestejnomerneho nasvıcenı vzorku Vysledky segmentace bunecnych jader a signalu toutometodou uvadıme v obrazku 9 Pro srovnanı vysledky segmentace metodou Trianglektera bude popsana v dalsı casti textu jsou zobrazeny na obrazku 11
Obrazek 9 Segmentace bunecnych jader a fluorescencnıch signalu metodou OTSU
16
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
TRIANGLETuto metodu publikoval Zack a kol [6] uz v roce 1977 Tedy zhruba ve stejne dobe jakoOtsu [5] Triangle algoritmus pro stanovenı segmentacnıho prahu je zalozen na analyzetvaru histogramu Je vhodny zejmena pro obraz ve kterem jas objektu v popredı vytvarıv histogramu nevyrazna lokalnı maxima Prıpadne jas techto objektu nenı mozne v his-togramu identifikovat Princip algoritmu je zrejmy z obrazku 10 Nechtrsquo a je nejmensı a
Obrazek 10 Triangle algoritmus stanovenı segmentacnıho prahu Zdroj [6]
b nejvetsı nenulova hodnota jasu na x-ove ose histogramu Nalezneme maximalnı hod-notu histogramu Hmax(i) a jı odpovıdajıcı uroven jasu i i isin 〈a b〉 Dale zjistıme kteryz intervalu 〈a i〉 〈i b〉 je vetsı V nem budeme hledat segmentacnı prah V dalsım textupredpokladejme ze vetsı interval je stejne jako na obrazku 10 ten na prave strane od ma-xima Pro forallj isin 〈i b〉 vedrsquome usecku spojujıcı Hmax(i) s j a zmerme jejı kolmou vzdalenostL(j) od histogramu Prah A zvolıme tam kde je L(j) maximalnı Takto urceny prah byvanekdy upraven prictenım konstantnı hodnoty jako kompenzace nehomogennıho pozadı
Stejne jako v prıpade OTSU algoritmu uvedrsquome i pro metodu Triangle jejı implementaciv knihovne GenExLib
1 include ltmathhgt
3 int CBinarizeTriangle(void)
4 5 if (m pImage == NULL)
6 return NULL
7 else 8 IplImagelowast image = m pImage
9 int width = imageminusgtwidth
10 int height = imageminusgtheight
11 IplImagelowast imageBin = cvCreateImage(cvSize(imageminusgtwidth imageminusgtheight) 8 1)
12 create histogram
13 int data[256] = 014 for(int i=0 ilthi++) 15 for(int j=0jltwj++) 16 CvScalar m n
17 m = cvGet2D(image i j)
17
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
18 data[(int)mval[0]]++
19 20 21 find min and max
22 int min = 0 dmax=0 max = 0 min2=0
23 for (int i = 0 i lt datalength i++) 24 if (data[ i]gt0)25 min=i
26 break
27 28 29 if (mingt0) minminusminus line to the (p==0) point not to data[min]
30 the other extreme
31 for (int i = 255 i gt0 iminusminus ) 32 if (data[ i]gt0)33 min2=i
34 break
35 36 37 if (min2lt255) min2++ line to the (p==0) point not to data[min]
38 for (int i =0 i lt 256 i++) 39 if (data[ i ] gtdmax) 40 max=i
41 dmax=data[i]
42 43 44 find which is the furthest side
45 boolean inverted = false
46 if ((maxminusmin)lt(min2minusmax))47 reverse the histogram
48 inverted = true
49 int left = 0 index of leftmost element
50 int right = 255 index of rightmost element
51 while (left lt right) 52 exchange the left and right elements
53 int temp = data[left ]
54 data[ left ] = data[right ]
55 data[right ] = temp
56 move the bounds toward the center
57 left ++
58 rightminusminus
59 60 min=255minusmin2
61 max=255minusmax
62 63 if (min == max)64 return min
65
18
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
66 describe line by nx lowast x + ny lowast y minus d = 0
67 double nx ny d
68 nx is just the max frequency as the other point has freq=0
69 nx = data[max] minusmin data[min] lowest value bmin = (p=0) in the image
70 ny = min minus max
71 d = sqrt(nx lowast nx + ny lowast ny)
72 nx = d
73 ny = d
74 d = nx lowast min + ny lowast data[min]
75 find split point
76 int split = min
77 double splitDistance = 0
78 for (int i = min + 1 i lt= max i++) 79 double newDistance = nx lowast i + ny lowast data[i] minus d
80 if (newDistance gt splitDistance) 81 split = i
82 splitDistance = newDistance
83 84 85 splitminusminus
86 if (inverted) 87 The histogram might be used for something else so let rsquos reverse it back
88 int left = 0
89 int right = 255
90 while (left lt right) 91 int temp = data[left ]
92 data[ left ] = data[right ]
93 data[right ] = temp
94 left ++
95 rightminusminus
96 97 return (255minussplit)
98 99 else
100 return split
101 102
Vlastnı pouzitı vypoctu prahu a binarnıho obrazu s pouzitım knihovny GenExLib je pakvelmi snadne
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 IplImagelowast pSrcImage = cvLoadImage(CT2CA(filename)minus1)
5 IplImagelowast pBinImage = cvCreateImage( cvGetSize(pSrcImage) pSrcImageminusgtdepth1 )
7 CBinarizelowast binarize = new CBinarize(pSrcImage)
19
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
8 int threshold = binarizeminusgtTriangle()
9 delete(binarize)
11 cvThreshold( pSrcImage pBinImage threshold 255 CV THRESH BINARY )
12
Obrazek 11 Segmentace bunecnych jader a fluorescencnıch signalu metodou Triangle
33 Popis segmentovanych objektu
Zakladnım prvkem pro popis segmentovanych objektu v knihovne GenExLib je konturaKontura je sekvence bodu ktera v obraze definuje krivku V OpenCV je kontura repre-zentovana jako dynamicky spojovy seznam ve kterem kazdy prvek nese zaroven informaci(odkaz) na prvek nasledujıcı V nası implementaci konturu urcıme prımo z binarizovanehoobrazu algoritmem ktery v roce 1985 publikoval Suzuki [8] Uvedrsquome ukazku zdrojovehokodu pro popis segmentovanych objektu konturou
1 include rdquoGenExLibhrdquo
2
3 CString filename = T(rdquotest tif rdquo) 8bit gray scale image
4 pSrcImage minusminus vstupni barevny obraz
5 pBinImage minusminus binarni segmentovany obraz
6 CvSeqlowast contours = 0
7 CvMemStoragelowast storage = cvCreateMemStorage(0)
9 int level = cvFindContours(pBinImage storage ampcontours sizeof(CvContour)
10 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
11
Pro visualizaci segmentovanych objektu pouzıvame funkce ktere jsou dostupne v OpenCVV soucasne verzi je mozne pro kazdy segmentovany objekt vykreslit jeho konturu (imple-mentace)
12 CvScalar contour color = CV RGB(02550) contour color
13 draw all contours
14 for(CvSeqlowast c = contours c = NULL c = cminusgth next)
15 cvDrawContours(pSrcImageccontour colorcontour color028cvPoint(00))
20
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
prıpadne objekt aproximovat opsanym obdelnıkem
16 CvRect rect
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 rect = cvBoundingRect(c)
19 cvRectangle(pSrcImage cvPoint(rectx rect y)
20 cvPoint(rectx + rectwidth rect y + rectheight)
21 CV RGB(255 0 0))
22
nebo elipsou
16 CvBox2D32flowast box
17 for(CvSeqlowast c = contours c = NULL c = cminusgth next) 18 CvPoint center CvSize size int i
19 int count = cgttotal
20 Number point must be more than or equal to 6
21 if (count lt 6)
22 continue
23 Alloc memory for contour point set
24 PointArray = (CvPointlowast)malloc( countlowastsizeof(CvPoint) )
25 PointArray2D32f= (CvPoint2D32flowast)malloc( countlowastsizeof(CvPoint2D32f) )
26 Alloc memory for ellipse data
27 box = (CvBox2D32flowast)malloc(sizeof(CvBox2D32f))
28 Get contour point set
29 cvCvtSeqToArray(c PointArray CV WHOLE SEQ)
30 Convert CvPoint set to CvBox2D32f set
31 for(i=0 iltcount i++) 32 PointArray2D32f[i]x = (float)PointArray[i ] x
33 PointArray2D32f[i]y = (float)PointArray[i ] y
34 35 Fits ellipse to current contour
36 cvFitEllipse (PointArray2D32f count box)
37 Convert ellipse data from float to integer representation
38 center x = cvRound(boxminusgtcenterx)
39 center y = cvRound(boxminusgtcentery)
40 size width = cvRound(boxminusgtsizewidthlowast05)
41 size height = cvRound(boxminusgtsizeheightlowast05)
42 boxminusgtangle = minusboxminusgtangle
43 Draw ellipse
44 cvEllipse(image04 center size boxminusgtangle 0 360
45 CV RGB(00255) 1 CV AA 0)
46 Free memory
47 free (PointArray)
48 free (PointArray2D32f)
49 free (box)
50 51
21
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
34 Prıznaky
Prıznaky (zakladnı popisne charakteristiky) detekovanych objektu jsou vypocıtany pouzepro ty ktere s velkou pravdepodobnostı odpovıdajı bunecnym jadrum nebo fluorescencnımsignalum Experimentalne jsme overily ze uspokojive vysledky zıskame tehdy pokud profiltraci detekovanych objektu pouzijeme jejich plochu a excentricitu Vlastnı filtrovanıobjektu pak probıha takto
1 CvSeqlowast pCur sekvence kontur
2 while(pCur = 0L)
3 4 i++
5 CStatlowast stat = new CStat(pCur)
6 statminusgtCalculateStatistics()
7 if (statminusgtstatseccentricity lt 05) 8 CvSeqlowast pTmp
9 pTmp = pCur
10 if (pCurminusgth prev == 0L) first element
11 pCur = pCurminusgth next
12 if (pCur = 0L)
13 pCurminusgth prev = 0L
14 pTmpminusgth next = 0L
15 lowast cells = pCur
16 17 else if (pCurminusgth next == 0L) last element
18 pCurminusgth prevminusgth next = 0L
19 pCur = 0L
20 pTmpminusgth prev = 0L
21 22 else 23 pCurminusgth nextminusgth prev = pCurminusgth prev
24 pCurminusgth prevminusgth next = pCurminusgth next
25 pCur = pCurminusgth next
26 pTmpminusgth prev = 0L
27 pTmpminusgth next = 0L
28 29 30 else
31 pCur = pCurminusgth next
32 delete stat
33
Po teto operaci jsou ze spojoveho seznamu detekovanych kontur odstraneny ty ktere ne-splnujı nase pozadavky na excentricitu prıpadne plochu Na zbytku jsou pak napocıtanyprıznaky Knihovna GenExLib ma v aktualnı verzi implementovany tyto popisne statis-tiky
1 plocha objektu
22
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
2 delka opsane kontury
3 excentricita
4 souradnice teziste
Vlastnı vypocet prıznaku je pak snadny
1 for(CvSeqlowast c = m pContours c = NULL c = cminusgth next) 2 CStatlowast statistics = new CStat(c)
3 statistics minusgtCalculateStatistics()
5 if ( statistics minusgtstatsarea == 00)
6 7 idx++
8 continue
9 10 napocitane statistiky
11 statistics minusgtstatsarea
12 statistics minusgtstatslength
13 statistics minusgtstats eccentricity
14 statistics minusgtstatsc of grx
15 statistics minusgtstatsc of gry
16 idx++
17
Vysledkem jsou naprıklad data uvedena v tabulce 2
23
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
4
Prıklady pouzitı
Vytvorme s pouzitım knihoven OpenCV a GenExLib aplikaci ktera v obraze z fluo-rescencnıho mikroskopu detekuje bunecna jadra oznacı je konturou kazdemu deteko-vanemu jadru priradı identifikator a napocıta jeho zakladnı parametry Pokud v MicrosoftVisual Studiu 2012 vytvorıme projekt pro novou konzolovou Win32 aplikaci postupempopsanym v kapitole 23 bude automaticky vygenerovany zdrojovy kod vypadat takto
1 include rdquostdafxhrdquo
2 include rdquocvhrdquo
3 include rdquocxcorehrdquo
4 include rdquohighguihrdquo
5 include rdquoGenExLibTesthrdquo
6 include rdquoGenExLibhrdquo
8 ifdef DEBUG
9 define new DEBUG NEW
10 endif
12 CWinApp theApp
14 using namespace std
15 using namespace cv
17 int tmain(int argc TCHARlowast argv[] TCHARlowast envp[])
18 19 int nRetCode = 0
21 HMODULE hModule = GetModuleHandle(NULL)
23 if (hModule = NULL)
24 25 initialize MFC and print and error on failure
26 if (AfxWinInit(hModule NULL GetCommandLine() 0))
27 28 tprintf ( T(rdquoFatal Error MFC initialization failednrdquo))
29 nRetCode = 1
30 31 else
32
24
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
33 lowastminus misto pro vlastni kod algoritmu lowast34 35 36 else
37 38 TODO change error code to suit your needs
39 tprintf ( T(rdquoFatal Error GetModuleHandle failednrdquo))
40 nRetCode = 1
41 42 return nRetCode
43
Do kodu jsme pouze vlozili nactenı hlavickovych souboru knihovny OpenCV na radcıch 2
- 4 hlavickovy soubor knihovny GenExLibh na radku 6 a pak jmenny prostor OpenCVna radku 15 Vlastnı kod algoritmu budeme vkladat na radek 33 Nejprve nacteme vstupnıobraz Predpokladejme ze soubor bude ve stejnem adresari jako vysledny program a budese jmenovat rdquotesttifrdquo
1 CString m strImageFileName = T(rdquotesttifrdquo)
2 IplImagelowast m pImage = cvLoadImage(CT2CA(m strImageFileName)minus1)
Obraz je tvoren tremi barevnymi kanaly RGB Vıme ze bunecna jadra jsou vyraznazejmena v modrem kanalu Proto si vytvorıme tri pomocne 8bitove monochromatickeobrazky pro kazdy barevny kanal jeden a vstupnı obraz do nich rozlozıme Dale pakbudeme pracovat pouze s modrym barevnym kanalem
3 IplImagelowast r image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
4 IplImagelowast g image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
5 IplImagelowast b image = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
6 cvSplit(m pImageb imageg imager imageNULL)
V dalsım kroku z obrazu odstranıme sum (radek 9) a provedeme jeho binarizaci
7 IplImagelowast thr image = cvCreateImage(cvGetSize(m pImage) m pImageminusgtdepth1 )
8 IplImagelowast temp = cvCreateImage( cvGetSize(m pImage) m pImageminusgtdepth1 )
9 cvSmooth( b image temp CV GAUSSIAN 7 7 )
10 b image = temp
11 cvReleaseImage(amptemp)
13 CBinarizelowast binarize = new CBinarize(b image)
14 thr image = binarizeminusgtOTSU()
15 delete(binarize)
Na radku 13 dynamicky vytvorıme novy objekt binarize Pro prahovanı pouzijeme algo-ritmus OTSU ktery je volan na radku 14 jako metoda objektu binarize Objekt je pakna radku 15 ukoncen a dealokovan destruktorem Tım zıskame binarizovany obraz kteryobsahuje bıle objekty v popredı na cernem pozadı V dalsım kroku hranice techto objektu
25
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
popıseme konturou
16 CvSeqlowast contours = 0
17 CvMemStoragelowast storage = cvCreateMemStorage(0)
18 IplImagelowast segm image = cvCloneImage(thr image)
20 int level = cvFindContours(segm image storage ampcontours sizeof(CvContour)
21 CV RETR EXTERNAL CV CHAIN APPROX SIMPLE cvPoint(00) )
Contours je spojovy seznam ktery obsahuje struktury popisujıcı jednotlive spoctene kon-tury Jejich celkovy pocet je ulozen v promenne level V zaverecne fazi vytvorıme CSVsoubor s popisnymi prıznaky jednotlivych jader ktera budou pro snadnou identifikacive vystupnım obraze oznacena
22 CString logname = T(rdquotestcsvrdquo)
23 CString imagename = T(rdquotest labelsjpgrdquo)
25 CLogFilelowast log = new CLogFile(lognamem pImagecontours)
26 logminusgtLabelImage()
27 logminusgtSaveImage(imagename)
28 logminusgtCSVStatistics()
29 delete(log)
Promenne na radcıch 22 a 23 definujı jmena CSV souboru a souboru s vystupnım obrazemOba soubory budou vytvoreny ve stejnem adresari ve kterem bude spusteny program Ge-nExLibTest Na radku 25 je dynamicky vytvoren objekt log a pomocı metod LabelImage()a CSVStatistics() jsou vytvorena vystupnı data Objekt je pote ukoncen destruktoremNa zaver dealokujeme i ostatnı promenne
22 cvReleaseMemStorage(ampstorage)
23 cvReleaseImage(ampm pImage)
24 cvReleaseImage(ampr image)
25 cvReleaseImage(ampg image)
26 cvReleaseImage(ampb image)
27 cvReleaseImage(ampsegm image)
28 cvReleaseImage(ampthr image)
Program spustıme z prıkazove radky Vystupem je tabulka 2 a obrazek 12 s oznacenymijadry
ID Area Length Eccentricity CoG (x) CoG (y)1 3457900000 75306810 034054 18049921 396288642 5394000000 126431283 088500 45885843 264306413 1317150000 45754624 029372 9841728 13332914
Tabulka 2 Zakladnı popisne charakteristiky detekovanych objektu
26
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
Obrazek 12 Vstupnı a vystupnı obraz programu GenExLibTest
27
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
5
Reference funkcı
51 Class Preprocessing
CPreprocessingCPreprocessing
Konstruktor
CPreprocessing()
CPreprocessing(IplImagelowast image)
Metody
IplImagelowast Blur(int width int height)
IplImagelowast Gaussian(int width int height flout sigma)
IplImagelowast Median(int width int height)
IplImagelowast Bilateral(int width int height float a float b)
IplImagelowast EqualizeHist(IplImagelowast pSrcImage)
IplImagelowast StretchHist(IplImagelowast pSrcImage int lower int upper)
Atributy
IplImagelowast m pImage
Destruktor
CPreprocessinglowast preproc = new CPreprocessing(IplImagelowast image)
delete preproc
28
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
52 Class Binarize
CBinarizeCBinarize
Konstruktor
CBinarize()
CBinarize(IplImagelowast image)
Metody
IplImagelowast OTSU()
int Triangle ()
Atributy
IplImagelowast m pImage
Destruktor
CBinarizelowast binarize = new CBinarize(IplImagelowast image)
delete binarize
53 Class Cell
CCellCCell
Konstruktor
CCell()
CCell(IplImagelowast image)
CCell(IplImagelowast image IplImagelowast c img IplImagelowast i img)
CCell(CvSeqlowast p contours IplImagelowast image)
Metody
29
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
CvSeqlowast Find(int type)
void Cell(CvSeqlowastlowast cells)
void Interphase(CvSeqlowastlowast cells)
Atributy
CvSeqlowast m pContours
IplImagelowast m pImage
IplImagelowast m pcImage
IplImagelowast m piImage
Destruktor
CCelllowast cell = new CCell(IplImagelowast image)
delete cell
54 Class Stat
CStatCStat
Struktury
typedef struct CvMoments moments
double eccentricity
double area
double length
CvPoint2D64f c of gr
Statistics
Konstruktor
CStat(void)
CStat(CvSeqlowast contour)
Metody
30
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
Statistics CalculateStatistics ()
Atributy
CvSeqlowast m pContour
Statistics stats
Destruktor
CStatlowast stats = new CStat(CvSeqlowast contour)
delete stats
55 Class LogFile
CLogFileCLogFile
Konstruktor
CLogFile(void)
CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
Metody
void LabelImage()
void CSVStatistics()
void SaveImage(CString filename)
Atributy
CString m strLog
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
31
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
CLogFilelowast logfile = new CLogFile(CString logname IplImage lowastimage CvSeqlowast contours)
delete logfile
56 Class Visualization
CVisualizationCVisualization
Konstruktor
CVisualization()
CVisualization(IplImagelowast image)
CVisualization(IplImagelowast image CvSeqlowast contours)
Metody
void DrawContours()
void DrawBoundingBox()
void DrawEllipse()
void SaveImage(CString filename)
Atributy
IplImagelowast m pImage
CvSeqlowast m pContours
Destruktor
CVisualizationlowast visualization = new CVisualization(IplImagelowast image CvSeqlowast contours)
delete visualization
57 Class Config
Trıda Config nenı v soucasne verzi knihovny implementovana Predpokladame ale ze budenutne pred vlastnım vyhodnocenım vzorku system konfigurovat naprıklad dle pouzitehohardware (objektiv mikroskopu kamera) fluorescencnıch barviv typu experimentu atpTato trıda nam do budoucna umoznı system snadno nastavit pro optimalnı zpracovanıkonkretnı ulohy
32
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
6
Zaver
V tomto dokumentu jsme predstavili CC++ knihovnu GenExLib ve verzi 10 kteravznikla jako jeden z vysledku projektu GenEx K zaveru roku 2012 obsahuje algoritmyktere byly vyvinute a experimentalne overene v prubehu dosavadnıho resenı projektuKnihovna umoznuje v obraze z fluorescencnıho mikroskopu prahovanım segmentovat ob-jekty dle jejich velikosti a kruhovitosti je separovat na bunecna jadra nebo fluorescencnısignaly a priradit k nim jejich zakladnı popisne charakteristiky Ty jsou pak pouzıvanyk dalsımu ndash statistickemu vyhodnocenı vzorku Je pravdepodobne ze knihovna budeprubezne rozsirovana o dalsı metody ktere vzniknou dalsım vyvojem systemu pro pod-poru vyhodnocenı metody FISH Knihovna je volne prıstupna resitelskemu tymu projektuGenEx vcetne zdrojovych kodu Ostatnım je dostupna na vyzadanı v binarnı forme
Tento dokument vznikl dıky podpore projektu TA01010931 - GenEx ndash Systempro podporu vyhodnocovanı metody FISH programem Alfa Technologicke agenturyCeske Republiky httpwwwtacrcz
33
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34
Literatura
[1] Linda G Shapiro and George C Stockman Computer Vision Prentice Hall Massa-chusetts 2nd Edition 2001 ISBN 0-13-030796-3
[2] Milan Sonka Vaclav Hlavac and Roger Boyle Image Processing Analysis and Ma-chine Vision Thomson 2008 ISBN 0-495-08252-X
[3] Bruce Eckel Thinking in C++ Introduction to Standard C++ Prentice Hall 2 edi-tion 2000 ISBN 0-13-979809-9
[4] C Tomasi and R Manduchi Bilateral Filtering for Gray and Color Images Procee-dings of the 1998 IEEE International Conference on Computer Vision Bombay India1998
[5] Otsu N A Threshold Selection Method from Gray-Level Histograms IEEE Transacti-ons on Systems man and Cybernetics 1979 pp 62-66
[6] Zack GW Rogers WE Latt SA Automatic measurement of sister chromatid exchangefrequency J Histochem Cytochem 1977 25 (7) 741ndash53 PMID 70454
[7] Canny J A Computational Approach To Edge Detection IEEE Trans Pattern Ana-lysis and Machine Intelligence 8(6)679ndash698 1986
[8] Suzuki S and Abe K Topological Structural Analysis of Digitized Binary Images byBorder Following CVGIP 30 1 pp 32-46 1985
34