6. Показ довільних растрових зображень.
Довільне зображення на екрані комп'ютера являє собою масив пікселів, кожен з яких характеризується своїм кольором. Колір пікселя визначається трьома складовими: червоним, зеленим і синім (Red, Green, Blue - RGB). Для завдання величини складової кольору пікселя досить одного байта пам'яті (8 бітів), де можна записати цілі числа від нуля до 255 (всього 256 значень).
Отже, кожному пікселю екрану повинні відповідати три цілих числа в діапазоні від 0 до 255. У системі MATLAB таким цілим числам відповідає тип даних, що позначається як uint8. Під такий тип даних відводиться в пам'яті всього один байт, замість 8 байт для звичайних речових (дрібних) чисел типу double. За замовчуванням будь-якої змінної в системі MATLAB ставиться у відповідність тип double незалежно від числових значень, які ви привласнюєте змінним.
Наприклад, в результаті наступного рядка коду
створюється змінна з ім'ям iVar1 і типом double, якій присвоюється значення 128. Для зберігання такого значення досить одного байта пам'яті, однак для змінної iVar1 типу double відводиться 8 байт пам'яті. У наявності явний перевитрата пам'яті комп'ютера.
Щоб уникнути такого перевитрати змінну потрібно явно оголошувати як цілу, використовуючи модифікатор uint8:
Так створена змінна iVar2 вважається цілої змінної (а не речової), і під неї відводиться один байт пам'яті. Такі змінні в системі MATLAB спеціально призначені для зберігання цілих значень від 0 до 255 (з метою економії пам'яті) і не призначені для обчислень! По-крайней мере в версії MATLAB 5.2 це ще так. В результаті для наступного фрагмента
отримуємо повідомлення про помилку:
. Function '+' not defined for variables of class 'uint8'.
Дослівно означає, що операція "складання" для змінних типу uint8 не визначена.
Щоб дізнатися (якщо забули), який тип має та чи інша змінна з робочого простору системи MATLAB, потрібно ввести і виконати команду
в результаті в командному вікні MATLABа з'явиться наступне повідомлення:
з якого видно, що iVar1 є масивом розміру 1x1 (тобто фактично скаляром) типу double і займає в пам'яті 8 байт, а iVar2 має тип uint8 і займає в пам'яті тільки 1 байт (в 8 разів менше). При цьому обидві змінні мають однакові значення.
Деякий набір квітів (в кількості m штук), званий палітрою або colormap, можна оформити у вигляді матриці розміром m x 3 типу double. Наприклад, матриця map1
map1 (1,1) = 0.12; map1 (1,2) = 0.123; map1 (1,3) = 0.987;
map1 (4,1) = 0.255; map1 (4,2) = 0.298; map1 (4,3) = 0.128;
задає набір з п'яти кольорів. Кожен рядок відповідає одному кольору. Елементи рядка (зліва - направо) задають червону, зелену і синию складові кольору.
Далі сформуємо матрицю k x L типу uint8, кожен елемент якої буде дорівнює одному з номерів (мінус одиниця) рядків таблиці кольорів map1. Такий матриці разом з матрицею квітів буде досить, щоб показати на екрані комп'ютера масив пікселів, тобто довільне зображення.
Наприклад, матриця X1
X1 = uint8 ([1 4 1 3 2; 4 0 2 1 3])
задає масив типу uint8 розміром 2 x 5 піксель. Цей масив всього займає в пам'яті 10 байт, а не 80 байт, як було б у випадку масиву типу double. Перший піксель в першому ряду має колір, що задається другим рядком матриці map1, другий піксель в цьому ж ряду відповідає п'ятому рядку матриці map1, і так далі.
Щоб змусити систему MATLAB реально відобразити довільну картину пікселів, потрібно викликати функцію image.
Наприклад, за допомогою функцій
створюється графічний об'єкт Image системи MATLAB, якому в графічному вікні MATLABа відповідає реальне зображення:
Оскільки ми не управляємо розміром графічного вікна системи MATLAB, то воно з'являється на екрані з деяким розумним розміром, заданим за замовчуванням. Далі, так як наше зображення складається з двох рядів по п'ять піксель в кожному, а це дуже дрібне зображення (фізичний розмір пікселя екрану приблизно дорівнює 0.2 мм), то MATLAB за замовчуванням встановлює масштаб його (збільшує), щоб можна було розгледіти це зображення. Якщо потрібно скасувати таке масштабування, то слід вказати явно потрібні розміри:
figure ( 'Units', 'pixels', 'Position', [100 100 n m]);
Тут розміри m і n зображення X1 нав'язуються в якості фізичного розміру картинки в графічному вікні системи MATLAB. Для надто маленьких картинок при цьому нічого доброго не вийде.
Якщо ми не будемо створювати нові зображення, маніпулюючи явно матрицями, а будемо намагатися відобразити в графічному вікні системи MATLAB вже готові картинки, записані в файлах, то тоді нам буде потрібно прочитати вміст цих файлів функцією imread. Зокрема, раніше ми записували тривимірні зображення в файли за допомогою функції imwrite. Тепер їх можна прочитати
і показати в графічному вікні. Зауважимо тільки, що файл повинен бути в поточному каталозі системи MATLAB, інакше його потрібно вказати разом з повним шляхом до нього.
Розглянуте нами будова даних для об'єкта Image, що складається з двох матриць, одна з яких через підрядник задає кольори, а друга своїми елементами вказує входи в таблицю (матрицю) квітів, називається більш точно як Indexed Image (індексовані зображення). Є й інший тип об'єкта Image - так званий Truecolor Image (картинки з дуже великою кількістю квітів - до 16 мільйонів). Цей другий тип об'єктів Image влаштований по-іншому.
Для TruecolorImage- об'єктів таблиця кольорів не потрібно, так як масиви даних таких об'єктів безпосередньо визначають кольору.
Ці масиви мають розмір m x n x 3 (це масиви розмірності 3). Величини m і n визначають розмір картинки на екрані (m x n пікселів), а вздовж третього напряму розташовуються RGB-складові кольору кожного пікселя. Задамо для прикладу наступний масив для зображення TrueColor:
xTrue (1,1,1) = uint8 (127); xTrue (1,1,2) = uint8 (127); xTrue (1,1,3) = uint8 (127);
xTrue (1,2,1) = uint8 (19); xTrue (1,2,2) = uint8 (12); xTrue (1,2,3) = uint8 (255);
xTrue (1,3,1) = uint8 (245); xTrue (1,3,2) = uint8 (127); xTrue (1,3,3) = uint8 (1);
xTrue (2,1,1) = uint8 (6); xTrue (2,1,2) = uint8 (203); xTrue (2,1,3) = uint8 (128);
xTrue (2,2,1) = uint8 (100); xTrue (2,2,2) = uint8 (1); xTrue (2,2,3) = uint8 (80);
xTrue (2,3,1) = uint8 (60); xTrue (2,3,2) = uint8 (249); xTrue (2,3,3) = uint8 (5);
Масив xTrue створює зображення 2 x 3 пікселя за допомогою виклику однієї функції image (xTrue):
У разі TrueColor зображень тут матриця X отримає розмір m x n x 3 а матриця палітри map буде порожній:
Надалі функція image автоматично за розміром матриці X розпізнає типи зображень і діє в обох випадках як треба, а функція colormap в разі порожнього масиву map не робить нічого, так що обидва ці випадки можуть бути оброблені однаково.
Однак, якби ми заздалегідь знали, що в файлі міститься зображення типу TrueColor, то ми б виконували для його читання більш короткий код
а показували б зображення викликом тільки однієї функції image (X). Щоб заздалегідь дізнатися тип зображення в файлі, потрібно викликати функцію
Зокрема для файлу 'myfile1.jpg', створеного в попередньому розділі даного посібника, функція imfinfo видасть наступну інформацію:
Звідси видно, що тип зображення в файлі (ColorType) є truecolor. Це означає, що можна повністю обійтися без матриці кольорів.