+ All Categories
Home > Documents > C/C++ knihovna - zoi.utia.cas.cz

C/C++ knihovna - zoi.utia.cas.cz

Date post: 15-Nov-2021
Category:
Upload: others
View: 2 times
Download: 1 times
Share this document with a friend
34
GenExLib v.1.0 C/C++ knihovna Referenˇ cn´ ı pˇ ıruˇ cka B. Kov´ r, J. Schier, M. Kuneˇ s c UTIA v.v.i., Leden 2014 TA01010931 – GenEx - Syst´ em pro podporu vyhodnocov´ an´ ı metody FISH
Transcript
Page 1: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 2: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 3: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 4: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 5: C/C++ knihovna - zoi.utia.cas.cz

(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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 6: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 7: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 8: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 9: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 10: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 11: C/C++ knihovna - zoi.utia.cas.cz

[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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 12: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 13: C/C++ knihovna - zoi.utia.cas.cz

(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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 14: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 15: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 16: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 17: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 18: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 19: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 20: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 21: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 22: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 23: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 24: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 25: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 26: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 27: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 28: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 29: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 30: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 31: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 32: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 33: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura
Page 34: C/C++ knihovna - zoi.utia.cas.cz

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

  • Uacutevod
  • Instalace
    • Instalace OpenCV v220
    • Instalace GenExLib v10
    • Konfigurace Visual Studio 2012
      • Metodologie a implementace
        • Predzpracovaacuteniacute obrazu
          • Korekce obrazoveacuteho šumu
          • Jasoveacute korekce
            • Detekce bunecnyacutech jader a signaacutelu
            • Popis segmentovanyacutech objektu
            • Priacuteznaky
              • Priacuteklady použitiacute
              • Reference funkciacute
                • Class Preprocessing
                • Class Binarize
                • Class Cell
                • Class Stat
                • Class LogFile
                • Class Visualization
                • Class Config
                  • Zaacutever
                  • Literatura

Recommended