Zadanie 5
Najneskorší termín odovzdania: 24.3.2024 (nedeľa) o 18:00
Odovzdávané súbory: AnalyzatorSkenu.java
, Osoba.java
Doplňujúce požiadavky:
- riešenia, ktoré nebude možné skompilovať (t.j. riešenia so syntaktickými chybami) nebudú hodnotené,
- zdrojový kód správne naformátujte (CTRL+SHIFT+F),
- komentovaný zdrojový kód
Bunka sem, bunka tam (4 body)
Daniela je študentkou medziodborového štúdia biológia-informatika na UPJŠ. A ako to už býva pri štúdiu biológie, práci v labákoch sa žiaden študent nevyhne. Daniela nie je žiadnou výnimkou. Pri jednej takej práci v laboratóriu im ich vyučujúci ukázal experiment, na ktorom práve robia. V rámci experimentu študujú pohyb a delenie akýchsi buniek (Daniela je ešte len prváčka, takže to, o aké bunky ide, veľmi „nerieši“). Samozrejme na UPJŠ nie je núdza ani o modernú laboratórnu techniku. A tak biológovia na tie bunky nepozerajú bežným mikroskopom ale rovno digitálnym mikroskopom. Taký digitálny mikroskop si môžete predstaviť ako digitálny fotoapárat s veľmi kvalitným „zoomom“ – umožňuje vyfotografovať či nakamerovať mikroskopické zábery. Aby bolo bunky lepšie vidieť, biológia si dopomáhajú rôznymi fluorescenčnými látkami alebo ožarovaním (preto sú bunky tak „do zelena“). Ale k veci. Vyučujúci poprosil Danielu a jej spolužiakov o pomoc pri vyhodnocovaní experimentu. Biológovia majú kopu záberov z mikroskopu, no pre samotné vyhodnotenie by potrebovali vedieť, koľko buniek je jednotlivých záberoch (keďže čas vzniku záberov poznajú, môžu tak určiť rýchlosť delenia buniek a jej závislosť od okolitých podmienok). Daniela aj spolužiaci súhlasili (veď kto by sa nechcel podieľať na takomto experimente) – a začali bunky na záberoch rátať. S každým ďalším záberom a každou ďalšou bunkou ich nadšenie (exponenciálne?) klesalo… 🙁
Ako také zábery vyzerajú, si môžete pozrieť na tomto obrázku:
Ďalšie mikroskopické zábery buniek nájdete v súbore: SkenyBuniek.zip (aj s počtom buniek, ktoré študenti na zábere napočítali)
A vtedy si Daniela uvedomila: veď ja viem predsa programovať! PAZ1a má za sebou, PAZ1b je ešte otvorené, no už všelijaké algoritmy a údajové štruktúry pozná. A nebolo by skvelé, ak by kolegom biológom ukázala, že informatike sa dnes už nevyhne asi žiaden vedecký odbor? Čo tak naprogramovať program, ktorý by zrátal počet buniek na zábere z digitálneho mikroskopu?
Obrázkov na spracovanie je veľa, niektoré sú oveľa väčšie ako tie na obrázku. Daniela je však znalá problematiky efektívnosti algoritmov. Rozhodla sa preto napísať program čo najefektívnejšie – v ideálnom prípade tak, aby pracoval v lineárnom čase (lepšie sa nedá, lebo na každý pixel obrázka sa musíme pozrieť aspoň raz).
Zadanie
Upravením triedy AnalyzatorSkenu
vytvorte triedu na analýzu záberov buniek z digitálneho mikroskopu. Kód analyzujúci vstupný obrázok umiestnite do metódy analyzuj
. Metódu pocetBuniek
upravte tak, aby vrátila počet buniek na obrázku. Pri analýze použitie tieto skutočnosti:
- metóda
jePixelBunky
vám povie, či pixel na zadaných súradniciach je pixelom bunky – využíva sa to, že obrázok je predspracovaný a pozadie má čiernu farbu, - rozmery načítaného obrázka sú v inštančných premenných
sirka
avyska
; platný rozsah indexov pre pixely v x-ovej súradnici je teda0, ..., (sirka-1)
a y-ovej súradnici je0, ..., (vyska-1)
, - žiadne dve bunky sa nedotýkajú (ak niečo vyzerá ako 2 zlepené bunky, tak to je v skutočnosti jedna bunka, ktorá je práve v procese delenia)
- pozor, bunka sa môže dotýkať aj niektorej zo strán obrázku a nemusí ju byť teda vidiet celú.
Trieda AnalyzatorSkenu
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
public class AnalyzatorSkenu {
/**
* Naskenovany obrazok
*/
private BufferedImage obrazok;
/**
* Sirka nacitaneho obrazka
*/
private int sirka;
/**
* Vyska nacitaneho obrazka
*/
private int vyska;
/**
* Hustota buniek - podiel plochy pokrytej bunkami k ploche skenu
*/
private double hustotaBuniek;
/**
* Vytvori novy analyzator skenu buniek a spusti zakladnu analyzu
*
* @param nazovSuboru
* nazov suboru so skenom buniek
*/
public AnalyzatorSkenu(String nazovSuboru) {
try {
obrazok = ImageIO.read(new File(nazovSuboru));
sirka = obrazok.getWidth();
vyska = obrazok.getHeight();
} catch (IOException e) {
System.err.println("Subor " + nazovSuboru
+ " sa nepodarilo nacitat.");
}
analyzuj();
}
/**
* Vrati, ci je pixel na suradniciach [x, y] pixelom bunky.
*/
private boolean jePixelBunky(int x, int y) {
Color pixel = new Color(obrazok.getRGB(x, y));
return !pixel.equals(Color.black);
}
/**
* Vypocita hustotu buniek
*/
private void vypocitajHustotuBuniek() {
int pocetBunkovychPixelov = 0;
for (int y = 0; y < vyska; y++)
for (int x = 0; x < sirka; x++)
if (jePixelBunky(x, y))
pocetBunkovychPixelov++;
hustotaBuniek = pocetBunkovychPixelov / ((double) sirka * vyska);
}
/**
* Realizuje zakladnu analyzu obrazka so skenom buniek
*/
private void analyzuj() {
vypocitajHustotuBuniek();
// ???
// ... dalsia analyza obrazku spustena po nacitani skenu
}
/**
* Vrati pocet buniek na obrazku
*/
public int getPocetBuniek() {
// ???
return 0;
}
/**
* Vrati hustotu buniek (pomer bunkovych pixelov k vsetkym pixelom)
*/
public double getHustotaBuniek() {
return hustotaBuniek;
}
public static void main(String[] args) {
AnalyzatorSkenu analyzator = new AnalyzatorSkenu("cellscan328371.png");
System.out.println("Hustota buniek: "
+ (analyzator.getHustotaBuniek() * 100) + " %");
System.out.println("Pocet buniek: " + analyzator.getPocetBuniek());
}
}
V triede AnalyzatorSkenu
nájdete aj metódu vypocitajHustotuBuniek
, ktorá demonštruje princíp práce s obrázkom ako aj použitie metódy jePixelBunky
. Táto metóda do inštančnej premennej hustotaBuniek
vypočíta pomer počtu pixelov, ktoré zachycujú nejakú bunku, k celkovému počtu pixelov obrázka. Inými slovami hustotaBuniek
určuje, aké percento plochy obrázka je pokryté bunkami.
Matemágia (max. 4 body)
Viete kto je David Copperfield? Áno, je to ten slávny iluzionista. Ale počuli ste už o Arthurovi Benjaminovi? Arthur Benjamin (okrem toho, že je profesorom matematiky) je aj matemagik. Jeho vystúpenie na TEDe si môžete pozrieť na stránke: https://www.ted.com/talks/arthur_benjamin_a_performance_of_mathemagic (len tak mimochodom, na TEDe nájdete kopu zaujímavých a inšpirujúcich prednášok a vystúpení). Pre nás bude najzaujímavejšia jeho demoštrácia, ktorá začína od 6 minúty. Arthur vyberie 4-ciferné číslo Y
, ktoré je druhou mocninou nejakého dvojciferného čísla X
, t.j. Y = X*X
(Y
je výsledok z úvodu jeho vystúpenia). Potom požiada náhodného diváka (teda až štyroch nezávisle), aby číslo Y
vynásobil akýmkoľvek 3-ciferným číslom (toto číslo nikomu neprezradí) – označme ho M
. Divákovi sa na kalkulačke zobrazí 6- alebo 7-ciferné číslo M*Y
. Arthur diváka požiada, aby mu prezradil ľubovoľných 5 resp. 6 cifier z čísla M*Y
v akomkoľvek poradí. Následne sa Arthur pokúsi uhádnuť chýbajúcu (divákom nepovedanú) šiestu, resp. siedmu cifru čísla M*Y
. Ako inak, Arthur chýbajúcu cifru uhádne. Ide však o šťastie alebo je za tým skrytá nejaká sofistikovaná matematika? Pre nás ako matematikov a informatikov, je to zaujímavá výzva, aby sme tento problém analyzovali.
Nech X
je dvojciferné číslo také, že X*X
je 4-ciferné číslo. Je pravdou, že pre každé 3-ciferné číslo M
platí, že ľubovoľných (v akomkoľvek poradí) 5, resp. 6 cifier čísla X*X*M
jednoznačne určuje zostávajúcu (šiestu resp. siedmu) cifru tohto čísla? Dokážte alebo nájdite kontrapríklad.
Ako odovzdávať riešenie:
- Ak je tvrdenie pravdivé, dôkaz v písomnej forme odovzdajte svojmu cvičiacemu. Ak pri dôkaze využijete aj nejaký program, jeho zdrojový kód nech je súčasťou dôkazu.
- Ak je tvrdenie nie je pravdivé, nájdite kontrapríklad (alebo kontrapríklady) ako trojicu
(X, M1, M2)
takú, že v číslachX*X*M1
aX*X*M2
, ktoré majú rovnaký počet cifier, možno vybrať takých 5 resp. 6 cifier, podľa ktorých tieto čísla nemožno rozlíšiť, resp. nemožno jednoznačne doplniť šiestu, resp. siedmu cifru. Príklad: Ak si zoberiete číslá3451
a5324
, tak tieto čísla nemožno rozlíšiť pomocou ľubovoľných 3 cifier. Totiž, ak nám niekto povie, že číslo obsahuje cifry345
, nevieme, či to je číslo4351
alebo5324
– a teda nevieme, či máme doplniť číslo1
alebo2
. Za každý nájdený kontrapríklad je 0.1 boda. Ak pri hľadaní kontrapríkladov využijete nejaký program, jeho zdrojový kód musí byť súčasťou riešenia. Ak pri hľadaní kontrapríkladov sa budete opierať o nejaké matematické tvrdenia a kombinatoriku, popis postupu hľadania kontrapríkladov musí byť súčasťou riešenia (odovzdáva sa v písomnej forme).
Ako odovzdávať riešenie cez Moodle:
- Moodle dovoľuje k tejto úlohe odovzdať 2 súbory. Prvý je akýkoľvek súbor, ktorý obsahuje popis vášho riešenia (podporný zdrojový kód, dôkazy, …). Druhý je textový súbor
kontrapriklady.txt
. Evaluátor obsahuje test, či zadané trojice čísel predstavujú kontrapríklady (otestovať, či niečo spĺňa zadané vlastnosti je možné aj bez toho, aby ste vedeli, či vôbec existuje objekt s týmito vlastnosťami). Formát súborukontrapriklady.txt
: v každom riadku sa očakáva jeden kontrapríklad zadaný ako trojica medzerami oddelených číselX
,M1
aM2
.