Úloha 118: Vylepšení histogramu

Úkolem je implementovat nějakou zajímavější variantu histogramu rastrového obrázku, jehož pilotní verze je součástí projektu 117raster

Screenshot

Základ

Budete pracovat v prostředí projektu 117raster z repository grcis (GIT). Je připravena aplikace, jejíž popis je na této stránce

Svoji novou třídu (třídy) umístíte do zvláštního adresáře a řešení na konci odevzdáte tak, že zazipujete tento adresář a pošlete mailem jako přílohu. Můžete přidat/vylepšit i formulář[e]... Jen nezasahujte do zdrojových souborů projektu 117raster.

Pro všechny Vaše nové třídy použijte prosím "namespace" obsahující Vaše jméno, např. namespace JanVoprsalek;.

Pokud byste narazili na nějakou překážku (a měli nutkání základ projektu upravovat), radši mne okamžitě kontaktujte a opravíme to společně, aby z toho měli užitek i kolegové/kolegyně.

Pilotní verze

Jednoduchý globání histogram je implementován jako modul (viz interface IRasterModule) a umístěn v adresáři 117raster/ModuleHistogram. Tam najdete několik souborů, o kterých si teď napíšeme podrobněji:

Histogram.cs – obsahuje třídu ImageHistogram, která implementuje výpočet histogramu a vykreslování jeho grafu. Histogram se počítá z celého obrázku a algoritmus výpočtu je naivní (dva for-cykly v sobě a čtení pixelu funkcí Bitmap.GetPixel(x, y), což je velmi pomalé). Čtyři režimy umějí uvažovat stupně šedi nebo jednotlivé barevné kanály R, G, B.
Vykreslování grafu histogramu je implementováno ve funkci DrawHistogram(Bitmap). Základní myšlenkou je, že se grafika kreslí do záložní bitmapy ("back-buffer"), která je přesně naškálována na velikost vizualizačního okna a při pozdějším vykreslování systémem Windows (událost Paint) se již pak beze změny použije tato předem připravená záložní bitmapa. Překreslovat graf/grafy je potřeba jedině po změně velikosti vizualizačního okna (událost Resize). Překreslování grafů je výpočetně mnohem méně náročné než sbírání dat histogramu, proto jsou tyto dvě fáze od sebe odděleny a je umožněno provádět je samostatně a efektivně – např. při změně velikosti okna jen překreslovat grafy a pouze v případě, že se změnila vstupní data nebo parametry výpočtu se bude přepočítávat celý histogram.

HistogramForm*.cs – jednoduché visualizační okénko, které vykresluje svůj obsah pomocí záložní bitmapy ("back-buffer"), kterou připraví někdo jiný – typicky modul IRasterModule. Reaguje jen na události Paint, Resize a FormClose, v posledním případě umí upozornit připojený výpočetní modul, že bylo okno zavřeno (např. uživatelem = myší). Výpočetní modul je rovněž upozorněn na změnu velikosti okénka (je vyvoláno překreslení grafiky).

Ukázkový modul ModuleHistogram.cs – implementace třídy ModuleGlobalHistogram. Splňuje všechny náležitosti rastrového modulu (IRasterModule) a přitom implementuje jen minimální sadu položek, ve kterých se liší od předka DefaultRasterModule. Používá výpočetní třídu ImageHistogram a visualizační okénko HistogramForm. Třída ModuleGlobalHistogram může sloužit jako ukázka snadné implementace nového rastrového modulu.

Náměty na rozšíření

Lokální histogram – modul bude histogram přepočítávat v metodě PixelUpdate(x, y) a bude ho počítat jen z nějakého omezeného okolí daného pixelu obrázku [x, y]. Velikost (nebo i tvar) okolí by měly jít konfigurovat přes textové parametry Param. Pozn: PixelUpdate(x, y) se v hlavním programu volává stiskem Ctrl + levého tlačítka myši.

HSV histogram – četnosti barev budou počítány v jiném barevném prostoru (HSV) a visualizovány jinou formou (v barevném kruhu HSV). K převodu z RGB do HSV můžete použít funkci ColorToHSV() podle vzoru:

 Color col = image.GetPixel(x, y);
 double H, S, V;
 Arith.ColorToHSV(col, out H, out S, out V);

Lepší visualizace histogramů – kreslení více grafů do jednoho obrázku, doplnění popisků, okótování souřadnicových os, apod. Budete se pravděpodobně muset seznámit s některými pokročilejšími funkcemi kreslení GDI+: Graphics Class.

Textové parametry Param

Analýza parametrů z textového pole "Param" – s výhodou můžete použít funkce z pomocné knihovny Util: funkce Util.ParseKeyValueList(param); nejprve rozdělí text na úseky oddělené čárkami a v nich se poté mohou hledat definice ve tvaru <key>=<value>. Funkce bool Util.TryParse(p, "name", ref val) vrací true pokud byl daný klíč nalezen a současně je přepsána hodnota parametru val.

Co odevzdat

Svoji novou třídu – modul (potomka DefaultRasterModule) a příp. další třídy, které jste implementovali, umisťujte do zvláštního adresáře a řešení na konci odevzdejte tak, že zazipujete celý tento adresář a archiv pošlete svému cvičícímu mailem jako přílohu. Můžete přidat/vylepšit i formulář[e]... Nezasahujte do zdrojových souborů projektu 117raster.

Pro všechny Vaše nové třídy použijte prosím "namespace" obsahující Vaše jméno, např. namespace JanVoprsalek;.

Ještě jinak řečeno: Vámi odevzdané řešení musí být kompatibilní s projektem 117raster tak, že až se do 117raster.csproj přidají Vaše soubory (váš adresář), bude v systému viditelný a použitelný Váš nový modul (Vaše nové moduly).

Termín

Odevzdat do: 10. 11. 2019

Body

Základ: 5 bodů za netriviální úpravu,
7 bonusových bodů za nápaditost a složitost rozšíření.

Projekt

Visual Studio projekt: 117raster

Zdrojový soubor

Zazipovaný podadresář, který lze zapojit do projektu 117raster.


Copyright (C) 2019 J.Pelikán, last change: 2019-11-04 13:51:40 +0100 (Mon, 04 Nov 2019)