Н.Ш. Хусаинов Руководство к набору...

60
УДК 681.3.06 У912 МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ КАФЕДРА МАТЕМАТИЧЕСКОГО ОБЕСПЕЧЕНИЯ И ПРИМЕНЕНИЯ ЭВМ Государственное образовательное учреждение высшего профессионального образования "Южный федеральный университет" Технологический институт Южного федерального университета в г.Таганроге Работа выполнена в соответствии с Программой развития Южного федерального университета на 2007-2010гг. Н.Ш. Хусаинов Руководство к набору лабораторных работ на тему КОДИРОВАНИЕ ИЗОБРАЖЕНИЙ С ИСПОЛЬЗОВАНИЕМ ПАКЕТА MATLAB по курсу "Теория кодирования информации" Для студентов специальностей 230105 Программное обеспечение вычислительной техники и автоматизированных систем 010503 Математическое обеспечение и администрирование информационных систем Таганрог 2008

Upload: others

Post on 08-Jul-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

УДК 681.3.06 У912

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

КА

ФЕД

РА

МА

ТЕМ

АТИ

ЧЕС

КО

ГО О

БЕС

ПЕЧ

ЕНИ

Я И

ПР

ИМ

ЕНЕН

ИЯ

ЭВ

М

Государственное образовательное учреждение высшего профессионального образования

"Южный федеральный университет"

Технологический институт Южного федерального университета в г.Таганроге

Работа выполнена в соответствии с Программой развития Южного федерального университета на 2007-2010гг.

Н.Ш. Хусаинов

Руководство к набору лабораторных работ на тему

КОДИРОВАНИЕ ИЗОБРАЖЕ НИЙ С ИСПОЛЬЗОВАНИЕМ ПАКЕТА MATLAB

по курсу "Теория кодирования информации"

Для студентов специальностей

230105 – Программное обеспечение вычислительной техники и автоматизированных систем

010503 – Математическое обеспечение и администрирование информационных систем

Таганрог 2008

Page 2: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

2

УДК 681.3.06 (076.5) + 681.325.5. (076.5)

Хусаинов Н.Ш. Руководство к набору лабораторных работ "Кодирование изображений с

использованием пакета MATLAB" по дисциплине “Теория кодирования информации".– Таганрог:

ТТИ ЮФУ, 2008. 60с.

Руководство включает две лабораторных работы. Первая нацелена на знакомство со средой

MATLAB, приобретение базовых практических навыков работы с оболочкой пакета, изучение

принципов обработки данных и построения программ на языке MATLAB. Кратко приводятся

поддерживаемые типы данных, иерархия графических объектов и объектов пользовательского

интерфейса, особенности выполнения вычислительных операций над данными,

представляемыми в виде матриц.

Вторая лабораторная работа посвящена разработке программы эффективного кодирования

изображений. Организация пользовательского интерфейса и выполнение процедур кодирования

и декодирования данных проиллюстрированы на приведенном примере программы на языке

MATLAB. Приведены варианты задания для выполнения лабораторной работы.

Пособие предназначено для студентов специальностей 220400, 351500, изучающих курс

"Теория кодирования информации". Представляет интерес для инженеров, разработчиков и

программистов в области систем обработки и кодирования текстовой, аудио- и визуальной

информации.

© Технологический институт

Южного федерального университета в г.Таганроге, 2008г.

© Н.Ш.Хусаинов, 2008г.

Page 3: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

3

СОДЕРЖАНИЕ

Лабораторная работа 1. Выполнение базовых вычислительных операций в среде MATLAB .........

Введение .........................................................................................................................................................

Состав интегрированной среды MATLAB .....................................................................................................

Краткие сведения об интерфейсе среды MATLAB ......................................................................................

Разработка пользовательского интерфейса для программ на языке MATLAB ........................................

Основы программирования на языке MATLAB ...........................................................................................

Примеры реализации простейших алгоритмов обработки векторных и матричных данных

средствами MATLAB .......................................................................................................................................

Способы оценки производительности и повышения эффективности программ на языке MATLAB .....

Вопросы для самопроверки ..........................................................................................................................

Контрольные задания ....................................................................................................................................

Список использованных источников к лабораторной работе № 1 ...........................................................

Лабораторная работа 2. Реализация и исследование алгоритма компрессии изображений ...........

Основные требования к выполнению работы ............................................................................................

Общие требования к содержанию отчета по лабораторной работе ........................................................

Пример. Разработка программа кодирования изображения по алгоритму JPEG ................................... Задания на лабораторную работу ................................................................................................................

Page 4: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

4

ЛАБОРАТОРНАЯ РАБОТА 1. ВЫПОЛНЕНИЕ БАЗОВЫХ ВЫЧИСЛИТЕЛЬНЫХ ОПЕРАЦИЙ В СРЕДЕ

MATLAB

Цель работы – знакомство со средой MATLAB, изучение основных принципов организации

вычислений.

Основными задачами, стоящими при выполнении данной лабораторной работы, являются:

- изучение состава интегрированной среды MATLAB и приобретение навыков работы с

командным окном, рабочим пространством, текстовым редактором;

- выполнение простейших операций по созданию, инициализации и преобразованиям

матриц и векторов, доступа к элементам массивов средствами языка MATLAB;

- знакомство с иерархией классов вычислительных объектов (типов данных) и графических

объектов MATLAB;

- организация программных конструкций с использованием операторов управления

программой, оформление модулей MATLAB в виде файлов-сценариев и файлов-функций;

- знакомство со способами оценки производительности программного кода в среде MATLAB

и методами повышения эффективности программ.

Введение

MATLAB (MATrix LABoratory) – интегрированная среда, объединяющая в себе средства для

численных расчетов, моделирования, графические возможности и встроенный язык

программирования высокого уровня MATLAB.

Первоначальной целью при создании MATLAB было обеспечение доступа к программным

библиотекам LINPACK и EISPACK, которые были написаны на Фортране и являлись на тот момент

самыми современными средствами матричных вычислений. Собственно, язык

программирования MATLAB был разработан Кливом Моулером (Cleve Moler) в конце 1970-х

годов, когда он был деканом факультета компьютерных наук в Университете Нью-Мексико. Целью

разработки служила задача дать студентам факультета возможность использования библиотек

LINPACK и EISPACK без необходимости изучения Фортрана. Вскоре новый язык распространился

среди других университетов и был с большим интересом встречен учёными, работающими в

области прикладной математики.

В 1984г. Клив Моулер вместе с инженерами Стивом Бангертом (Steve Bangert) и Джоном

Литтлом (John N. (Jack) Little) основали компанию "The MathWorks" с целью "перенести" средства

и языки математического и технического программирования, созданные к тому времени для

суперкомпьютеров, на персональные компьютеры, сделав их коммерчески выгодным проектом.

Первые 10 копий MATLAB (переведенного к тому времени с Фортрана на Си) были приобретены

Масачусетским технологическим институтом по цене 500 долларов за экземпляр. Последующие

версии MATLAB вышли в 1987 (MATLAB 2.0) и в 1991 (MATLAB 4.0) годах соответственно. В состав

интегрированной среды MATLAB 4.0 был включен пакет Simulink (называвшийся сначала

Page 5: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

5

SIMULAB), предназначенный для изучения и моделирования динамических систем, а также

добавлены средства для визуализации данных и результатов расчетов [1].

На сегодняшний день MATLAB насчитывает более 1 млн. пользователей. Основными

покупателями пакета являются компании, занятые высокотехнологичными разработками, научно-

исследовательские центры, финансовые организации и, конечно же, университеты [2].

MATLAB используется во множестве областей, среди которых обработка сигналов и

изображений, проектирование систем управления и связи, финансовые расчеты и медицинские

исследования. Его открытая архитектура делает возможным использование MATLAB и

сопутствующих продуктов для исследования данных и создания собственных инструментов,

использующих функциональные возможности MATLAB *3].

Сегодня MATLAB – платформонезависимый высокоуровневый язык для технических

вычислений и интерактивная среда для разработки алгоритмов, численных вычислений, анализа

и визуализации данных. MATLAB находит применение для самого широкого спектра приложений,

включая обработки сигналов и изображений, связь, системы управления, тестирование

оборудования, финансовые расчеты и медицинские исследования. Наборы дополнительных

инструментов (toolboxes) расширяют возможности среды MATLAB и позволяют решать

конкретные практические задачи. Кроме того, MATLAB также предоставляет возможности по

интегрированию разработанных алгоритмов и программ с внешними приложениями и языками

программирования (Microsoft Excel, .NET, COM, C/C++, Java) [3].

Состав интегрированной среды MATLAB

Базовыми компонентами среды MATLAB являются [4]

1) интегрированная среда MATLAB, которая включает пять составляющих:

- среда разработки (рабочий стол, окно команд, окно истории, рабочее пространство,

редактор, отладчик, система помощи);

- библиотека базовых математических функций (от элементарных, типа

сложения/вычитания, до более сложных, например, вычисление обратной матрицы или

реализация быстрого преобразования Фурье);

- язык MATLAB (высокоуровневый язык программирования, ориентированный на обработку

векторов/матриц и содержащий большинство стандартных конструкций современных языков

программирования, в том числе объектно-ориентированных);

- подсистема графики (содержит высокоуровневые функции для отображения двух- и

трехмерных данных, графиков, изображений, видео, анимации, деловой графики и

низкоуровневые функции, позволяющие разработать собственный графический интерфейс

приложения);

- программный интерфейс MATLAB API (библиотека, позволяющая писать программы на

языках С/С++, которые могут затем взаимодействовать с MATLAB. Библиотека содержит средства

для вызова динамических подпрограмм (ddl) из MATLAB, вызова функций MATLAB для

выполнения вычислений, чтения/записи данных в рабочем пространстве и файлах данных

MATLAB.

Page 6: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

6

Важная роль в MATLAB отводится коллекциям специализированных функций (Toolboxes),

которые позволяют решать частные классы задач.

2) пакет моделирования Simulink – интерактивная среда для моделирования, имитации и

анализа динамических систем в самых разных прикладных областях. Она позволяет

проектировать модели на основе блоков, моделировать поведение системы, оценивать ее

производительность и уточнять модель по результатам оценок. Основное предназначение

Simulink – описание динамических систем, поведение которых можно представить как функцию от

времени. Simulink глубоко интегрирован с MATLAB, что обеспечивает разработчику

непосредственный доступ ко всем средствам обработки и анализа данных MATLAB. Особое

значение при создании моделей имеет библиотека проблемно-ориентированных наборов блоков

(Blocksets), реализующих специфичные для той или иной области алгоритмы обработки.

3) пакет Stateflow – интерактивный инструмент проектирования для создания и

моделирования систем на основе событийного подхода. Используя предоставляемые средства

разработчик может описывать поведение исследуемой системы как цепочку правил "если-то".

Основой построения и исследования моделей в среде Stateflow является теория конечных

автоматов. Совместное использование Simulink и Stateflow позволяет описать логику

функционирования и создать виртуальный прототип практически любой системы.

Множество входящих в MATLAB дополнительных средств (всего около 100 пакетов) по

своему назначению можно разбить на следующие категории:

- организация параллельных вычислений на нескольких ЭВМ локальной сети,

организованных в вычислительный кластер), где установлен MATLAB с соответствующими

пакетами (Parallel Computing Toolbox, MATLAB Distributed Computing Server);

- математические вычисления и решение оптимизационных задач (Optimization Toolbox,

Symbolic Math Toolbox, Partial Differential Equation Toolbox и др.);

- статистическая обработка и анализ данных (Statistics Toolbox, Neural Network Toolbox, Spline

Toolbox и др.);

- проектирование, анализ систем управления, моделирование систем управления (Control

System Toolbox, Robust Control Toolbox, Aerospace Toolbox, Simulink Control Design, Simulink

Parameter Estimation, Aerospace Blockset и др.);

- обработка сигналов и связь, моделирование систем связи и обработки сигналов (Signal

Processing Toolbox, Communications Toolbox, Filter Design Toolbox, Wavelet Toolbox, Fixed-Point

Toolbox, RF Toolbox , Signal Processing Blockset, Communications Blockset, Video and Image Processing

Blockset и др.);

- обработка изображений (Image Processing Toolbox, Mapping Toolbox и др.);

- измерения и тестирование (Data Acquisition Toolbox, Instrument Control Toolbox и др.);

- вычислительная биология (Bioinformatics Toolbox, SimBiology);

- финансовое моделирование и анализ (Financial Toolbox, Fixed-Income Toolbox, Datafeed

Toolbox и др.);

- компьютерная графика (Virtual Reality Toolbox, Gauges Blockset);

- моделирование физических процессов (Simscape, SimMechanics, SimPowerSystems,

SimElectronics и др.);

Page 7: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

7

- разработка приложений (MATLAB Compiler, Spreadsheet Link EX (for Microsoft Excel), MATLAB

Builder NE (for Microsoft .NET Framework и др.);

- генерация кода для выполнения в других исполнительных средах (Real-Time Workshop,

Real-Time Embedded Coder и др.);

- "быстрое" моделирование на целевой платформе (xPC Target, Real-Time Windows Target,

Target Support Package for TC6 (for TI's C6000 DPP), Embedded IDE Link VS (for Analog Devices

VisualDSP++) и др.);

- работа с базами данных и генерация отчетов (Database Toolbox, MATLAB Report Generator);

- верификация, валидация и тестирование (Simulink Verification and Validation, SystemTest,

PolySpace Code Verification Products).

Краткие сведения об интерфейсе среды MATLAB

При запуске MATLAB на экране появляется главное окно программы – рабочий стол,

содержащий инструменты для работы с файлами (Current Directory), переменными рабочей

области (Workspace), интерактивного выполнения команд (Command Window), окна истории

команд (Command History), главного меню, панели инструментов, панели ссылок (Shortcuts) и

кнопки запуска "Start" (аналогичной по своему функциональному назначению кнопке "Start" в ОС

Windows) – как показано на рисунке 1.1.

Рисунок 1.1 – Рабочий стол MATLAB сразу после запуска приложения

Одним из основных достоинств MATLAB является то, что для работы пользователю

достаточно знать о нем ровно столько, сколько требует решаемая задача *5+. Если задача требует

Page 8: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

8

использования каких-либо специальных инструментов, то пользователю предоставляется в

распоряжение практически универсальный язык объектно-ориентированного программирования

в сочетании с интерактивными средствами отладки создаваемых программ. А в простейшем

случае MATLAB может сыграть роль простого калькулятора или средства для визуализации

значений переменных или файлов, как показано на рисунке 1.2.

Рисунок 1.2 – Отображение значения переменной y, содержащей отсчеты звукового файла, в

редакторе переменных (Variable Editor) и в виде графика

Выполнять любые команды и функции MATLAB можно посредством окна Command Window

рабочего стола MATLAB. Однако при написании более сложных программ, которые хранятся в m-

файлах, целесообразно пользоваться встроенным редактором среды MATLAB (см. рисунок 1.3).

Редактор MATLAB обладает мощными возможностями для написания, отладки и анализа

программного кода. Средства, облегчающие набор программы и контроль синтаксиса стандартны

для современных средств разработки программ. Дополнительным средством, которое

автоматически проверяет фрагменты программы на предмет наличия потенциальных ошибок и

оценки эффективности выполнения, является средство анализа M-Lint Code Check.

Для повышения эффективности отладки и анализа программ кроме использования

стандартных средств (условные и безусловные точки останова, просмотр значений переменных,

профилирование) может использоваться механизм "быстрого" выполнения фрагмента программы

Rapid Code Iteration Using Cells. Он позволяет выполнить оформленный специальным образом

фрагмент, не выполняя остальной код программы. Разбив всю программу на такие фрагменты

(называемые "ячейками" (Cells) кода), можно последовательно выполнять отладку программу, не

прибегая к использованию точек останова.

Page 9: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

9

Рисунок 1.3 – Окно редактора m-файлов среды MATLAB

Для разработки пользовательского интерфейса (если это необходимо для решаемой задачи)

MATLAB содержит инструмент GUIDE, вызываемый из главного меню MATLAB (кнопка Start) и

позволяющий создавать экранные формы с набором стандартных элементов управления (кнопка,

текстовая метка, поле для ввода, список, таблица, кнопки для выбора, поле для отображения

графики и др.). Поля, связанные с каждым элементом управления и самой формой, можно

редактировать с помощью Property Inspector. Описание формы и элементов управления хранится

в файле с расширением ".fig". По аналогии с традиционными языками высокого уровня для

каждой формы MATLAB автоматически генерирует m-файл с тем же именем, в котором находятся

"главная" функция, отвечающая за прорисовку экранной формы, а также callback-функции,

отвечающие за обработку событий, генерируемых элементами управления на форме.

Подробное описание среды разработки MATLAB, оконного интерфейса и возможностей

редактора приведены в *6,7].

В MATLAB используются несколько стандартных расширений файлов:

- m-файлы (с расширением .m) – файлы, содержащие тексты программ на языке MATLAB.

Есть два типа m-файлов: файлы-сценарии и файлы-функции. Файл-сценарий, именуемый также

Script-файлом, является просто записью серии команд без входных и выходных параметров. Файл-

функция содержит входные и выходные параметры, использует аппарат локальных переменных и

поэтому является типичным объектом языка программирования системы MATLAB и полноценным

модулем с точки зрения структурного программирования;

- fig-файлы – файлы с описанием оконных форм (Figure) пользовательского интерфейса,

обычно используются в программах на MATLAB;

- mdl-файлы – файлы моделей Simulink;

Page 10: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

10

- p-файлы – промежуточные файлы, содержащие скомпилированный код процедур MATLAB.

Использование p-файлов обычно существенно повышение быстродействие по сравнению с

выполнением (интерпретированием) m-файлов и позволяет защитить от несанкционированного

доступа содержание программного кода;

- mat-файлы – файлы, содержащие данные в двоичном коде (обычно значения каких-либо

переменных), доступ к которым возможен из командного окна MATLAB либо с помощью

специальных средств Simulink. Подробное описание формата mat-файла приведено в *8].

Разработка пользовательского интерфейса для программ на языке MATLAB

Графический интерфейс пользователя (Graphical User Interface, GUI) предоставляет

пользователю возможность интерактивной обработки данных в приложении посредством

оконной формы. Основными элементами управления GUI на форме являются меню, панель

инструментов, кнопки различных типов, списки и т.д. GUI может отображать данные в виде таблиц

и графиков или изображений.

Разработка пользовательского интерфейса средствами GUIDE

Для создания элементов пользовательского интерфейса используется встроенная в MATLAB

оболочка GUIDE, которая в интерактивном режиме позволяет добавлять на форму элементы

управления, контролировать и изменять их размер, порядок, выравнивание. При первом

сохранении макета экранной формы GUIDE автоматически генерирует m-файл, содержащий код

инициализации формы, а также процедуры для вызова, визуализации и закрытия экранной

формы.

Пример экранной формы, созданной в GUIDE, приведен на рисунке 1.4. По аналогии с

другими современными средами разработки программ, управление полями элементов формы в

GUIDE осуществляется с использованием окна редактора свойств (Inspector). GUIDE также

выполняет генерацию шаблонов (заголовков и минимума кода) для callback-процедур по

необходимому событию.

Подробнее средства создания пользовательского интерфейса в MATLAB средствами GUIDE

описаны в *9+.

Page 11: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

11

Рисунок 1.4 – Окно GUIDE с созданной экранной формой

Виды графических объектов MATLAB

Иерархия графических объектов MATLAB приведена на рисунке 1.5. Основным объектом

пользовательского интерфейса в MATLAB является оконная форма (Figure), которая может

содержать как объекты пользовательского интерфейса (UI objects), так и "рисованные"

графические объекты. Объект Figure, в свою очередь является потомком объекта Root, события и

свойства которого позволяют работать с некоторыми глобальными установками MATLAB.

Page 12: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

12

Root

Figure

AxesUI Objects Hidden Annotation Axes

Core

Objects

Plot

Objects

Group

Objects

Annotation

Objects

image

light

line

patch

rectangle

surface

text

checkbox

edit

text

uitable

listbox

popupmenu

pushbutton

radiobutton

togglebutton

slider

Container

Objects

Primary

Objects

ActiveX

Object

uipanel

uibuttongroup

areaseries

barseries

contourgroup

errorbarseries

lineseries

quivergroup

scattergroup

stairseries

stemseries

surfaceplot

UI Control

Objects

UI Menu

Object

UI Toolbar

Object

UI ContextMenu

Object

Рисунок 1.5 – Иерархия графических объектов MATLAB

Графические объекты MATLAB можно разделить на два больших подмножества:

- core graphics objects – базовые графические объекты (графические примитивы), которые

используются высокоуровневыми функциями рисования и составными объектами (composite

objects) для создания различного вида графиков и диаграмм (см. рисунок 1.6). Графические

примитивы являются потомками объекта axes (оси), который задает двумерную или трехмерную

систему координат для отображаемых данных. К графическим примитивам относятся такие

объекты, как image ("изображение"; используется для отображения двумерной числовой

матрицы, при этом значения элементов матрицы соответствуют цвету пиксела), light ("источник

света", определяет направление источника света для полигонов и поверхностей; сам объект light

не виден на экране), line ("линия", соединяет задающие ее точки), patch("закрашенный полигон",

может содержать грани, с различными параметрами окрашивания), rectangle ("прямоугольник",

двумерный объект с задаваемыми параметрами границы, заливки и степени кривизны, позволяет

рисовать окружности и эллипсы), surface ("поверхность", элемент трехмерной сетки из

четырехугольников, образуемых путем отображения значения элемента двумерной матрицы в

виде высоты над плоскостью рисования), text ("текст", строка символов в системе координат

осей). Работа с графическими примитивами относится к категории дескрипторной

("низкоуровневой") графики MATLAB;

- composite objects – "сложные" графические объекта, составленные из нескольких

сгруппированных базовых объектов для создания более удобного и функционального

интерфейса.

Page 13: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

13

Рисунок 1.6 – Примеры базовых графических объектов

Составные объекты образуют базис для четырех подтипов графических объектов:

- plot objects (графики) – объединяют некоторые базовые графические объекты, но имеют

дополнительные общие свойства для графиков. Работа с методами plot-объектов относится к

"высокоуровневой" графике. При визуализации данных с использованием "высокоуровневых"

функций графики и изображения либо строятся каждый раз в новом окне (с параметрами

отрисовки, установленными по умолчанию), либо выводятся в имеющийся объект axes с

предварительным удалением всех объектов, ранее связанных с axes и сбросом параметров

объекта axes в значения по умолчанию. При отображении объекта plot MATLAB самостоятельно

использует графические примитивы. Потомками объекта plot являются, например, barseries

("столбиковая диаграма"), contourgraph ("контурная диаграмма"), lineseries ("набор линий"),

surfaceplot("поверхность"). Большое количество разнотипных графиков и диаграмм, реализуемых

методами объекта plot, существенно упрощает задачу визуализации данных, однако при

необходимости создания сложного (нетипового) графика, диаграммы и т.п. без средств

низкоуровневой графики обойтись трудно;

- annotation objects ("объекты-примечания") – объекты (стрелки, прямоугольники, текст),

размещаемые на отдельном от остальных графических объектов уровне, и используемые, как

правило, для выделения или ретуширования данных, приведенных на графиках и диаграммах;

- group objects ("объекты-группы") – объекты, содержащие в себе несколько других объектов

и позволяющие работать с ними (например, устанавливать их параметры или выполнять

преобразования) как с одним объектом;

Page 14: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

14

- UI objects (объекты интерфейса) – объекты, используемые при создании графического

пользовательского интерфейса GUI. С формой (Figure) связаны панель инструментов (uitoolbar),

меню (uimenu), контекстные меню (uicontextmenu, создается аналогично объекту uimenu, но

затем "назначается" том или иному объекту интерфейса) и базовые элементы управления. К

базовым элементам управления относятся объекты, "типичные" для большинства

интегрированных средств разработки программ (кнопки различных видов, текстовые поля, списки

и раскрывающиеся списки, полоса прокрутки, таблица). Объекты uipanel и uibuttongroup

представляют собой контейнеры для хранения базовых элементов управления, графических

объектов и других контейнеров. Объект ActiveX является особым объектом MATLAB и позволяет

организовать взаимодействие с другими приложениями посредством COM-интерфейса.

Доступ к графическим объектам в программе на MATLAB

Каждому графическому объекту при создании MATLAB присваивает уникальный числовой

идентификатор (handle), Идентификатор объекта root равен 0. Для остальных объектов

идентификатор – это обычно число вещественного типа.

Чтение и запись свойств графических объектов осуществляется функциями set() и

get().Аргументы функции должны содержать идентификатор объекта и наименование свойства,

которое требуется прочитать или модифицировать например:

bl_size = get(hndl_1, 'Value');

set(hndl_2, 'String', 'Кодирование завершено');

В соответствии с парадигмой событийно-ориентированного программирования каждому

компоненту управления сопоставлена одна (или более) процедур (callback) обработки событий.

Вызов каждой такой процедуры связан с выполнением пользователем определенного действия

(нажатия кнопки, выбора пункта меню, перемещения курсора мыши над элементом управления и

т.п.). Содержание callback-процедур определяет пользователь, разрабатывающий

пользовательский интерфейс.

Наиболее распространенными типами callback-процедур в GUIDE являются:

- ButtonDownFcn – вызывается по нажатию кнопки мыши над компонентом управления, для

которого установлено свойство Enable. В случае, если используется для объекта Figure, то

возникает когда щелчок происходит по области окна, не занятой другими объктами;

- WindowsButtonDownFcn, WindowsButtonMotionFcn – вызываются при нажатии кнопки

мыши или перемещении мыши (в пределах окна);

- Callback – вызывается при выполнении функционального действия компонента (нажатие

кнопки, или выбор пункта меню);

- CloseRequestFcn – вызывается непосредственно перед закрытием формы;

- CreateFcn – вызывается при создании компонента управления но до отображения формы

на экране. Шаблон, генерируемый GUIDE для данной функции, обычно реализует установку цвета

отображения компонента на экране;

Page 15: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

15

- DeleteFcn – вызывается при удалении компонента из памяти;

- KeyPressFcn – вызывается когда пользователь нажимает клавишу на клавиатуре, а

компонент управления находится в фокусе.

Параметрами вызова callback-процедуры, как правило, являются:

- hObject – идентификатор (handle) элемента управления, для которого вызвана процедура

обработки;

- eventdata – параметр зарезервирован;

- handles – структура, содержащая идентификаторы всех графических элементов,

присутствующих на оконной форме.

Благодаря такому набору параметров из любой callback-процедуры некоторой формы

можно получить доступ к свойствам не только "родного" объекта (через идентификатор hObject),

но и к свойствам любого объекта на данной форме (через структуру handles), например:

bl_size = get(hObject, 'Value')

set(handles.text8, 'String', 'Кодирование завершено');

В некоторых случаях для получения идентификатора графического объекта в MATLAB-

программе можно воспользоваться следующими функциями:

- findobj – выполняет поиск объекта по заданным свойствами (например, имени) и

возвращает идентификатор объекта;

- gcb – возвращает идентификатор окна, содержащего объект, для которого вызвана

процедура обработки события;

- gcbo – возвращает идентификатор объекта, для которого вызвана процедура обработки

события;

- gca – возвращает идентификатор текущего (активного) объекта axes. Обычно используется

при работе с графикой на дескрипторном ("низком") уровне;

- gco – возвращает идентификатор текущего (активного) графического объекта. Обычно

используется при работе с элементами управления.

Подробнее средства создания пользовательского интерфейса в MATLAB средствами GUIDE и

методы работы с графическими объектами описаны в *9, 10+. Организация взаимодействия

MATLAB-программы с другими приложениями через COM-интерфейс и использование объектов

ActiveX рассмотрены в *11].

Основы программирования на языке MATLAB

Язык программирования системы MATLAB вобрал в себя все средства, необходимые для

реализации различных видов программирования: процедурного, функционального, объектно-

ориентированного, структурного (модульного), визуально-ориентированного и т.п. [12]. MATLAB

имеет черты известных языков программирования высокого уровня: BASIC, Pascal, FORTRAN [13]:

- среда выполнения MATLAB представляет собой интерпретатор;

- отсутствует необходимость в объявлении типов и размеров переменных;

Page 16: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

16

- обеспечивается возможность образования новых типов вычислительных объектов (классов)

на основе типов объектов, уже существующих в языке;

- все переменные в MATLAB являются локальными, то есть действуют лишь в границах той

программной единицы (процедуры, функции или главной, управляющей программы), где им

присвоены некоторые конкретные значения. При переходе к выполнению другой программной

единицы, значения переменных предыдущей программной единицы или совсем теряются (в

случае, если выполненная программная единица является процедурой или функцией), или

становится недосягаемыми (если выполненная программа – управляющая). Обмен данными

между функциями (и командами) происходит главным образом через их входные параметры;

- в языке MATLAB нет глобальных переменных, однако интерпретатор MATLAB позволяет в

одном и том же сеансе работы выполнять несколько самостоятельных программ, причем все

переменные, используемые в этих программах, являются общими для этих программ и образуют

общее рабочее пространство (Workspace);

- подавляющее большинство функций и команд языка представляют собой вполне

законченные модули, оформленные в виде текстовых m-файлов, которые хранятся на диске и

подключаются к программам по мере необходимости. Это позволяет более рационально

организовывать сложные (громоздкие) вычисления по принципу, который напоминает

оверлейные структуры.

Особенности записи программы на языке MATLAB

Основные особенности записи текста программы (m-файла) на языке MATLAB [13]:

- обычно каждый оператор записывается в отдельной строке текста программы. Признаком

конца оператора является конец строки. Можно размещать несколько операторов в одной строке,

тогда предыдущий оператор этой строки должен заканчиваться символом ' ; ' или ' , '. Можно

длинный оператор записывать в несколько строк. При этом предыдущая строка оператора должна

заканчиваться тремя точками " ... ".

- если очередной оператор не заканчивается символом ' ; ', результат его действия при

выполнении программы будет выведен в командное окно. Чтобы предотвратить вывод на экран

результатов действия оператора программы, запись этого оператора в тексте программы должна

заканчиваться символом ' ; '. Если выражение завершается знаком ';', то MATLAB не выводит

результирующее значение на экран. Обычно формат оператора с ';' используется при работе со

средой в интерактивном режим, а без ';' – при написании программы;

- строка программы, начинающаяся с символа ' % ', не выполняется. Эта строка

воспринимается системой MATLAB как комментарий;

- строки комментария, предшествующие первому выполняемому оператору программы, т. е.

такому, который не является комментарием, воспринимаются системой MATLAB как описание

программы;

- в программах на языке MATLAB отсутствует символ окончания текста программы;

- в языке MATLAB переменные не описываются и не объявляются. Любое новое имя,

появляющееся в тексте программы при ее выполнении, воспринимается системой как имя

Page 17: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

17

матрицы. Размер этой матрицы устанавливается при предварительном вводе значений ее

элементов либо определяется действиями по установлению значений ее элементов, описанными

в предшествующих операторах или процедуре;

- имена переменных могут содержать лишь буквы латинского алфавита или цифры и должны

начинаться из буквы. Общее число символов в имени может достигать 30. В именах переменных

могут использоваться как прописные, так и строчные буквы. Строчные и прописные буквы в

именах различаются.

Файлы-сценарии и файлы-функции

Все команды, которые вводятся в командной строке (Command Window), можно сохранить в

виде единой последовательности в файле с расширением ‘m’. Такой файл называется сценарием

(script-файлом) и может быть запущен на выполнение из командной строки, из другого m-файла

или непосредственно из текстового редактора MATLAB. Для файлов сценариев характерны

следующие особенности:

- они не имеют входных и выходных аргументов;

- работают с данными из рабочей области, т.е. значения переменных сохраняются не только

на время выполнение сценария, но и на протяжении всего сеанса работы с MATLAB;

- в процессе выполнения не компилируются;

- представляют собой законченную последовательность операций, полностью аналогичную

той, что используется при работе с командной строкой.

Структура файла-сценария обычно имеет следующий вид:

%Основной комментарий (необязательный)

%Дополнительный комментарий (необязательный)

Тело_файла. Содержит любые допустимые выражения MATLAB

Основной комментарий выводится при выполнении команд lookfor и <help имя_каталога>.

Основной и дополнительный комментарии выводятся при выполнении команды <help

имя_файла>.

Файл-функция (также имеет расширение 'm') является полноценным модулем с точки

зрения структурного программирования, поскольку содержит входные и выходные параметры и

использует аппарат локальных переменных. Структура такого модуля с одним выходным

параметром выглядит следующим образом (чтобы функцию можно было вызвать, ее имя

(f_name) должно совпадать с именем m-файла):

function var=f_name(Cпиcoк_napaмeтpов)

%Основной комментарий (необязательный)

%Дополнительный комментарий (необязательный)

Тело файла с любыми выражениями

vаr=выражение

Page 18: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

18

Файл-функция имеет следующие свойства:

- он начинается с объявления function, после которого указывается имя переменной var –

выходного параметра (для случая одного выходного параметра), имя самой функции и список ее

входных параметров – все это указывается в первой строке файла;

- функция возвращает свое значение и может использоваться в виде f_name

(Список_параметров) в математических выражениях;

- все переменные, имеющиеся в теле файла-функции, являются локальными, т. е. действуют

только в пределах тела функции;

- файл-функция является самостоятельным программным модулем, который общается с

другими модулями через свои входные и выходные параметры;

- правила вывода комментариев те же, что у файлов-сценариев;

- файл-функция служит средством расширения системы MATLAB;

- при обнаружении файла-функции он компилируется и затем исполняется, а созданные

машинные коды хранятся в рабочей области системы MATLAB;

- конструкция vаг=выражение необходима, если требуется, чтобы функция возвращала

результат вычислений.

Если выходных параметров больше одного, то они указываются в квадратных скобках после

слова function. При этом структура модуля имеет следующий вид:

function [varl,var2....]=f_name(Список_параметров)

%Основной комментарий (необязательный)

%Дополнительный комментарий (необязательный)

Тело файла с любыми выражениями

vаг1=выражение

vаг2=выражение

Функция языка MATLAB с несколькими выходными параметрами схожа с процедурой

традиционного языка программирования высокого уровня. Ее нельзя слепо использовать

непосредственно в математических выражениях, поскольку она возвращает не единственный

результат, а множество результатов — по числу выходных параметров. Если функция используется

как имеющая единственный выходной параметр, но в действительности имеет ряд выходных

параметров, то для возврата значения функции будет использоваться первый из них. Это зачастую

ведет к ошибкам в математических вычислениях. Если функция используется в виде f_nаmе(...), то

возвращается значение только первого выходного параметра — переменной varl.

При необходимости функции m-файла могут разделять общую переменную. Для работы с

такой переменной в каждой из функций, где она используется, переменную необходимо объявить

с использованием оператора global.

Файл-функция (в отличие от файла-сценария) может содержать несколько функций, однако

из других модулей (или рабочего пространства) может быть вызвана только первая (главная)

функция модуля. При необходимости остальные функции модуля могут быть вызваны из главной

функции.

Более подробная информация о файлах-функция и файлах-сценариях содержится в *13,14].

Page 19: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

19

Типы данных MATLAB

В MATLAB определены следующие основные встроенные классы вычислительных объектов

и объектов управления (см. рисунок 1.7):

Массив (ARRAY)

обычный или разреженный

logical char NUMERIC cell structure function handle

классы Javaклассы

пользователяint8, uint8,

int16, uint16,

int32, uint32,

int64, uint64

single double

Рисунок 1.7 – Классы (типы данных) MATLAB

- double – числовые массивы с числами удвоенной точности (все числовые данные по

умолчанию имеют тип double);

- single – числовые массивы с числами одинарной точности;

- int64, uint64 – массивы 64-разрядных чисел со знаком и без знаков;

- int32, uint32 – массивы 32-разрядных чисел со знаком и без знаков;

- int16,uint16 – массивы 16-разрядных целых чисел со знаком и без знаков;

- int8, uint8 – массивы 8-разрядных целых чисел со знаками и без знаков;

- char – строчные массивы с элементами-символами;

- logical – логические массивы, содержащие значения 1 ("истина") или 0 ("ложь");

- struct – массивы структур с полями, которые также могут содержать массивы;

- сеll – массивы ячеек; ячейки, в свою очередь, тоже могут быть массивами;

- sparse – наследует свойства double, разреженные матрицы с элементами-числами

удвоенной точности;

- date – работа с данными, представляющими собой дату и время;

- function_handle – дескрипторы функций.

MATLAB – система, специально предназначенная для осуществления вычислений с

векторами, матрицами и полиномами. Под вектором в MATLAB понимается одномерный массив

чисел, а под матрицей – двумерный массив. При этом следует четко понимать, что вектор, вектор-

строка, вектор-столбец или тензор – это математические объекты, а одномерный или двумерный

массив – структура данных, предназначенная для хранения этих объектов в рамках программы

[15,16].

По умолчанию предполагается, что любая (!) заданная переменная является вектором или

матрицей (в терминах программы – массивом). Например, отдельное заданное число (скаляр)

система воспринимает как матрицу размером 1х1 (массив из одной строки и одного столбца), а

вектор-строку из N элементов – как матрицу размером 1хN (одномерный массив).

Page 20: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

20

Массив, имеющий более двух измерений, называется многомерным массивом.

Многомерный массив в MATLAB обычно рассматривается как расширение двумерного массива. В

случае трехмерного массива третье измерение условно называется "страницей".

MATLAB позволяет преобразовывать массив, изменяя размеры и даже размерность массива

(функция reshape()) при условии сохранения числа элементов в массиве неизменным, выполнять

перестановку размерностей массива (функция permute()), минимизировать размерность массива,

т.е. удалять размерность, по которой имеется только одно возможное значение соответствующего

индекса (функция squeeze()).

Переменная в MATLAB создается, когда ей присваивается значение. Ниже приведены

некоторые примеры формирования и инициализации числовых переменных, значения которых

хранятся в одномерных и многомерных массивах:

Оператор Размерность переменной,

тип Комментарии

A = 1 1 x 1 double

Создается переменная-скаляр A (матрица размером 1х1)

B = [1 2 3 4 5] 1 x 5 double

Вектор-строка B из 5 элементов. Значения строки массива разделяются пробелом. Квадратные скобки являются конструктором числового массива

C = uint8([1; 2; 3; 4; 5.4]) 5 x 1 uint8

Вектор-столбец из 5 беззнаковых целых чисел. Значения различных строк разделяются знаком " ; ". Округление до целого выполняется по математическим правилам

[1 2 3 4 5] 1 x 5 Вектор-строка из 5 элементов записывается в специальную системную переменную ans, поскольку оператор не содержит знака присваивания. Полученное значение переменной ans может использоваться в следующих операторах вычислений

D = uint32([1; 2; 3; 4; 5]) 5 x 1 uint32

Вектор-столбец из 5 элементов

E = [1 2 3 4 5]' 5 x 1 double

Вектор-столбец из 5 элементов получается путем транспонирования (знак " ' ") вектора-строки

F = [1.0 2 3.9 14 -5]'' 5 x 1 double

Вектор-строка из 5 элементов получается путем двойного транспонирования вектора-строки

G = [1 2; 3 4; 5 6] 3 x 2 double

Матрица из 3-х строк и 2-х столбцов. Значения различных строк разделяются знаком ";"

H = [1 2 3; 4 5 6; 7 8 9]; H(:, :, 2) = [1 0 4; 5 4 3; 2 3 4]

3х3х2 double

Сначала создается двумерный массив H(3х3). Затем инициализируются значения второй страницы (добавляется третье измерение). Результат – трехмерный массив из 3-х строк, 3-х столбцов и 2 "страниц"

I = [B F] 1 x 10 double

Вектор-строка из 10 элементов. Сначала последовательно заносятся 5 элементов вектора B, затем – 5 элементов вектора F

J = [B; F] 2 x 5 double

Матрица из 2-х строк и 5 столбцов. Первая строка – элементы вектора B, вторая строка – элементы вектора F

K = [1 2; ; 5 6] 2x2 double

Неинициализированные строки автоматически удаляются из матрицы. Данный оператор эквивалентен "А=*1 2; 5 6]"

L = [1 2; 3; 5 6] Ошибка Количество значений для строк не соответствует количеству значений для столбцов

Page 21: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

21

Оператор Размерность переменной,

тип Комментарии

M = [-0.1 : 0.3 : 1.4] 1х6 double

Вектор-строка *-0.1 0.2 0.5 0.8 1.1 1.4]. Задается начальным значением, шагом, конечным значением.

N = zeros(4, 6) 2x6 double

Матрица из 4-х строк и 6 столбцов, содержащая нулевые элементы

O = ones(3, 5, 2) 3x5x2 double

Трехмерный массив размерностью 3х5х2 элементов, содержащий единичные элементы

P = rand(10) 10x10 double

Матрица размером 10х10 элементов, равномерно распределенных в диапазоне от 0 до 1

R = 2*ones(4) 4x4 double

Матрица размером 4x4 элемента, все значения которой равны 2

S = eye(2) T = repmat(R, 2, 3)

2x2 double 4x6 double

Единичная матрица S размером 2x2 элемента (единицы расположены на главной диагонали. Матрица T размером 4x6 элементов, которая получается путем дублирования матрицы S 2 раза по вертикали и 3 раза по горизонтали

Кроме числовых типов данных в MATLAB реализована поддержка символьных данных,

записей (структур) и ячеек.

Строка в MATLAB представляет собой одномерный массив (вектор), компоненты которого

содержат числовые коды символов. Код каждого символа при хранении занимает 2 байта памяти.

Один символ хранится в массиве размером 1х1, строка из N символов – в массиве размером 1xN

(класс char). Массив объектов типа char может хранить несколько строк, причем все строки

должны быть одинаковой длины, например:

name = ['Ivanov S.P. '; ...

'Morkovkin A.V. '; ...

'Cheremushkin K.D.'];

Как видим, в случае, если строки имеют различную длину, то они должны быть дополнены

пробелами до длины самой длинной строки. Избежать данных проблем помогает использование

массива ячеек (Cell Array).

Если обычный массив MATLAB содержит данные одного типа, то массив ячеек – это массив,

элементами которого являются ячейки, которые сами могут содержать любой тип массива, в том

числе и массив ячеек. Массивы ячеек позволяют хранить массивы с элементами данных разных

типов. Создание массива ячеек может выполняться при инициализации содержимого ячеек (см.

ниже), а может быть выполнено путем вызова функции вида:

D = cell(100, 1); % создание одномерного массива ячеек из 100 элементов

(ячеек)

Массивы записей (структур) – это тип массивов в системе MATLAB, в котором разрешается

сосредоточивать в виде записей разнородные данные (т. е. данные разных типов (классов)).

Отличительной особенностью таких массивов является наличие именованных полей. Как и

Page 22: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

22

вообще в MATLAB, массивы записей не объявляются. Отдельные экземпляры этого класса

создаются автоматически при задании конкретных значений полям записи:

FIO.family = 'Ivanov';

FIO.name = 'Ivan';

FIO.surname = 'Ivanovich';

FIO.god = 1990

или путем использования оператора struct:

<имя записи> = struct('<имя поля1>', <значение1>, '<имя поля2>', <значение2>, ...).

Например:

FIO = struct('family','Ivanov,'name','Ivan','surname','Ivanovich','god', 1990)

При создании массива записей новые записи добавляются путем указания соответствующего

индекса:

FIO(2).family = 'Petrov';

FIO(2).name = 'Petr';

FIO(2).surname = 'Petrovich';

FIO(2).god = 1996;

Если к какому-либо из элементов массива записей (структуры) добавляется значение нового

поля, то же поле автоматически появляется во всех остальных элементах, хотя значение этого

поля у других элементов при этом остается пустым.

Чтобы установить, какому классу принадлежит объект, используется функция class().

Вопросы использования объектно-ориентированного программирования при обработке

данных на языке MATLAB выходят за рамки данного краткого введения и детально рассмотрены в

[13, 17].

Доступ к элементам массивов, ячеек и структур данных

Обращение к элементам массива осуществляется путем указания индекса. Использование

диапазонов значений индексов позволяет получить доступ к подмассиву исходного массива [18].

Примеры доступа к отдельным элементам описанных ниже переменных A и B, приведены в таблице:

A = [1 2 3 4; 5 6 7 8; 9 10 11 12];

B = [1.1 -2.1 3.4 4.5 5.8; 6.7 7.9 8.4 9.6 10.2];

Оператор Размерность результата

Комментарии

A(2,3) 1x1 В системную переменную ans заносится значение элемента массива, расположенного на пересечении второй строки и

Page 23: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

23

Оператор Размерность результата

Комментарии

третьего столбца

C = A(1:2,3:4) 2x2 В переменную C заносится подматрица, состоящая их элементов правого верхнего угла матрицы А: [3 4; 7 8]

D = B(1, :) 1x5 В вектор-строку D заносятся все элементы первой строки матрицы B

E = [A(2:3,2:3) B] 2x7 В матрицу E заносится подматрица матрицы A, а затем к ней слева "приписывается" матрица B

A(:, 1) = 0 размерность матрицы A

Первый столбец матрицы A заполняется нулями

F = zeros(10); H = ones(2); F(5:6,5:6) = B

10x10 Результатом является матрица F размером 10x10 элементов, четыре центральных элемента которой равны 1, а остальные 0.

При "переинициализации" переменной (всей переменной, а не ее части!) матрицей другого

размера, размер переменной автоматически корректируется.

Хранение матрицы в MATLAB осуществляется по столбцам, сверху-вниз. Поэтому к каждому

элементу, например, двумерной матрицы можно получить доступ, либо два индекса (номер

строки и номер столбца), либо указав номер элемента в "линейной развертке" матрицы.

При доступе к элементам многомерного массива сначала указывается номер строки, затем

номер столбца, затем номер "страницы" (для трехмерного массива), как показано на рисунке 1.8.

Понятно, что количество индексов должно соответствовать размерности массива.

Рисунок 1.8 – Индексы элементов многомерного (трехмерного) массива в MATLAB

При этом MATLAB позволяет получить доступ не только к одному элементу массиву, но и к

целой строке, столбцу, странице и т.д., как это показано на рисунке 1.9. Чтобы реализовать такой

режим доступа необходимо зафиксировать один или несколько из индексов (т.е. указать в них

конкретные значения), а вместо остальных значений индексов указать знак ":" или необходимый

диапазон значений, например, "1:3".

Page 24: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

24

Рисунок 1.9 – Доступ к "странице" трехмерного массива в MATLAB

Доступ к элементам массива ячеек (в отличие от доступа к элементам массива) обычно

осуществляется путем указания индекса в фигурных скобках, например:

C{1,1} = 'Ivanov S.P.';

C{1,2} = [1 2 3 4 5];

C{2,1} = [1 2 3; 4 5 6; 7 8 9];

C{2,2} = uint8(1:1:10);

Для символьного и графического отображения массива ячеек используются функции

celldisp() и cellplot().

Доступ к элементам массива записей не отличается от доступа к элементам массива структур

в традиционных языках программирования и также требует указания номера записи и имени

поля.

Непосредственное использование в расчетах классов cell и struct затруднительно, тем не

менее они используются в MATLAB для хранения информации, а также при создании новых

классов объектов.

Виды операций над массивами

Операции с массивами в MATLAB можно разделить на 2 группы [13]:

- векторные (матричные) операции, выполняемые по правилам математики. К таким

операциям относятся сложение векторов, вычитание векторов, транспонирование вектора,

умножение вектора на число, умножение двух векторов (определено только когда один из

векторов – строка, а другой – столбец и оба вектора имеют одинаковое количество элементов, в

зависимости от порядка операндов результатом может быть либо число, либо квадратная

матрица), векторное произведение (определено только трехкомпонентных векторов, вызывается

как функция);

- математические операции над элементами массивов. К таким операциям относятся все

элементарные математические функции MATLAB от одного аргумента (например, sin(x), exp(x) и

т.п., где x – матрица произвольной размерности) и некоторые стандартные математические

операции (прибавление числа ко всем элементам матрицы, поэлементное умножение матриц

(оператор ".*"), поэлементное деление матриц (оператор ".\"), поэлементное возведение

Page 25: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

25

матрицы в степень (оператор ".^"), причем для операций поэлементного умножения и деления

матрицы должны быть одинакового размера).

Построение простейших графиков функций

MATLAB обладает мощными средствами визуализации данных. Рассмотрим кратко пример

построения с использованием MATLAB функции одной переменной. Построение простейшего

графика функции состоит из трех этапов:

- задание вектора значений аргумента;

- вычисление вектора значений функции для заданных значений аргумента;

- вызов команды plot для построения графика функции.

Например (см. рисунок 1.10):

x = [0:0.1:1.0]; % формируется вектор x из (1х11) элементов

y = exp(x) .* (10*x); % формируется вектор y из (1х11) элементов, причем yi = exi * (10*xi)

plot(x, y); % создается окно с областью рисунка, в котором выводится график функции

Рисунок 1.10 – Результат использования функции plot() для построения графика функции

Если в списке аргументов функции plot() указать только один аргумент, то он будет

интерпретирован как вектор значений функции для значений аргумента 0, 1, 2, ...

Если в качестве аргумента значений функции указать не одномерный, а двумерный массив,

то для каждого столбца (!) этого массива в области рисунка будет построен свой график.

Например, для двумерного массива C = [1 2 3; 4 5 6; 7 8 9] будут построены три графика со

значениями функции *1 4 7+, *2 5 8+ и *3 6 9+ и общими значениями аргумента *1 2 3+.

MATLAB поддерживает более 30 способов графического представления двумерных данных и

более 20 способов – трехмерных. Детально они описаны в *10].

Page 26: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

26

Управление программой на языке MATLAB

Помимо программ с линейной структурой, инструкции которых исполняются строго по

порядку, существует множество программ, структура которых нелинейна. При этом ветви

программ могут выполняться в зависимости от определенных условий, иногда с конечным числом

повторений — циклов, иногда в виде циклов, завершаемых при выполнении заданного условия.

Практически любая серьезная программа имеет нелинейную структуру. Для создания таких

программ необходимы специальные управляющие структуры. К таким управляющим структурам в

языке MATLAB относятся условные операторы, операторы организации цикла, оператор

обработки исключений и оператор возврата из функции.

Синтаксис Пример Комментарии

Условные операторы:

if logical_expression_1 statements_1 [elseif logical_expression_2 statements_2] [else statements_3] end

if A(2, 3) == 0 B = A*C; end

Проверка на эквивалентность значений выполняется с использованием оператора "=", на неравенство – оператора "~="

if A B = A*C; end

Если оцениваемое логическое выражение приводит к получению нескалярного значения, то условие считается истинным, если все(!) элементы аргумента не равны нулю

if A(1,1) > 0 B = A*C elseif A(1,1) < 0 B = A*A end

Для организации "вложенных" условных операторов можно использовать оператор elseif

switch expression case value_1 statements_1 [ case value_2 statements_2] ... [ otherwise statements_n] end

switch input_num case -10 a = 32; case {-5, 0, 5} a = 64; case 10 a = 128; otherwise a = 0; end

В качестве оцениваемого значения expression может использовать либо скаляр, либо строка. В отличие от языка С при попадании в одну из ветвей case, управление не "проваливается" в нижеследующие ветви – остальные case-варианты не выполняются. Поэтому оператор break в данном случае не используется. Оператор switch может отрабатывать множественные проверки в каждой ветви case

Операторы цикла:

for index=start:inc:end statements end

for i=2:1:10 a(i) = a(i-1) end

Выполнение итераций завершается, когда значение переменной цикла становится больше (меньше) верхней границы для положительного (отрицательного) модификатора. Допускается формат записи пределов изменения переменной цикла в виде start:end. В этом случае MATLAB использует значение модификатора переменной, равное единице. В цикле for можно использовать операторы continue и break

while expression statements end

n = 1; while n < 100 n = n + 1; end

В цикле while можно использовать операторы continue и break

Page 27: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

27

Оператор обработки исключений

try statements_1 catch statements_2 end

Последовательность между операторами try и catch выполняется до тех пор, пока не произойдет ошибка. В этом случае управление передается на операторы внутри блока catch. Текст сообщения о причине ошибки, идентификатор ошибки и состояние стека можно получить с использованием функции lasterror

Оператор возврата из функции

return Оператор позволяет вернуть управление из функции в вызывающую программу до нормального завершения выполнения функции

Примеры реализации простейших алгоритмов обработки векторных и матричных данных

средствами MATLAB

Ниже приводятся примеры вычисления типовых математических операций над векторами и

матрицами, которые лежат в основе большинства алгоритмов обработки данных [15, 16].

Скалярное произведение двух векторов одинакового размера. Скалярное произведение

векторов a и b длины N, состоящих из действительных чисел, определяется как сумма попарных

произведений элементов этих векторов. Для вычисления скалярного произведения можно

использовать следующее выражение MATLAB:

res1 = sum(a .* b)

Результатом вычислений будет число res1 (массив размером 1х1).

Модуль вектора. Модуль вектора равен квадратному корню из суммы квадратов всех

элементов вектора. На языке MATLAB выражения для вычисления модуля вектора можно

записать следующим образом:

res2 = sqrt(sum(a .* a))

Результатом вычислений будет число res2 (массив размером 1х1).

Векторное произведение векторов. Векторное произведение векторов a x b определено в

MATLAB только для векторов из трехмерного пространства, т.е. состоящих из трех элементов. Для

вычисления векторного произведения может использоваться специальная функция cross:

res3 = cross(a, b)

Результат res3 является вектор в трехмерном пространстве (массив 1х3 или 3х1, в

зависимости от того, являлись ли исходные вектора соответственно строками или столбцами).

Вычисление среднего значения вектора. Для вычисления среднего значения вектора

необходимо найти сумму всех его элементов и разделить на число элементов (размер вектора).

Размер массива a можно определить функцией size(a), однако следует помнить, что функция

вернет вектор, содержащий количество значений, равное размерности массива (т.е. будет

подсчитано число элементов для каждого измерения массива). Чтобы подсчитать число

элементов для какого-то конкретного измерения массива, следует использовать формат вызова

size(a, номер_измерения), которая вернет единственное число.

Page 28: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

28

Таким образом, требуемый результат для случая, если вектора а – вектор строка, можно

получить, применив выражение

res4 = sum(a) / size(a, 2)

Более простым способом получения желаемого является использование встроенной

функции MATLAB mean():

res4 = mean(a)

Результатом вычислений в обоих случаях будет число res4 (массив размером 1х1).

Вычисления евклидова расстояния между двумя векторами. Евклидово расстояние между

двумя векторами равно квадрату из суммы квадратов поэлементных разностей векторов.

res5 = sqrt(sum( (a-b) .^ 2))

Результатом вычислений будет число res5 (массив размером 1х1).

Нахождение суммы элементов матрицы. Как отмечалось выше применение функции

суммирования sum() к двумерному массиву приведет к вычислению суммы независимо по

каждому столбцу матрицы (т.е. формируется вектор-строка с суммами по столбцам). Чтобы

получить итоговую сумму матрицы надо сложить найденные суммы:

res6 = sum(sum(a))

Результатом вычислений будет число res6 (массив размером 1х1).

Сортировка строк в массиве. Рассмотрим случай, когда имеется матрица, все строки которой

представляют собой последовательности символов одинаковой длины, например: a = ['abcd '; 'as

', 'asdfg']. Для сортировки строк такой матрицы по возрастанию удобно использовать функцию

sortrows():

res7 = sortrows(a)

Результатом вычислений будет массив res7 той же размерности, что и а.

Детальное описание встроенных функций MATLAB приведено в руководствах [19-21].

Способы оценки производительности и повышения эффективности программ на языке MATLAB

Для анализа эффективности программы и выявления тех ее фрагментов, которые требуют

оптимизации, в MATLAB используются следующие средства:

1) утилита профилирования (Profiler), которая позволяет оценить относительное время

выполнения той или иной части программы, чтобы выявить наиболее проблемные фрагменты

кода. Запуск профайлера можно выполнить из редактора m-файлов (пункт меню

Tools→Open_Profiler) или набрав в командной строке среды (Command Window) команду profile

view и введя имя функции, которую следует запустить на выполнение. По результатам

профилирования (см. рисунок 1.11) оценивается время выполнения каждой функции (в том числе

без учета времени выполнения вложенных функций) и ее отдельных строк, время выполнения

вложенных функций, подсвечиваются наиболее "проблемные" участки кода.

Подробные инструкции по использованию профайлера можно найти в *6+;

Page 29: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

29

2) специальные функции tic и toc – позволяют путем соответственно включения и

выключения таймера измерить "абсолютное" время выполнения программы или ее части для

оценки эффективности алгоритма, сравнения производительности различных аппаратных

платформ и т.п. Хотя для аналогичной цели может использоваться функция cputime, разработчики

пакета MATLAB рекомендуют использовать именно функции tic и toc, обеспечивающих получение

более достоверных оценок, особенно на многоядерных (hyperthreading) процессорах, начиная с

Intel Pentium IV.

Рисунок 1.11 – Результат работы профайлера для функции Profiling1 (код модуля Profiling1.m

приведен в левом верхнем окне). Справа внизу – краткая статистика, справа - подробная

Повышение производительности выполнения программ на языке MATLAB может

достигаться за счет использования следующих основных приемов:

- использования распараллеливания вычислений. MATLAB поддерживает как "неявное"

распараллеливание (multithreading, в основном достигается за счет выполнения отдельных задач

в виде потоков на разных процессорных элементах (ядрах) одного компьютера при

соответствующих аппаратных возможностях, повышает производительность выполнения базовых

операций над матрицами, не требует внесения каких-либо изменения в программный код,

включается в окне установок (Preferences) MATLAB) и "явное" (выполнение отдельных задач на

различных компьютерах с использованием пакета Parallel Computing Toolbox, увеличивает

производительность при больших объемах вычислений в каждой задаче, требует модификации

программного кода);

- векторизация циклических операций, т.е. замена цикла с несколькими итерациями, в

котором выполняется обработка скалярных значений, одной операций с вектором или матрицей,

например:

Исходный код Код после оптимизации

i = 0; t = 0 : .01 : 10;

Page 30: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

30

for t = 0 : .01 : 10 i = i + 1; y(i) = sin(t); end

y = sin(t);

"Векторизированный" код в среде MATLAB будет выполняться значительно быстрее за счет

реализации "накладных расходов" (организации цикла, выполнения переходов между

элементами массива и т.п.) внутренними средствами MATLAB. Особенно полезными при

векторизации могут быть такие функции, как all(), any(), sumsum(), find(), prod(), sort(), sum() и др.;

- предварительное распределение памяти под массивы. Если в теле цикла присутствуют

операции, выполнение которых приводит к динамическому увеличению размера массива, то

регулярный поиск в оперативной памяти непрерывных блоков нужного размера средствами

MATLAB будет существенно снижать производительность программы. Чтобы избежать этого

рекомендуется до начала цикла выделить под массив память максимально необходимого

размера, например:

Исходный код Код после оптимизации

x = 0; for k = 2:1000 x(k) = x(k-1) + 5; end

x = zeros(1, 1000); for k = 2:1000 x(k) = x(k-1) + 5; end

- в случае использования типа данных (класса), отличного от double, указание типа значений

матрицы непосредственно при создании матрицы во избежание выполнения операции

преобразования типа над большим объемом данных:

Исходный код Код после оптимизации

A = int8(zeros(100)); A = zeros(100, 'int8');

Дополнительные возможности и приемы повышения производительности выполнения

программ на языке MATLAB рассмотрены в *14, 23]

Вопросы для самопроверки

1. Каким образом объявляются переменные в языке MATLAB?

2. В чем заключаются различия между файлом-сценарием и файлом-функцией?

3. Как можно задать матрицу или вектор с MATLAB?

4. Чем отличаются поэлементные операции от обычных операций над матрицами?

5. Как построить столбцовую диаграмму? гистрограмму?

6. В чем заключается векторизация вычислений в MATLAB и в чем преимущества

векторизации?

7. Какие инструкции в языке MATLAB используются для организации циклов?

8. Что такое массив ячеек?

9. Как хранятся матрицы в MATLAB?

10. Как осуществляется взаимодействие с пользователем при использовании GUI?

Page 31: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

31

Контрольные задания

Виды заданий:

1. Найти значение арифметического выражения

2. Найти сумму элементов ряда

3. Построить матрицу с заданной структурой

4. Написать программу для вычисления выражения, содержащего повторяющееся

подвыражение. Оформить процедуру вычисления подвыражения в виде файл-функции

5. Выполнить профилирование разработанной в п.4 программы

6. Разработать программу с оконным интерфейсом, которая позволяет вводить необходимое

число значений, выполняет вычисление и выводит результат в числовом и/или графическом виде

Вариант задания для сдачи лабораторной работы получить у преподавателя.

Список использованных источников к лабораторной работе № 1

1. http://www.answers.com/topic/the-mathworks-inc

2. The MathWorks - http://www.mathworks.com

3. http://ru.wikipedia.org/wiki/MATLAB

4. Learning MATLAB 7. – The MathWorks, 2005

5. Гультяев А. Визуальное моделирование в среде MATLAB: учебный курс. – СПб: Питер, 2000

6. MATLAB 7. Desktop Tools and Development Environment. – The MathWorks, 2008

7. MATLAB 7. Getting Started Guide. – The MathWorks, 2008

8. MATLAB 7. MAT-File Format. – The MathWorks, 2008

9. MATLAB 7. Creating Graphical User Interfaces. – The Mathworks, 2008

10. MATLAB 7. Graphics. – The Mathworks, 2008

11. MATLAB 7. External Interfaces. – The Mathworks, 2008

12. Иллюстрированный самоучитель по MATLAB. – realcoding.net

13. Лазарев Ю.Ф. Начала программирования в среде MatLAB: Учебное пособие. – К.: НТУУ

"КПИ", 2003

14. MATLAB 7. Programming Fundamentals. – The Mathworks, 2008

15. Ануфриев И.Е. Самоучитель MatLab 5.3/6.x – СПб.:БХВ-Петербург, 2003

16. Ануфриев И.Е., Смирнов А.Б., Смирнова Е.Н. MATLAB 7. – СПб.: БХВ-Петербург, 2005

17. MATLAB 7. Classes and Object-Oriented Programming. – The Mathworks, 2008

18. Ануфриев И.Е. Методическое пособие "Информатика. Пакет MatLab" – Изд-во СпбГПУ,

2003. http://amd.stu.neva.ru/anufriev/MLab/mlad.htm

19. MATLAB 7. Function Reference. Volume 1: A-E. – The MathWorks, 2008

20. MATLAB 7. Function Reference. Volume 2: F-O. – The MathWorks, 2008

21. MATLAB 7. Function Reference. Volume 1: P-Z. – The MathWorks, 2008

22. MATLAB 7. Desktop Tools and Development Environment. – The Mathworks, 2008

23. MATLAB 7. Programming Tips. – The Mathworks, 2008

Page 32: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

32

ЛАБОРАТОРНАЯ РАБОТА 2. РЕАЛИЗАЦИЯ И ИССЛЕДОВАНИЕ АЛГОРИТМА КОМПРЕССИИ

ИЗОБРАЖЕНИЙ

Цель лабораторной работы – реализовать средствами MATLAB алгоритм компрессии

изображений и исследовать зависимость результатов кодирования от параметров алгоритма.

Основные задачи:

- средствами GUIDE и редактора m-файлов MATLAB разработать графический интерфейс

пользователя, позволяющий в интерактивном режиме управлять параметрами кодирования и

анализировать результаты кодирования (степень компрессии и качество кодирования);

- разработать структуры данных для хранения исходного и результирующего изображений,

промежуточных данных при кодировании и декодировании;

- реализовать заданный алгоритм обработки панхроматических (в градациях серого) или

цветных изображений;

- провести эксперименты с целью оценки влияния на качество и степень компрессии

основных параметров алгоритма кодирования.

Основные требования к выполнению работы

Разработать программу на языке MATLAB, реализующую кодирование и декодирование

цветного или серого изображения.

Программа должна иметь разработанный средствами GUIDE пользовательский интерфейс,

позволяющий:

- выбирать файл для обработки;

- задавать (выбирать) значения параметров алгоритма кодирования;

- запускать процессы кодирования и декодирования изображения;

- выводить на экран исходное и восстановленное изображения для визуальной оценки

качества кодирования;

- рассчитывать степень компрессии изображения;

- рассчитывать оценку степени соответствия восстановленного изображения исходному

(качество кодирования) – с использованием соотношения "сигнал-шум" или среднеквадратичной

ошибки.

Отдельные этапы обработки изображений следует реализовывать в программе в виде

самостоятельных функций внутри основного модуля (или самостоятельных файлов-функций).

Программный код должен быть структурирован, содержать комментарии различных уровней на

русском языке. Особое внимание следует уделить использованию "ориентации" MATLAB на

обработку векторных и матричных значений, избегая по возможности применения явных

циклических конструкций для повышения производительности вычислений.

Общие требования к содержанию отчета по лабораторной работе

Page 33: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

33

Отчет по работе должен содержать:

1) титульный лист;

2) формулировку задания (в соответствии с вариантом);

3) краткое описание алгоритма компрессии, включающее:

- общую характеристику алгоритма (сильные и слабые стороны, возможности эффективной

реализации на ЭВМ, на какие данные ориентирован и т.п.);

- описание алгоритма кодирования изображения (кодера) с обязательной ссылкой на

источник литературы;

- описание алгоритма декодирования изображения (декодера) с обязательной ссылкой на

источник литературы;

- упрощения алгоритма обработки данных (отличия от описанного) и обоснования их

использования;

4) описание интерфейса пользователя, вид экранной формы с элементами управления в

режиме конструктора (Editor Layout) и/или в режиме выполнения;

5) список элементов управления и соответствующих им callback-процедур, которые реально

используются при обработке данных ("пустые" шаблоны callback-процедур, сгенерированные

GUIDE, приводить не следует), и краткое описание функционального назначения этих процедур;

6) список модулей (m-файлов) с кратким описанием их функционального назначения и

связей между модулями;

7) структурная схема (схемы) алгоритма обработки данных с указанием последовательности

вызовов, передаваемых данных, имен вызываемых функций;

8) перечень переменных, описанных с модификатором global;

9) описание использованных способов повышения эффективности выполнения программы

за счет векторизации обработки данных и других рассмотренных приемов;

10) результаты проведенных экспериментов;

11) список использованных источников;

12) листинги всех m-модулей программы с подробными комментариями.

Пример. Разработка программа кодирования изображения по алгоритму JPEG

В качестве примера разработана программа, выполняющая компрессию изображений по

стандарту JPEG. Описание реализации алгоритма приведено в соответствии с требованиями к

отчету по работе.

Разработанный интерфейс пользователя содержит дополнительные возможности,

позволяющие анализировать результаты кодирования по отдельным блокам изображения

(просмотр коэффициентов ДКП и коэффициентов масштабирования, просмотр результатов

применения ДКП к изображению, просмотр в укрупненном виде одного блока изображения,

полученных для него коэффициентов преобразования и восстановленного изображения).

Реализация этих возможностей обусловлена необходимостью демонстрации на примере

возможностей работы с различными элементами управления. В рамках выполнения

лабораторной работ реализация таких дополнительных возможностей является необязательной.

Page 34: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

34

Краткое описание алгоритма JPEG

Общая характеристика алгоритма. Алгоритм JPEG разработан как метод сжатия непрерывно-

тоновых изображений. На практике он характеризуется сравнительно высоким коэффициентом

сжатия, большим числом параметров кодирования, позволяющих найти баланс между степенью и

качеством компрессии, возможностью использования "быстрой реализации" алгоритма прямого и

обратного преобразования изображения (ДКП), возможностью использования только

целочисленной арифметики при реализации. К недостаткам алгоритма могут быть отнесены

дефекты, проявляющиеся в виде регулярных блоков одинакового размера на восстановленном

изображении при сильной степени компрессии. Кроме того, возможно проявление эффекта

Гиббса – ореолов по границам резких переходов цветов.

Компрессия/декомпрессия изображения выполняется путем последовательного

применения нескольких различных алгоритмов обработки данных. Рассматривается стандартный

режим работы алгоритма.

Краткое описание алгоритма кодирования. Основные шаги сжатия по алгоритму JPEG состоят

в следующем *1+.

1) Цветное изображение преобразуется из цветового пространства RGB в цветовое

пространство, состоящее из компоненты яркости (Y) и двух компонент цветности (I и Q), например:

Y = 0.299R + 0.587G + 0.114B

I = 0.596R – 0.274G – 0.322B

Q = 0.211R – 0.522G + 0.311B

На практике в JPEG используется перевод в пространство YCbCr, ориентированное на 8-

битовое представление компонент. Различия между цветовыми пространствами YCbCr и YIQ для

данной задачи несущественно.

Глаз менее чувствителен к ошибкам в передаче цветности, нежели яркости. Поэтому

кодировать компоненты цветности можно с меньшей точностью, чем компоненту Y. Для этого

выполняется понижение частоты дискретизации (прореживание) компонент цветности в 2 или

даже 4 раза по каждой размерности. Далее каждая компонента кодируется отдельно.

2) Пикселы цветовой компоненты разбиваются на блоки NxN пикселов. Если количество

пикселов не кратно N, то последняя строка и/или столбец повторяются необходимое число раз.

3) К каждому блоку применяется дискретно-косинусное преобразование

где S(x,y) – исходное значение амплитуды пиксела с координатами x и y внутри блока, D(i,j) –

значение элемента (i,j) матрицы коэффициентов преобразования (0i,jN-1), а значения C(i) и C(j)

рассчитывается по формуле .

4) Каждая из 64 компонент делится на специальное число – коэффициент квантования.

Обычно таблица коэффициентов квантования является статически заданной и передается вместе с

Page 35: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

35

закодированным изображением. Один из способов формирования таблицы квантования Q

является использование формулы

Q(i,j) = 1 + (i+j) * R

где i,j – номер строки и столбца в блоке (0i,jN-1), R – некоторый показатель качества (R = 100-

Quality+1). Чем больше значение R, тем сильнее квантование и, соответственно, ниже качество

восстановленного изображения.

5) Квантованные коэффициенты ДКП после округления преобразуются из матричного

представления в линейное таким образом, чтобы в элементы были расположены в векторе в

порядке убывания значимости (с точки зрения "важности" кодируемых частот). Для этого

используется зигзагообразный обход матрицы коэффициентов, проиллюстрированный на

рисунке:

1 2 6 7

3 5 8 13

4 9 12 14

10 11 15 16

Обход обычно реализуется на основе рассчитываемых заранее индексов табличной

перестановки. Например, для блока 4х4 такой таблицей является:

(1,1) (1,2) (2,1) (3,1) (2,2) (1,3) (4,1) (2,3) (3,2) (4,1) (4,2) (3,3) (2,4) (3,4) (4,3) (4,4)

6) К полученному вектору коэффициентов применяются дополнительные методы

кодирования. При этом обычно первый коэффициент (DC) кодируется в виде кода Хаффмана для

разности с DC-коэффициентом предыдущего блока, а остальные (AC) коэффициенты кодируются с

использованием комбинации RLE и метода Хаффмана (или арифметического кодирования).

При кодировании DC коэффициента сначала унарным кодом кодируется длина бинарного

представления DC-коэффициента, а затем записывается собственно значение коэффициента.

В последовательности AC-коэффициентов, как правило, значительная часть нулевых

значений. Для кодирования каждого ненулевого значения x кодер а) определяет число

предшествующих ему нулей (Z), б) определяет длину унарного кода (R) числа x и номер числа x

среди всех чисел с данной длиной двоичного представления (C), в) заменяет пару <R, Z> на код

переменной длины Хаффмана (H), выбираемый из заранее заданной статической таблицы с

монотонно возрастающими длинами кодов, г) приписывает H к C (C представлено в виде R битов)

и выдает полученное кодовое слово в битовый поток. После кодирования последнего ненулевого

коэффициента в выходной поток записывается специальный четырехбитовый код окончания

блока (EOB), отсутствующий в таблице кодов Хаффмана.

7) Полученный битовый поток дополняется заголовком, содержащим параметры

изображения, таблицы квантования, таблицу Хаффмана и записывается в файл или передается в

канал связи.

Краткое описание алгоритма декодирования. Основные шаги декодирования по алгоритму

JPEG состоят в следующем *1+.

Page 36: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

36

1) Из файла (канала связи) читается битовый поток, из которого выбирается заголовок,

таблицы квантования и таблица Хаффмана, а также параметры (размеры) изображения.

Рассчитывается количество блоков по вертикали и горизонтали.

2) Последовательно выполняется декодирование DC и AC коэффициентов каждого блока и

формирование вектора коэффициентов ДКП.

3) Выполняется формирование матрицы коэффициентов ДКП-преобразования каждого

блока путем применения такой же таблицы для обхода, как и при кодировании (только в

обратном направлении).

4) Выполняется обратное масштабирование (квантование) коэффициентов ДКП каждого

блока путем поэлементного умножения значений блока на соответствующие значения матрицы

коэффициентов квантования Q.

5) К каждому блоку применяется обратное ДКП-преобразование:

где S(x,y) – исходное значение амплитуды пиксела с координатами x и y внутри блока, D(i,j) –

значение элемента (i,j) матрицы коэффициентов преобразования (0i,jN-1), а значения C(i) и C(j)

рассчитывается по формуле .

6) Выполняется обратное изменение (повышение) частоты дискретизации компонент

цветности.

7) Выполняется переход из пространства YCbCr в пространство RGB

R = 1.0*Y + 0.956*I + 0.621*Q

G = 1.0*Y – 0.272*I – 0.647*Q

B = 1.0*Y - 1.106*I + 1.703*Q

Упрощения и ограничения алгоритма обработки изображения, допущенные при

программной реализации. При реализации с целью сокращения трудоемкости разработки

использованы следующие допустимые упрощения и ограничения стандартного алгоритма:

1) программа обрабатывает только изображения в градациях серого (т.е. одна цветовая

плоскость), хранящиеся в файле формата BMP. При поступлении на вход программы цветного

изображения, выполняется его перевод в одноцветное "серое" изображение путем применения к

каждому пикселу формулы:

Y = 0.299R + 0.587G + 0.114R

Поддержка только формата BMP объясняется возможностью перекодирования изображения

из другого формата в формат BMP средствами практически любого графического редактора;

1) не реализован этап эффективного кодирования коэффициентов ДКП с использованием

неравномерного кода Хаффмана (или арифметического кодирования). Это объясняется тем, что

несмотря на наличие в MATLAB (в пакете Communications Toolbox) специализированных функций

для построения дерева Хаффмана и кодирования/декодирования по Хаффману huffmandict(),

huffmanenco(), huffmandeco() и аналогичных функций для арифметического кодирования,

реализовать на их основе используемый в JPEG вариант неравномерного кодирования

Page 37: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

37

коэффициентов ДКП достаточно проблематично, поскольку в JPEG используется статически

заданная двумерная таблица, ставящая кодовое слово в зависимость от двух параметров. По этой

же причине не выполняется сохранение компрессированного изображения в файл;

2) для оценки размера выходного битового потока на один блок изображения используется

условная таблица длин кодов Хаффмана, сходная с реальной таблицей стандарта JPEG

(увеличение длин кодов происходит монотонно от левого верхнего к правому нижнему углу

таблицы). Поэтому, несмотря на отсутствие процедур формирования реального битового потока,

оценка размера выходного битового потока для каждого блока изображения является

достоверной. Кроме того, при оценки степени компрессии не учитываются заголовки как

исходного изображения, так и закодированного потока.

3) размеры изображения должны быть кратны размеры выбранного блока ДКП. Для

универсальности рекомендуется, чтобы размер изображения по каждой стороне был кратен 64

(максимальный поддерживаемый размер блока ДКП равен 64). В случае невыполнения этого

требования кодирование не выполняется. Это связано с необходимостью дополнительной

обработки блоков, имеющих неполное количество пикселов, перед выполнением прямого ДКП и

после выполнения обратного ДКП. По той же причине размер изображения не может быть менее

4х4 пикселов (минимальный поддерживаемый размер блока ДКП). Необходимый размер

изображения может быть получен путем использования практически любого графического

редактора;

4) дополнительно к кодированию всех ненулевых коэффициентов (как предусмотрено в

алгоритме JPEG) в программе добавлена возможность кодирования фиксированного числа ДКП-

коэффициентов блока.

Описание интерфейса пользователя

Главная экранная форма в режиме макета приведена на рисунке 2.1, а в режиме

выполнения – на рисунке 2.2.

При запуске программы на выполнение из редактора, оболочки GUIDE или из командной

строки, на экран выводится форма, приведенная на рисунке 2.2. Она позволяет пользователю:

- выбрать и загрузить BMP-файл для обработки (кнопка "Выбрать изображение");

- установить параметры алгоритма кодирования на панели "Параметры кодирования"

(размер блока от 4х4 до 64х64, способ кодирования ДКП-коэффициентов блока,

среднестатистическое число битов на один ДКП коэффициент (для оценки степени компрессии

изображения), качество кодирования – от минимального (R=100, правый край ползунка) до

максимального (R=1, левый край ползунка);

- рассчитать и визуализировать форму базисных ДКП-поверхностей, накладываемых на блок

изображения (для i,j от 0 до N-1) для выбранного размера блока. При этом базисные ДКП-

изображения появляются в новом окне, как показано на рисунке 2.3;

Page 38: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

38

Рисунок 2.1 – Главная экранная форма программы в режиме макета

Рисунок 2.2 – Главная экранная форма программы в режиме выполнения

- выполнить кодирование и декодирование изображения (кнопка "Выполнить

кодирование"). После выполнения кодирования будет выведено восстановленное изображение, а

также будет рассчитан коэффициент компрессии изображения;

Page 39: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

39

Рисунок 2.3 – Базисные ДКП-изображения для блока 8х8

- рассчитать и вывести в новом окне масштабирующие коэффициенты для выбранного

размера блока и заданного значения R, как показано на рисунке 2.4;

Рисунок 2.4 – Коэффициенты квантования для блока 8х8

- вывести в отдельном окне исходное изображение и восстановление изображение (кнопки

с надписями "Показать в отдельном окне" соответственно под исходным изображением слева и

под восстановленным изображением справа);

- показать детальную информацию о кодировании одного блока изображения. Для выбора

блока необходимо щелкнуть в интересующей области исходного изображения. Блок, в который

попали координаты указателя мыши, будет детально проанализирован на панели "Обработка

блока ДКП". При этом будут показаны изображение блока (в укрупненном масштабе), таблица

коэффициентов ДКП (в таблице слева), таблица коэффициентов ДКП после квантования,

Page 40: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

40

кодирования/декодирования и деквантования (в таблице справа), а также изображение

восстановленного блока изображения (в укрупненном масштабе).

Программа не выполняет проверку признака загруженности изображения и завершения

кодирования, поэтому попытки вывести в отдельном окне исходное или декодированное

изображение, а также выбрать область на изображении для детального анализа могут привести к

генерации ошибочного сообщения в Command Window среды MATLAB.

Основные элементы управления и связанные с ними callback-процедуры

Основные элементы управления, для которых выполнена разработка процедур обработки

событий, приведены в таблице 2.1.

Таблица 2.1 – Основные элементы управления и связанные с ними callback-процедуры

Наименование элемента Тип Callback-функция Вызов по событию

Описание процедуры обработки

pushbutton_LoadImage кнопка pushbutton_LoadImage_Callback(...) нажатие кнопки

Загрузка bmp-изображения из файла. Если изображение цветное, то преобразование к серому. Результат обработки – двумерный массив

pushbutton_ShowDCTCoefs кнопка pushbutton_ShowDCTCoefs_Callback(...) нажатие кнопки

Чтение параметров с формы. Формирование базисных функций ДКП и вывод их в новом окне

pushbutton_ShowQuantCoefs кнопка pushbutton_ShowQuantCoefs_Callback(...) нажатие кнопки

Чтение параметров с формы. Формирование коэффициентов квантования и вывод их в новом окне

pushbutton_RunCoding кнопка pushbutton_RunCoding_Callback(...) нажатие кнопки

Чтение параметров с формы. Кодирование и декодирование изображения. Расчет степени компрессии

figure1 окно figure1_WindowButtonDownFcn(...)

нажатие кнопки над окном вне элементов

управления

Если указатель мыши находится над исходным изображением – то рассчитать номер блока и показать детальную информацию по его кодированию

slider_Quality слайдер slider_Quality_Callback(...) сдвиг

бегунка

Считывание позиции бегунка и вывод числового значения параметра качества в текстовое поле

pushbutton5 кнопка pushbutton5_Callback(...) нажатие кнопки

Вывод исходного изображения в отдельном окне

pushbutton6 кнопка pushbutton6_Callback(...) нажатие кнопки

Вывод декодированного изображения в отдельном окне

Список m-файлов (модулей)

Перечень m-файлов, используемых программой, приведен на рисунке 2.5. Все файлы

являются файл-функциями и вызываются из функций главного модуля – JPEG_Analysis.

Page 41: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

41

Рисунок 2.5 – Модульная структура программы

Функциональное назначение модулей

function varargout = JPEG_Analysis(varargin) – шаблон файл-функции генерируется

автоматически средстами GUIDE при сохранении экранной формы. Содержит callback-процедуры

для некоторых элементов управления, размещенных на форме, а также функции для обработки

данных. При вызове функции JPEG_Analysis создается новая экранная форма или, если форма с

таким именем уже открыта, она становится активной. Вызов функции с параметрами и возврат

значений не предполагается;

function [coefs_scale] = Generate_Scales(N, Quality) – файл-функция, генерирует

коэффициенты (масштабирующие множители) для квантования коэффициентов ДКП. Входные

параметры – размер матрицы (матрица полагается квадратной), и условное значение параметра

качества, выходной параметр – двумерный квадратный массив NxN коэффициентов квантования

(типа double). Одна и та же матрица применяется и при кодировании, и при декодировании;

function [Indices] = Generate_Zigzag(N) – файл-функция, генерирует индексы для обхода

матрицы заданного размера "зигзагом". Входной параметр – размер матрицы (матрица

полагается квадратной), выходной параметр – массив (размером N*N х 2) индексов элементов

исходной матрицы в требуемом порядке, первый столбец соответствует номерам строк, второй –

номерам столбцов элементов исходной матрицы. Одна и та же таблица индексов применяется и

при кодировании, и при декодировании;

function [out_linear] = UnrollMatrix(in_matrix, ind) – файл-функция, реализующая обход

матрицы в заданном порядке. Входные параметры – матрица значений и массив индексов

порядка обхода. Выходной параметр – вектор, содержащий значения матрицы в порядке обхода;

function [out_matrix] = RollMatrix(in_linear, ind) – файл-функция, реализующая

преобразование вектора в матрицу с учетом требуемого порядка расположения элементов.

Входные параметры – вектор значений и массив индексов порядка обхода. Выходной параметр –

матрица, содержащая значения вектора в заданном порядке;

function [res] = SNR(im_x, im_y) – файл-функция, рассчитывающая отношение сигнал-шум

кодирования. Входные параметры – матрицы исходного и восстановленного изображения.

Выходной параметр – значения отношения сигнал-шум в децибелах.

Page 42: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

42

function [block_bitrate] = EstimateBlockBitRate(linear_block, prev_DC, table_len) – файл-

функция, рассчитывающая размер выходного битового потока для блока квантованных

коэффициентов. Входные параметры – вектор квантованных коэффициентов ДКП, значение DC-

коэффициента предыдущего блока, таблица кодов Хаффмана. Выходной параметр – размер

выходного потока в битах.

Структурная схема алгоритмов обработки данных

Структурная схема алгоритма обработки изображения приведена на рисунке 2.6.

pushbutton_RunCoding_Callback()

ДЕ

КО

ДЕ

РК

ОД

ЕР

pushbutton_LoadImage_Callback()

Вывести на

форму

BMP-файл

Загрузить изображениеИзображение (NxN)

или (NxNx3)

Преобразовать

в серое

Преобразовать в double

figure1

(JPEG_Analysis)

Workspace

(global)

double SrcImage[NxN]

double DstImage[NxN]

double DCT_Image[NxN]

double DeScaleDCT_Image[NxN]

struct Params:

ImageSize[2x2]

BlockSize[1x1]

NumBlocks[2x2]

Quality[1x1]

...

нажатие на кнопку pushbutton_LoadImage

double SrcImage [NxN]

Курсивом отмечены действия, выполняемые с использованием стандартных

функций MATLAB.

Пунктирные линии – вызовы процедур

Штрих-пунктирные линии – передача данных

Сплошные линии – передача управления

нажатие на кнопку pushbutton_RunCoding

Проверить размеры изображения на

кратность размеру блока

T = Params.NumBlock(1)*Params.NumBlocks(2)

Прочитать параметры кодирования с

формы

function read_params()

Выполнить прямое ДКП

function Im2DCT(SrcImage)

double SrcImage [NxN]

Проквантовать коэффициенты ДКП

function DCT2Scale(DCT_Image)

double DCTImage [N,N])

Преобразовать в вектор

function Scale2Zigzag(Scale_Image)

double ScaleImage [N,N]

Отбросить "лишние" коэффициенты

function CutCoefs(LinearCoefs)

double LinearCoefs [T,Params.BlockSize^2]

struct Params

double DstImage [NxN]

double DCT_Image [NxN]

double DeScaleDCT_Image [NxN]Вычислить размер сжатого изображ.

function EstimateBitRate(CutCoefs)

double CutCoefs [T,Params.BlockSize^2]

Рассчитать коэффициент компрессии

Преобразовать в матрицу

function Zigzag2Scale(CutCoefs)

Деквантование коэффициентов ДКП

function Scale2DCT(DeScale_Image)

double DeScale_Image [N,N]

Выполнить обратное ДКП

function Scale2DCT(DeScaleDCT_Image)

double DeScaleDCT_Image [N,N]

Рассчитать сигнал-шум

function SNR(SrcImage, DstImage)

double DstImage [N,N]

Вывести на

форму

figure1_WindowButtonDownFcn()

щелчок мышью над окном figure1

Проверить на попадание в axes_SrcImage

Вычислить номера блоков по вертикали и

горизонтали num_block [2,1]

Вывести на форму блоки SrcImage(num_block)

и DstImage(num_block)

Заполнить таблицы блокам

DCT_Image(num_block) и

DeScaleDC_Image(num_block)

struct Params

double DstImage [NxN]

double DCT_Image [NxN]

double DeScaleDCT_Image [NxN]

Рисунок 2.6 – Структурная схема алгоритма обработки изображения

Page 43: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

43

Перечень переменных, описанных с модификатором global

В различных функциях программы с модификатором global описаны следующие

переменные:

- Params – структура данных, содержащая характеристики изображения и параметры

кодирования, необходимые для использования в различных функциях модуля. Состоит из

следующих полей:

ImageSize [1,2] – размер изображения в пикселах;

BlockSize [1,1] – размер ДКП-блока;

Quality [1,1] – параметр, задающий качество кодирования (степень квантования);

NumBlocks [1,2] – количество блоков по горизонтали и вертикали;

CompressionRatio [1,1] – рассчитанный коэффициент компрессии изображения;

SN_Ratio[1,1] – отношение сигнал-шум;

CodeNonZero [1,1] – флаг кодирования всех ненулевых коэффициентов ДКП;

NumFirstDCTCoefs [1,1] – количество первых кодируемых коэффициентов ДКП

(учитывается только при CodeNonZero = 0).

- SrcImage, DstImage – двумерные массивы, содержащие исходное и восстановленное

изображения соответственно. Описаны как глобальные для использования в callback-процедурах,

вызываемых по различным событиям;

- DCT_Image, DeScaleDCT_Image – двумерные массивы, содержащие коэффициенты ДКП

исходного изображения и восстановленные после квантования/деквантования коэффициенты

ДКП. Описаны как глобальные для использования в callback-процедурах, вызываемых по

различным событиям.

Использованные способы повышения эффективности выполнения программы

Основными использованными приемами повышения производительности в разработанной

программе являются:

- вынос за цикл операций, выполнение которых может привести к увеличению размера

массива. В большинстве функций, выполняющих формирование массива, массив формируется

путем выделения памяти командой вида ARRAY = zeros(NxM);

- использование стандартных функций MATLAB для выполнения прямого и обратного

дискретного преобразований (dct2, idct2), формирования списка ненулевых коэффициентов блока

изображения (find), расчета отношения сигнал-шум (sum);

- использование матричных операций при обработке целиком блоков данных NxN при

выполнении прямого и обратного ДКП, квантования и деквантования ДКП-коэффициентов, при

обнулении "неиспользуемых" коэффициентов ДКП.

Page 44: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

44

Результаты экспериментов

Для проведения исследования алгоритма кодирования проанализируем влияния на степень

компрессии и качество кодирования двух параметров:

- размера блока ДКП (варианты значений: 4х4, 8х8, 16х16, 32х32, 64х64 при всех кодируемых

коэффициентах ДКП) – эксперимент № 1;

- количество кодируемых первых коэффициентов ДКП (варианты значений: 4, 8, 16, 32, 64

при размере блока ДКП, равном 8) – эксперимент № 2.

Эксперименты проводятся при постоянном значении параметра качества Quality=95. При

проведении экспериментов использовались 2 изображения.

Результаты экспериментов приведены в таблице 2.2.

Таблица 2.2 – Результаты исследования программы компрессии изображений

Значение варьируемого

параметра

Изображение 1 (128х128) Изображение 2 (1024х768)

Коэффициент компрессии, раз

С/Ш, дБ Коэффициент

компрессии, раз С/Ш, дБ

Эксперимент № 1

4х4 (16 коэф.) 8,2 25,7 13,1 32,1

8х8 (64 коэф.) 15,6 22,7 34,9 30,6

16х16 (256 коэф.) 26,7 19,4 73,7 28,4

32х32 (1024 коэф.) 45,1 17,2 133,7 26,2

64х64 (4096 коэф.) 78,3 15,5 232,6 24,1

Эксперимент № 2

4 32,4 14,8 46,7 23,7

8 25,3 16,2 38,4 27,4

16 19,3 19,0 35,5 29,7

32 16,8 21,1 35,0 30,1

64 15,6 22,7 34,9 30,6

В эксперименте № 1 степень компрессии увеличивается с размером блока (особенно для

второго изображения), поскольку после квантования начинают преобладать нулевые

коэффициенты ДКП. С увеличением размера блока качество кодирования снижается, что

объясняется ухудшением адаптации алгоритма к локальным характеристикам изображения при

расширении блока.

В эксперименте № 2 изменение числа кодируемых ДКП-коэффициентов также приводит к

изменению как степени компрессии, так и качества кодирования. Наблюдается постоянное

снижения величины коэффициента компрессии, обратно пропорциональное числу кодируемых

коэффициентов ДКП. График изменения отношения сигнал-шум показывает, что при кодировании

более половины коэффициентов блока качество кодирования и степень компрессии изменяются

слабо. Это объясняется тем, что после квантования большая часть высокочастотных

коэффициентов ДКП, расположенных в правой нижней части блока, и так равна нулю.

Page 45: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

45

Список использованных источников

1. Сэломон Д. Сжатие данных, изображений и звука. – Москва: Техносфера, 2004

2. Ватолин Д., Ратушняк А., Смирнов М., Юкин В. Методы сжатия данных. – Москва:

ДиалогМИФИ. - http://compression.graphicon.ru/

3. Рудаков П.И., Сафонов И.В. Обработка сигналов и изображений. MATLAB 5.x /Под общ.

ред. к.т.н. В.Г.Потемкина. – М.: ДИАЛОГ-МИФИ, 2000

4. MATLAB 7. Mathematics. – The MathWorks, 2008

5. MATLAB 7. Data Analysis. – The MathWorks, 2008

5. Ohad Gal. JPEG Compression – www.mathworks.com (MATLAB File Exchange)

Листинг программы

Модуль Generate_Scales.m

function [coefs_scale] = Generate_Scales(N, Quality)

% Генерация коэффициентов квантования для масштабирования коэф. ДКП

% Входные параметры:

% N - количество элементов в квадратной матрице

% Quality - условное значение параметра качества >0

% Выходные параметры:

% coefs_scale - матрица коэффициентов квантования размером NxN (double)

% Алгоритм:

% Формирование матрицы с монотонно увеличивающимися коэффициентами

%--------------------------------------------------------------------------

coefs_scale = zeros(N); % заранее генерируем квадратную матрицу

%---------------------------------------------------------

% Вариант 1 - с поэлементной обработкой

%for m=1:N

% for n=1:N

% coefs_scale(m,n) = 1 + (m+n)*Quality;

% end

%end

%---------------------------------------------------------

% Вариант 2 - ориентированный на векторную обработку

% выполняется быстрее в 3-5 раз (в зависимости от N)

coefs_scale(1,:) = (1+(1+1)*Quality):Quality:(1+(1+N)*Quality); % генерируем первую строку

for m=2:N

coefs_scale(m,:) = coefs_scale(m-1,:) + Quality; % ост. строки увеличиваем на Quality

end

%--------------------------------------------------------------------------

Модуль UnrollMatrix.m

function [out_linear] = UnrollMatrix(in_matrix, ind, ind_l)

% Разворачивание матрицы в вектор путем обхода в заданном порядке

% Входные параметры:

% in_matrix - исходная матрица

% ind - массив индексов (NxN,2)

% ind_l - массив индексов (NxN,1)- индексы представлены

% в виде смещений от начала массива (т.е. одним

% числом)

Page 46: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

46

% Выходные параметры:

% out_linear - вектор, содержащий элементы матрицы,

% упорядоченные в соответствии таблицей индексов

%--------------------------------------------------------------------------

n = size(in_matrix, 1); % взять размер полученной квадратной матрицы

out_linear = zeros(1, n*n); % заранее выделяем место под массив-вектор 1xN^2

%---------------------------------------------------------

% Вариант 1 - с поэлементной обработкой

% в цикле формируем вектор, выбирая в него элементы матрицы

% в порядке, который определен таблице индексов ind

%for i=1:n*n

% out_linear(i) = in_matrix(ind(i,1), ind(i,2));

%end

%---------------------------------------------------------

% Вариант 2 - с векторной обработкой

% для чтения сразу нескольких элементов матрицы необходимо, чтобы

% индексы ее элементов были перечислены в необходимом порядке

% виде скалярных значений.

out_linear = in_matrix(ind_l);

Модуль RollMatrix.m

function [out_matrix] = RollMatrix(in_linear, ind, ind_l)

% Сворачивание вектора в квадратную матрицу в вектор путем обхода по зигзагу

% Входные параметры:

% in_linear - исходный вектор

% ind - массив индексов (NxN,2)

% ind_l - массив индексов (NxN,1)- индексы представлены

% в виде смещений от начала массива (т.е. одним

% числом)

% Выходные параметры:

% out_matrix - матрица, содержащая элементы вектора,

% упорядоченные в соответствии с таблицей индексов

%--------------------------------------------------------------------------

n = sqrt(size(in_linear, 2)); % из размера вектора определить размер матрицы

out_matrix = zeros(n); % заранее выделяем место под квадратную матрицу

%---------------------------------------------------------

% Вариант 1 - с поэлементной обработкой

%for i=1:n*n

% out_matrix(ind(i,1), ind(i,2)) = in_linear(i);

%end

%---------------------------------------------------------

% Вариант 2 - с векторной обработкой

% для чтения сразу нескольких элементов матрицы необходимо, чтобы

% индексы ее элементов были перечислены в необходимом порядке

% виде скалярных значений.

out_matrix(ind_l) = in_linear;

%--------------------------------------------------------------------------

Модуль SNR.m

function [res] = SNR(im_x, im_y)

% Вычисление отношения сигнал-шум

% Входные параметры:

Page 47: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

47

% im_x - исходное изображение

% im_y - восстановленное изображение

% Изображения должны быть одинакового размера

% Выходные параметры:

% res - отношение сигнал-шум

%--------------------------------------------------------------------------

N = size(im_x,1) * size(im_x,2); % количество пикселов в изображении

% находим мощность исходного изображения

imx_sq = im_x .* im_x; % Src*Src – каждый элемент – в квадрат

P_x = sum(sum(imx_sq))/N; % Power(Src) – разделить сумму всех элементов

% матрицы на число элементов

% находим ошибку кодирования

e = im_x-im_y; % одной командой – сразу всю матрицу обрабатываем

% расчет мощности ошибки

e_sq = e.*e;

P_e = sum(sum(e_sq))/N;

% отношение сигнал-шум

res = 10*log10(P_x/P_e); % присваиваем значение выходному параметру

%--------------------------------------------------------------------------

Модуль Generate_Zigzag.m

function [Indices, , Indices_l] = Generate_Zigzag(N)

% Генерация индексов для обхода матрицы по зигзагу

% Входные параметры:

% N - количество элементов в квадратной матрице

% Выходные параметры:

% Indices - массив (N^2,2), содержащий номера строк

% и столбцов элементов квадратной матрица в порядке

% обхода. Первый столбец соответствует номеру строки,

% второй столбец - номера столбца

% Indices_l - массив (N^2,1), содержащий ту же самую

% информацию, что и Indices, но номера элементов

% приведены в виде одномерного смещения от начала

% массива. При этом учитывается, что матрица в MATLAB

% хранится по столбцам!

%--------------------------------------------------------------------------

Indices = zeros(N*N, 2); % заранее выделяем место под матрицу (N^2 x 2)

% Первую диагонально проходим вручную (один элемент)

Indices(1, :) = [1 1];

a = 2; % сдвигаем индекс в таблице индексов

% обрабатываем диагонали длиной больше 1 (все, кроме первой и последней)

for t=2:1:(2*N-2) % В матрице NxN строк есть 2N-1 диагоналей. Одну уже прошли

% сначала отрабатываем переход на первый элемент диагонали

% и устаналиваем необходимые параметры движения по ней

if (rem(t,2)~=0) % если диагональ нечетная (rem – остаток от деления)

dr = 1; dc = -1; % приращения для перехода к следующему элементу диагонали

if (t <= N) % длина диагонали растет или уменьшается?

P = t; % если растет - то число элементов равно номеру диагонали

Indices(a, 1) = Indices(a-1, 1);

Indices(a, 2) = Indices(a-1, 2)+1;

else

P = 2*N-t; % иначе: (2N - номер диагонали)

Indices(a, 1) = Indices(a-1, 1)+1;

Page 48: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

48

Indices(a, 2) = Indices(a-1, 2);

end

else % если диагональ четная

dr = -1; dc = 1;

if (t <= N) % длина диагонали растет или уменьшается?

P = t; % если растет - то число элементов равно номеру диагонали

Indices(a, 1) = Indices(a-1, 1) + 1;

Indices(a, 2) = Indices(a-1, 2);

else

P = 2*N-t; % иначе: (2N - номер диагонали)

Indices(a, 1) = Indices(a-1, 1);

Indices(a, 2) = Indices(a-1, 2)+1;

end

end

a = a + 1; % первый элемент диагонали обработали

% теперь проходим по оставшимся элементам диагонали

for i=2:1:P

Indices(a, 1) = Indices(a-1, 1) + dr;

Indices(a, 2) = Indices(a-1, 2) + dc;

a = a + 1;

end

end

% Последнюю диагонально проходим вручную (один элемент)

Indices(N*N, :) = [N N];

% Дополнительно расчитывает линейные индексы элементов

% Для преобразования (row,col) => ind может использоваться

% функция sub2ind вида

% ix = sub2ind([n n], ind(:,1), ind(:,2));

% Но поскольку она очень "медленная", то вместо нее

% лучше рассчитывать смещение от начала матрицы "вручную". При этом

% следует помнить, что в MATLAB двумерный массив хранится по столбцам.

Indices_l = (Indices(:,2)-1)*N + Indices(:,1);

%--------------------------------------------------------------------------

Модуль EstimateBlockBitRate.m

function [block_bitrate] = EstimateBlockBitRate(linear_block, prev_DC, table_len)

% Оценка размера блока в битах в соответствии с кодированием квантованных

% коэффициентов ДКП в алгоритме JPEG

% Входные параметры:

% linear_block - массив целочисленных значений Nx1

% prev_DC - значение первого коэффициента предыдущего

% блока

% table_len - условная таблица длин кодов Хаффмана

% (Nxn) элементов

% Выходные параметры:

% block_bitrate - размер блока в битах

% Алгоритм:

% Кодирование первого значения (DC) и остальных значений (AC)

% выполняется по отдельности.

% Для кодирования DC вычисляется разность между DC и prev_DC,

% которая кодируется унарным кодом + само число. Для оценки

% длины кода достаточно использовать двойную длину унарного

% кода

% При кодировании AC каждое число заменяется на пару

% <число_нулей, значение>. Для этой пары берется код из

% таблицы Хаффмана. Для оценки кода достаточно знать длину

% этого кода

Page 49: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

49

%--------------------------------------------------------------------------

N = size(linear_block, 1); % определяем размер массива

% рассчитываем размер кода для DC-коэффициента

diff = linear_block(1) - prev_DC;

block_bitrate = 2*(size(abs(diff),2)+1); % унарный код + само число.

% рассчитываем размер кода для всех AC-коэффициентов

nz_ind = find(linear_block); % получаем список всех ненулевых коэффициентов

snd = size(nz_ind,2); % число ненулевых коэффициентов

%---------------------------------------------------------

% Вариант 1 - с поэлементной обработкой

% начинаем обход всех ненулевых со второго ненулевого элемента

%for i=2:snd

% Z = nz_ind(i) - nz_ind(i-1); % число нулей между ними + 1 (для доступа к таблице)

% x = linear_block(nz_ind(i)); % само значение

% R = ceil(log2(abs(x))) + 1; % длина унарного кода значения - № строки в таблице

% C = R; % длина номера столбца в таблице

% % лишняя (можно вместо C использовать R)

% block_bitrate = block_bitrate + table_len(R,Z+1) + C;

%end

% добавляем 4 бита на символ конца блока

%block_bitrate = block_bitrate + 4;

%---------------------------------------------------------

% Вариант 2 - с векторной обработкой

% сначала находим смещение каждого ненулевого коэффициента от

% предыдущего. Для этого просто сдвигаем вектор индексов на 1 и поэлементно

% вычитаем из исходного

nz_ind_shift = nz_ind(1:(snd-1)); % берем только первые SND-1 ненулевых коэффициентов

Z = nz_ind(2:snd) - nz_ind_shift; % вычитаем их из первого (кроме первого эл-нта)

вектора

x = linear_block(nz_ind(2:size(nz_ind,2))); % берем вектор самих значений

R = ceil(log2(abs(x))) + 1; % рассчитываем количество битов

C = R; % запомнить (лишняя, можно вместо C исп-ть R

ind = (Z-1)*N+R; % находим линейные индексы для таблицы

block_bitrate = sum(table_len(ind) + C) + 4; % суммируем длины кодовых слов и C + 4 бита (EOB)

%--------------------------------------------------------------------------

Главный модуль JPEG_Analysis.m

function varargout = JPEG_Analysis(varargin)

% Инициализационный блок, сгенерированный GUIDE

gui_Singleton = 1;

gui_State = struct('gui_Name', mfilename, ...

'gui_Singleton', gui_Singleton, ...

'gui_OpeningFcn', @JPEG_Analysis_OpeningFcn, ...

'gui_OutputFcn', @JPEG_Analysis_OutputFcn, ...

'gui_LayoutFcn', [] , ...

'gui_Callback', []);

if nargin && ischar(varargin{1})

gui_State.gui_Callback = str2func(varargin{1});

end

if nargout

[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});

Page 50: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

50

else

gui_mainfcn(gui_State, varargin{:});

end

% Окончание инициализационного блока

%-----------------------------------------------------------------------

%-----------------------------------------------------------------------

% --- Выполняется непосредственно перед визуализацией формы

% --- Сгенерирован GUIDE

%-----------------------------------------------------------------------

function JPEG_Analysis_OpeningFcn(hObject, eventdata, handles, varargin)

% Choose default command line output for JPEG_Analysis

handles.output = hObject;

% Update handles structure

guidata(hObject, handles);

% UIWAIT makes JPEG_Analysis wait for user response (see UIRESUME)

% uiwait(handles.figure1);

%-----------------------------------------------------------------------

%-----------------------------------------------------------------------

% --- Выполняется непосредственно перед возвратом управления из функции

% --- Сгенерирован GUIDE

%-----------------------------------------------------------------------

function varargout = JPEG_Analysis_OutputFcn(hObject, eventdata, handles)

% Get default command line output from handles structure

varargout{1} = handles.output;

%-----------------------------------------------------------------------

%-----------------------------------------------------------------

% --- Обработка нажатия на кнопку "Выбрать изображение"

%-----------------------------------------------------------------

function pushbutton_LoadImage_Callback(hObject, eventdata, handles)

global SrcImage

global Params

% Вызов стандартного диалогового окна для выбора файла.

% Назначаем фильтр "*.bmp".

% Возвращаемые параметры - имя файла и путь к файлу

[fname, pname] = uigetfile( {'*.bmp', 'bmp-файл'}, ... % фильтр и его отображение

'Выберите файл изображения'); % заголовок диалога

if fname~=0 % если файл выбран

si = imread(fname, 'BMP'); % загрузить из файла и преобразовать в double

% проверить, что изображение содержит только одну компоненту

if ndims(si)>2 % если цветное - то преобразовать в серое

SrcImage = double(rgb2gray(si));

else

SrcImage = double(si);

end

% показать исходное изображение

axes(handles.axes_SrcImage); % активируем нужный элемент управления

imshow(SrcImage, [0 255]); % выводим в него изображение

end

%------------------------------------------------------------------

%------------------------------------------------------------------

Page 51: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

51

% --- Считывание с формы параметров кодирования

% --- Не является callback-функцией

%------------------------------------------------------------------

function read_params(hObject, eventdata, handles)

global Params

% взять выбранный размер блока

% прочитать в выпадающем списке (popupmenu) выбранную строку вида "99 x 99"

% до первого пробела и преобразовать подстроку в число

sfd = get(handles.popupmenu_BlockSize, 'String');

Params.BlockSize = str2num(strtok(sfd{get(handles.popupmenu_BlockSize, 'Value')}));

% прочитать параметр качества кодирования

Params.Quality = round(get(handles.slider_Quality, 'Value'));

% режим кодирования коэффициентов ДКП

Params.CodeNonZero = get(handles.radiobutton_CodeNonZero, 'Value');

% количество оставляемых ДКП коэффициентов

Params.NumFirstDCTCoefs = 0;

if (Params.CodeNonZero == 0) % если надо кодировать только первые коэффициенты

Params.NumFirstDCTCoefs = uint16(str2num(get(handles.edit_NumFirstDCTCoefs, 'String')));

% проверить, чтобы число оставляемых коэффициентов было не больше

% числа коэффциентов в блоке. Если что – скорректировать

if (Params.NumFirstDCTCoefs > Params.BlockSize*Params.BlockSize )

Params.NumFirstDCTCoefs = Params.BlockSize*Params.BlockSize;

set(handles.edit_NumFirstDCTCoefs, 'String', num2str(Params.NumFirstDCTCoefs));

end

end

%------------------------------------------------------------------

%------------------------------------------------------------------

% --- Отображение всех ДКП-поверхностей для иллюстрации

% --- Вызывается при нажатии на кнопку pushbutton_ShowDCTCoefs

%------------------------------------------------------------------

function pushbutton_ShowDCTCoefs_Callback(hObject, eventdata, handles)

global Params

% для наглядности вводим коэффициент "растяжения" поверхности

% (масштабирования по горизонтали)

resolution = 10;

% считать с формы параметры кодирования

read_params(hObject, eventdata, handles);

figure; % открываем новое окно

N = Params.BlockSize;

for k = 1:N

for l = 1:N

subplot( N, N,(k-1)*N+l ); % выбираем часть окна для вывода графика

% формируем матрицу для получения формы базисной функции

in = zeros(N*resolution);

in(k,l) = 1; % "тестовый сигнал" для оценки отклика

% выполнить прямое ДКП

out = dct2(in);

mesh(out); % вывести в заданной части окна

axis off; % отключить вывод числовых осей на графике

end

end

%-----------------------------------------------------------------

Page 52: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

52

%---------------------------------------------------------

% --- Отображение всех коэффициентов масштабирования для иллюстрации

% --- Вызывается при нажатии на кнопку pushbutton_ShowQuantCoefs

%---------------------------------------------------------

function pushbutton_ShowQuantCoefs_Callback(hObject, eventdata, handles)

global Params

% считать с формы параметры кодирования

read_params(hObject, eventdata, handles);

% рассчитать и показать коэффициенты квантования на отдельной форме

figure;

bar3(Generate_Scales(Params.BlockSize, Params.Quality));

%------------------------------------------------------------------

%------------------------------------------------------------------

% --- Выполнить процедуру кодирования изображения

% --- Вызывается при нажатии на кнопку pushbutton_RunCoding

%------------------------------------------------------------------

function pushbutton_RunCoding_Callback(hObject, eventdata, handles)

global Params

global SrcImage

global DstImage

global DCT_Image

global DeScaleDCT_Image

% читаем размеры изображения

Params.ImageSize = size(SrcImage);

% взять остальные параметры кодирования

read_params(hObject, eventdata, handles);

% Проверить размеры изображения на кратность заданым размерам блока ДКП

% если есть хотя бы один ненулевой остаток от деления размера изображения

% на размер блока ДКП - то ничего не делать

if (any(rem(Params.ImageSize, Params.BlockSize)))

return

end

Params.NumBlocks = uint16(Params.ImageSize / Params.BlockSize); % количество блоков

% показать сообщение о начале кодирования

set(handles.text_CodingProgress, 'String', 'Выполняется кодирование...');

drawnow; % принудительно вывести на экран

%----- КОДЕР -------

% выполнить кодирование

DCT_Image = Im2DCT(SrcImage); % прямое ДКП

Scale_Image = DCT2Scale(DCT_Image); % квантование коэффициентов ДКП

% выстроить коэффициенты в вектор

Linear_Coefs = Scale2Zigzag(Scale_Image); % обойти матрицу зигзагом

% обрезать коэффициенты (обнулить лишние)

[Cut_Coefs, NumC] = CutCoefs(Linear_Coefs); % оставить сколько надо коэффициентов

%---- КОНЕЦ КОДЕРА -------

% оценить коэффициент компрессии: размер исходного изображения в битах

% делить на размер сжатых даных

Params.CompressionRatio = (Params.ImageSize(1)*Params.ImageSize(2)*8) /

EstimateBitRate(Cut_Coefs);

%----- ДЕКОДЕР -------

DeScale_Image = Zigzag2Scale(Cut_Coefs); % сворачивание матрицы из вектора коэффициентов

DeScaleDCT_Image = Scale2DCT(DeScale_Image); % деквантование коэффициентов ДКП

Page 53: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

53

DstImage = DCT2Im(DeScaleDCT_Image); % обратное ДКП

%---- КОНЕЦ ДЕКОДЕРА -------

% оценить качество кодирования (сигнал-шум)

Params.SN_ratio = SNR(SrcImage, DstImage);

% показать восстановленное изображение

axes(handles.axes_DstImage); % активируем нужный элемент управления

imshow(DstImage, [0 255]); % выводим в него изображение

% показать коэффициент компрессии

set(handles.text_CompressionRatio, 'String', ...

strcat('Коэффициент компрессии изображения (раз) = ', ...

num2str(Params.CompressionRatio)));

set(handles.text_SNR, 'String', strcat('Отношение сигнал/шум (дБ) = ', ...

num2str(Params.SN_ratio)));

% вывести сообщение об окончании кодирования

set(handles.text_CodingProgress, 'String', 'Кодирование завершено');

%---------------------------------------------------------------------

%---------------------------------------------------------------------

% --- Выполнение ДКП для изображения

%---------------------------------------------------------------------

function [out_image] = Im2DCT(in_image)

global Params

out_image = zeros(Params.ImageSize); % создаем матрицу для хранения ДКП

% проходим по всем блокам заданного размера

d = uint16(Params.BlockSize); % d – размер блока по каждой оси

% в цикле используем векторизацию – за один раз рассчитываем

% сразу целый блок благодаря использованию конструкций [1:d]

for m = 0:Params.NumBlocks(1)-1 % количество блоков по вертикали

for n = 0:Params.NumBlocks(2)-1 % количество блоков по горизонтали

out_image(m*d+[1:d], n*d+[1:d]) = dct2(in_image(m*d+[1:d], n*d+[1:d]));

end

end

%---------------------------------------------------------------------

%---------------------------------------------------------------------

% --- Выполнение обратного ДКП для изображения

%---------------------------------------------------------------------

function [out_image] = DCT2Im(in_image)

global Params

out_image = zeros(Params.ImageSize); % создаем матрицу для хранения восст. изображения

% проходим по всем блокам заданного размера

d = uint16(Params.BlockSize); % d – размер блока по каждой оси

% в цикле используем векторизацию – за один раз рассчитываем

% сразу целый блок благодаря использованию конструкций [1:d]

for m = 0:Params.NumBlocks(1)-1 % количество блоков по вертикали

for n = 0:Params.NumBlocks(2)-1 % количество блоков по горизонтали

out_image(m*d+[1:d], n*d+[1:d]) = idct2(in_image(m*d+[1:d], n*d+[1:d]));

end

end

%---------------------------------------------------------------------

Page 54: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

54

%---------------------------------------------------------------------

% --- Масштабирование ДКП-коэффициентов

%---------------------------------------------------------------------

function [out_image] = DCT2Scale(in_image)

global Params

out_image = zeros(Params.ImageSize); % создаем матрицу для квант. коэффициентов

% сгенерировать коэффициенты масштабирования

coef_scales = Generate_Scales(Params.BlockSize, Params.Quality);

d = uint16(Params.BlockSize); % d – размер блока по каждой оси

% проходим по всем блокам заданного размера

for m = 0:Params.NumBlocks(1)-1 % количество блоков по вертикали

for n = 0:Params.NumBlocks(2)-1 % количество блоков по горизонтали

out_image(m*d+[1:d], n*d+[1:d]) = round(in_image(m*d+[1:d], n*d+[1:d]) ...

./ coef_scales); % округлить после деления

end

end

%---------------------------------------------------------------------

%---------------------------------------------------------------------

% --- Демасштабирование ДКП-коэффициентов

%---------------------------------------------------------------------

function out_image = Scale2DCT(in_image)

global Params

out_image = zeros(Params.ImageSize); % создаем матрицу для хранения восст. коэффициентов

% сгенерировать коэффициенты масштабирования

coef_descales = Generate_Scales(Params.BlockSize, Params.Quality);

d = uint16(Params.BlockSize); % d – размер блока по каждой оси

% проходим по всем блокам заданного размера

for m = 0:Params.NumBlocks(1)-1 % количество блоков по вертикали

for n = 0:Params.NumBlocks(2)-1 % количество блоков по горизонтали

out_image(m*d+[1:d], n*d+[1:d]) = in_image(m*d+[1:d], n*d+[1:d]) .* coef_descales;

end

end

%---------------------------------------------------------------------

%----------------------------------------------------------------------

% --- Обход матрицы зигзагом и вытаскивание коэффициентов в вектор

%----------------------------------------------------------------------

function linear_coefs = Scale2Zigzag(in_image)

global Params

% заранее выделить место под линейное хранение коэффициентов

% двумерный массив. Число строк – полное число блоков, число столбцов –

% количество элементов в блоке

linear_coefs = zeros(Params.NumBlocks(1)*Params.NumBlocks(2), ...

Params.BlockSize*Params.BlockSize);

% сформировать последовательность индексов для обхода зигзагом

% формируются индексы и в матричной форме и в линейной (для самопроверки)

% после тестирования достаточно оставить только линейную форму

[zigzag_ind, zigzag_ind_l] = Generate_Zigzag(Params.BlockSize);

% проходим по всем блокам заданного размера

d = uint16(Params.BlockSize); % d – размер блока по каждой оси

Page 55: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

55

t = d*d; % t – число элементов в блоке

p = 1; % храним в новом массиве

for m = 0:Params.NumBlocks(1)-1 % количество блоков по вертикали

for n = 0:Params.NumBlocks(2)-1 % количество блоков по горизонтали

ttt = UnrollMatrix(in_image(m*d+[1:d], n*d+[1:d]), zigzag_ind, zigzag_ind_l);

linear_coefs(p, :) = ttt; % запомнить результат

p = p+1; % перейти к следующему блоку

end

end

%---------------------------------------------------------------------

%---------------------------------------------------------------------

% --- Проход вектора и формирование матрицы зигзагом

%---------------------------------------------------------------------

function out_image = Zigzag2Scale(linear_coefs)

global Params

% заранее выделить место под матрицу

out_image = zeros(Params.ImageSize(1),Params.ImageSize(2));

% сформировать последовательность индексов для обхода зигзагом

% формируются индексы и в матричной форме и в линейной (для самопроверки)

% после тестирования достаточно оставить только линейную форму

[zigzag_ind, zigzag_ind_l] = Generate_Zigzag(Params.BlockSize);

% проходим по всем блокам заданного размера

d = uint16(Params.BlockSize); % d – размер блока по каждой оси

t = d*d; % t – число элементов в блоке

p = 1; % храним в новом массиве

for m = 0:Params.NumBlocks(1)-1 % количество блоков по вертикали

for n = 0:Params.NumBlocks(2)-1 % количество блоков по горизонтали

out_image(m*d+[1:d], n*d+[1:d]) = RollMatrix(linear_coefs(p, :), ...

zigzag_ind, zigzag_ind_l);

p = p+1;

end

end

%--------------------------------------------------------------------

%--------------------------------------------------------------------

% --- Обрезание числа коэффициентов

%--------------------------------------------------------------------

function [cut_linear_coefs, num_coefs] = CutCoefs(linear_coefs)

global Params

% выделяем память под массивы "обрезанных" коэффициентов

cut_linear_coefs = zeros(Params.NumBlocks(1)*Params.NumBlocks(2), ...

Params.BlockSize*Params.BlockSize);

% и под массив количества коэффициентов в каждом блоке

num_coefs = zeros(Params.NumBlocks(1)*Params.NumBlocks(2),1);

% вспомогательные временные переменные – для краткости

d = uint16(Params.BlockSize);

t = d*d;

% в зависимости от установленного способа кодирования коэффициентов ДКП

switch Params.CodeNonZero

case 0 % кодировать заданное число коэффициентов

% строим маску, одинаковую для всех блоков

mask = ones(1, Params.NumFirstDCTCoefs);

if Params.NumFirstDCTCoefs < t

add_mask = zeros(1, t-Params.NumFirstDCTCoefs);

mask = [mask add_mask];

Page 56: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

56

end

% проходим по всем блокам заданного размера

for m = 1:Params.NumBlocks(1)*Params.NumBlocks(2) % количество линейных блоков

cut_linear_coefs(m, :) = linear_coefs(m, :) .* mask;% обнуляем лишние коэффициенты

num_coefs(m+1) = Params.NumFirstDCTCoefs; % количество коэффициентов !=0

end

case 1 % кодировать все ненулевые коэффициенты

% проходим по всем блокам заданного размера

for m = 1:Params.NumBlocks(1)*Params.NumBlocks(2) % количество линейных блоков

% находим индекс последнего коэффициента, неравного 0

last_non_zero_ind = find(linear_coefs(m, :), 1, 'last');

% строим маску с необходимым числом единиц и нулей

if (last_non_zero_ind == t) % чтобы в цикле избежать изменения размера

mask = ones(1, last_non_zero_ind);

elseif isempty(last_non_zero_ind) % хотя бы один коэффициент должен быть

last_non_zero_ind = 1;

mask = [ones(1, last_non_zero_ind) zeros(1, t-last_non_zero_ind)];

else

mask = [ones(1, last_non_zero_ind) zeros(1, t-last_non_zero_ind)];

end

cut_linear_coefs(m, :) = linear_coefs(m, :) .* mask; % обнуляем лишние коэффициенты

num_coefs(m+1) = last_non_zero_ind; % количество коэффициентов !=0

end

end

%----------------------------------------------------------------------

%----------------------------------------------------------------------

% --- Оценка размера компрессированных данных

%----------------------------------------------------------------------

function [c_ratio] = EstimateBitRate(cut_linear_coefs)

global Params

c_ratio = 0;

% сформировать примерные длины кодов Хаффмана

table_code_len = Generate_Scales(Params.BlockSize*Params.BlockSize, 0);

% проходим по всем блокам заданного размера

pDC = 0; % последний DC-коэф. сначала = 0

for m = 1:Params.NumBlocks(1)*Params.NumBlocks(2) % количество линейных блоков

% рассчитать размер каждого блока

s = EstimateBlockBitRate(cut_linear_coefs(m, :), pDC, table_code_len);

pDC = cut_linear_coefs(m, 1); % запомнить последний DC

c_ratio = c_ratio + s; % суммируем по всему изображению

end

%----------------------------------------------------------------------

%-----------------------------------------------------------------------

% --- Обработка нажатия кнопки мыши над формой. Используется для выбора

% --- блока на исходном изображении и вывода детальной информации о его

% --- кодировании

%-----------------------------------------------------------------------

function figure1_WindowButtonDownFcn(hObject, eventdata, handles)

global Params

global SrcImage

global DstImage

global DCT_Image

global DeScaleDCT_Image

% определяем попадание координат в область исходного изображения

pt = get(handles.axes_SrcImage, 'currentpoint');

Page 57: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

57

cp(1,1) = pt(1, 2);

cp(1,2) = pt(1, 1);

% по смещению от начала области изображения определяем номер блока

num_block = floor(cp ./ Params.BlockSize);

% показать исходный блок

SrcBlockImage = SrcImage(num_block(1)*(Params.BlockSize) + [1:Params.BlockSize], ...

num_block(2)*(Params.BlockSize) + [1:Params.BlockSize]);

axes(handles.axes_SrcBlock); % активируем нужный элемент управления

imshow(SrcBlockImage, [0 255]); % выводим в него изображение

% показать восстановленный блок

DstBlockImage = DstImage(num_block(1)*(Params.BlockSize) + [1:Params.BlockSize], ...

num_block(2)*(Params.BlockSize) + [1:Params.BlockSize]);

axes(handles.axes_DstBlock); % активируем нужный элемент управления

imshow(DstBlockImage, [0 255]); % выводим в него изображение

% показать таблицу исходных коэффициентов ДКП

d = uint16(Params.BlockSize); % количество элементов в стороне блока

hdr_c = cell(1, Params.BlockSize); % место под заголовки столбцов

width_c = cell(1, Params.BlockSize); % место под ширины столбцов

hdr_r = cell(Params.BlockSize, 1); % место под заголовки строк

for i=1:Params.BlockSize

hdr_c{1, i} = num2str(i); % заголовки – просто номера строк и столбцов

width_c{1, i} = 'auto'; % ширина – "автоподбор"

hdr_r{i, 1} = num2str(i);

end

% установить параметры обеих таблиц одинаковыми

% исходные коэффициенты

set(handles.uitable_TableSrcBlock, 'ColumnName', hdr_c);

set(handles.uitable_TableSrcBlock, 'ColumnWidth', width_c);

set(handles.uitable_TableSrcBlock, 'RowName', hdr_r);

set(handles.uitable_TableSrcBlock, 'Data', DCT_Image(num_block(1)*d+[1:d], ...

num_block(2)*d+[1:d]));

% коэффициенты после квантования-деквантования

set(handles.uitable_TableDstBlock, 'ColumnName', hdr_c);

set(handles.uitable_TableDstBlock, 'ColumnWidth', width_c);

set(handles.uitable_TableDstBlock, 'RowName', hdr_r);

set(handles.uitable_TableDstBlock, 'Data', DeScaleDCT_Image(num_block(1)*d+[1:d], ...

num_block(2)*d+[1:d]));

%------------------------------------------------------------------------

%-------------------------------------------------------------------------

% --- Вывести исходное изображение в отдельном окне

% --- Вызывается при нажатии на кнопку pushbutton5

%-------------------------------------------------------------------------

function pushbutton5_Callback(hObject, eventdata, handles)

% hObject handle to pushbutton5 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

global SrcImage

figure; % новое окно

imshow(SrcImage, [0 255]); % принудительно установить диапазон амплитуд для double

%-------------------------------------------------------------------------

%-------------------------------------------------------------------------

Page 58: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

58

% --- Вывести декодированное изображение в отдельном окне

% --- Вызывается при нажатии на кнопку pushbutton6

%-------------------------------------------------------------------------

function pushbutton6_Callback(hObject, eventdata, handles)

% hObject handle to pushbutton6 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

global DstImage

figure; % новое окно

imshow(DstImage, [0 255]); % принудительно установить диапазон амплитуд для double

%-------------------------------------------------------------------------

%-------------------------------------------------------------------------

% --- Оценить значение полосы прокрутки и вывести в текстовое поле

% --- Вызывается при смещении ползунка

%-------------------------------------------------------------------------

function slider_Quality_Callback(hObject, eventdata, handles)

% параметр качества кодирования

st = round(get(hObject, 'Value'));

% вывести в числовом виде в более понятном представлении

% 1 – мин, 100 – макс

set(handles.text_Quality, 'String', num2str(100-st+1));

%-------------------------------------------------------------------------

%-------------------------------------------------------------------------

% Приведенные ниже функции (шаблоны) сгенерированы GUIDE и при разработке

% программы не использовались и не модифицировались

%-------------------------------------------------------------------------

function edit_Quality_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function slider_Quality_CreateFcn(hObject, eventdata, handles)

if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor',[.9 .9 .9]);

end

function edit4_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function listbox1_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function popupmenu_BlockSize_Callback(hObject, eventdata, handles)

function popupmenu_BlockSize_CreateFcn(hObject, eventdata, handles)

Page 59: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

59

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function edit_NumFirstDCTCoefs_Callback(hObject, eventdata, handles)

function edit_NumFirstDCTCoefs_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function edit_DCTCoefsBitRate_Callback(hObject, eventdata, handles)

function edit_DCTCoefsBitRate_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

%------------------------------------------------------------------------

Задания на лабораторную работу

Разработать программу, выполняющую компрессию и декомпрессию цветного

изображения. При кодировании программа должна выполнять несколько этапов обработки:

1) перевод изображения из цветового пространства RGB в другое пространство в

соответствии с вариантом заданием

2) понижение частоты дискретизации одной или двух компонент в соответствии с вариантом

задания

3) обработка каждой компоненты с использованием некоторого преобразования (согласно

варианту задания) с целью декорреляции элементов изображения

4) выбор наиболее значимых коэффициентов преобразования и отбрасывание остальных

алгоритмов (по собственному алгоритму, у которого должен быть варьируемый параметр)

5) для заданного фиксированного числа битов на каждый коэффициент оценить

планируемый размер закодированного изображения (не выполняя кодирования коэффициентов)

При декодировании порядок выполнения этапов, соответственно, обратный. После

декодирования необходимо оценить степень соответствия восстановленного изображения

исходному (качество кодирования).

Вариант №

Цветовое пространство

Фактор передискретизации

Вид преобразования Размеры блоков

1 YIQ 4 : 1 : 1 Дискретно-синусное 4х4, 8х8, 16х16

2 YCbCr 4 : 1 : 2 Дискретное

преобразование Фурье 8х8, 16х16

3 CIE Lab 4 : 2 : 1 Хаара 4х4, 8х8, 16х16,

32х32

Page 60: Н.Ш. Хусаинов Руководство к набору ...window.edu.ru/resource/332/60332/files/Full.pdf · 2015-01-12 · 2 УДК 681.3.06 (076.5) + 681.325.5. (076.5)

60

Вариант №

Цветовое пространство

Фактор передискретизации

Вид преобразования Размеры блоков

4 YIQ 4 : 2 : 2 Уолша-Адамара 4х4, 8х8, 16х16,

32х32

5 YCbCr 4 : 2 : 1 Карунена-Лоэва компонента

целиком

6 CIE Lab 4 : 1 : 2 Хотеллинга компонента

целиком

По результатам выполнения лабораторной работы провести эксперименты по оценке

влияния параметра алгоритма отбора наиболее значимых коэффициентов преобразования на

качество кодирования и степень компрессии.