Форум кафедры Техники и Электрофизики Высоких Напряжений

Онлайн-сообщество ТВНщиков
Гостям форума:

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


Текущее время: 11 дек 2019, 20:17

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 12 ] 
Автор Сообщение
СообщениеДобавлено: 11 ноя 2009, 14:52 
Не в сети
Site Admin

Зарегистрирован: 03 сен 2008, 16:09
Сообщения: 4290
Откуда: Д-3
По материалам семинара в группе Э-04-07 от 11 ноября 2009 г.

Каждое растровое изображение (рисунок, фотографию) можно хранить на компьютере двумя способами. Первый, наиболее естественный, - изображение представляют в виде матрицы размером NxMx3, где N - высота (число строк пикселей), M - ширина (число столбцов пикселей), а тройка - это три составляющих цвета (RGB - красный, зеленый, синий). Таким образом у каждого цветного изображения есть три слоя (три двумерных матрицы NxM), соответствующих трем компонентам цвета.

Второй способ хранения изображения - хранить не матрицу пикселей, а матрицу коэффициентов дискретного преобразования Фурье для этой матрицы. Мы рассмотрим простейший случай одномерного преобразования, имея в виду, что современные практические методы основаны на двумерных преобразованиях.

Самый верный способ освоить второй метод - это практика, поэтому подготовим для начала изображение. Во вложении к сообщению находится файл flower.tif, скачайте его и поместите в рабочий каталог Matlab.

Следующий код позволяет открыть файл с изображением в Matlab и показать его на экране.
Код:
img = imread('flower.tif');
imshow(img);

Результат отображения следующий:

Изображение

Для того, чтобы поначалу не тратить время на три цветовые составляющие, преобразуем изображение в оттенки серого.
Код:
gimg = rgb2gray(img);
imshow(gimg);

и увидим на экране черно-белую картинку:

Изображение

Переключаемся в Матлабе в окошко Workspace:

Изображение

и видим, что gimg - двумерная матрица 340 x 512, элементы которой имеют тип uint8 (unsigned integer 8 bit, то есть каждый элемент представлен беззнаковым целым числом, под которое выделено 8 бит (1 байт) памяти). Переменные такого типа имеют 2^8=256 различных значений от 0 до 255. Значение 0 соответствует черному цвету, 255 - белому.

Таким образом, полученная нами черно-белая картинка занимает в оперативной памяти 340*512*1 = 174080 байт.


У вас нет необходимых прав для просмотра вложений в этом сообщении.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 13 ноя 2009, 17:02 
Не в сети
Site Admin

Зарегистрирован: 03 сен 2008, 16:09
Сообщения: 4290
Откуда: Д-3
Сделаем для каждой строки матрицы gimg дискретное косинус-преобразование Фурье:

Код:
N = size(img, 1); % число строк матрицы gimg
M = size(img, 2); % число столбцов матрицы gimg

Mnew = M/2; % число коэффициентов Фурье, которое оставляем в спектре
for I=1:N % цикл по строкам матрицы gimg
    Ak=dct(gimg(I,:)); % получаем коэффициенты косинус-преобразования Фурье для I-й строки
    Ak_new(I,:) = Ak(1:Mnew); % оставляем только Mnew коэффициентов
end


В этом коде для каждой I-й строки матрицы gimg функция dct вычисляет коэффициенты косинус-преобразования Фурье и сохраняет в переменной Ak. Второй оператор внутри цикла создает новую переменную Ak_new, которая хранит только первые Mnew коэффициентов. Как следствие этого, размер матрицы коэффициентов уменьшается в два раза (Mnew = M/2) и это видно в окне Workspace:

Изображение

Теперь наше изображение хранится в матрице, размер которой двое меньше (320 x 256). Получить картинку в пиксельном виде можно с помощью обратного преобразования (функция idct):

Код:
for I=1:N
    gimg_new(I,:) = idct(Ak_new(I,:), M);
end
figure
imshow(uint8(gimg_new));


Изображение

Полученное изображение почти не отличается визуально от оригинала (впрочем, оно немного расплылось), однако мы использовали способ хранения информации в матрице в два раза меньшего размера. Эта идея и лежит в основе компрессии изображений - нужно хранить не матрицу пикселей, а матрицу коэффициентов Фурье, при этом можно отсечь часть этих коэффициентов, соответствующих высшим гармоническим.

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

Код:
figure
plot([1:M],gimg(1,:)); grid on;
xlim([1 M]); ylim([0 255]); xlabel('№ пикселя'); ylabel('Градации серого'); title('Первая строка изображения');


Изображение

График монотонный почти по всей ширине изображения (это небо, имеющее светло-серый цвет), а небольшой отрицательный выброс - темная травинка.
Применим к этой строке дискретное преобразование Фурье и построим спектр.
Код:
Ak1 = dct(double(gimg(1,:)));
figure; bar([1:M],Ak1); grid on;
xlim([1 M]); ylim([-50 50]); xlabel('№ гармоники'); ylabel('амплитуда гармоники'); title('Фурье-спектр для первой строки изображения');


Изображение

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

Проделаем такую же процедуру для средней строки матрицы:

Изображение

Изображение

Здесь градации серого резко меняются по ширине изображения. Это отражено и в спектре - высокочастотные составляющие стали больше по амплитуде. Поэтому, когда мы отбросили вторую половину спектра, изображение в средней части немного расплылось - исчезли высокочастотные составляющие, отвечающие за резкость изображения.

Влияние высоких частот на резкость можно увидеть яснее, если увеличить степень сжатия до 4, положив в m-коде Mnew = M/4.

Изображение

Верхняя часть изображения почти не пострадала (она не в фокусе и коэффициенты при высоких гармониках малы), а вот средняя часть "расфокусировалась" так как мы удалили высокие частоты.

M-файл с программным кодом для построения всех графиков находится во вложении.


У вас нет необходимых прав для просмотра вложений в этом сообщении.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 13 ноя 2009, 18:38 
Не в сети
Site Admin

Зарегистрирован: 03 сен 2008, 16:09
Сообщения: 4290
Откуда: Д-3
Слабым звеном этого повествования является то, что, несмотря на уменьшение размерности матрицы, выигрыша в оперативной памяти нет, так как коэффициенты Фурье хранятся в ячейках типа double (8 байт на коэффициент). Это поправимо, но усложнит код, а мне бы этого не хотелось.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 13 ноя 2009, 18:51 
Не в сети
Site Admin

Зарегистрирован: 03 сен 2008, 16:09
Сообщения: 4290
Откуда: Д-3
В завершение покажем, как можно решить задачу компрессии для цветного изображения. Никаких принципиальных сложностей нет, нужно обработать отдельно каждый цветовой слой.

Код:
clear
clc
img = imread('flower.tif');
imshow(img);

N = size(img, 1); % число строк матрицы img
M = size(img, 2); % число столбцов матрицы img

Mnew = M/2; % число коэффициентов Фурье, которое оставляем в спектре
for K=1:3
    for I=1:N
        Ak=dct(img(I,:,K)); % получаем коэффициенты косинус-преобразования Фурье для I-й строки
        Ak_new = Ak(1:Mnew); % оставляем только Mnew коэффициентов
        img_new(I,:,K) = idct(Ak_new, M); % обратное косинус-преобразование Фурье для I-й строки
    end
end
figure
imshow(uint8(img_new));


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

Оригинальное изображение:

Изображение

Двухкратная компрессия:

Изображение

Четырехкратная компрессия:

Изображение

Восьмикратная компрессия:

Изображение

Результаты аналогичны тому, что мы получили для изображения в оттенках серого. Сильная компрессия основательно "размывает" изображение и для практических задач сильной компрессии наш метод вряд ли приемлем. Тем не менее, он позволяет понять основную идею, заложенную во все современные методы цифровой обработки изображений. Этот раздел прикладной математики к настоящему времени уже сформировался, и мы каждый день пользуемся форматом JPEG (Joint Photographic Experts Group), в котором реализованы весьма сложные алгоритмы, базирующиеся на вейвлетных преобразованиях, которые, в свою очередь, основаны на модернизации дискретного преобразования Фурье.


У вас нет необходимых прав для просмотра вложений в этом сообщении.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 17 ноя 2009, 10:57 
Не в сети
Кибернетический организм
Аватара пользователя

Зарегистрирован: 03 сен 2008, 17:14
Сообщения: 202
Откуда: Д-3 =)
:idea: :prekl: :prekl: :prekl: :idea:

Очень здорово! :clap:

_________________
------------------------------------------
don't!.. don't believe what you see!...
don't!.. don't believe what you read!...
:krut:


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 17 ноя 2009, 11:53 
Не в сети
Кибернетический организм
Аватара пользователя

Зарегистрирован: 03 сен 2008, 17:14
Сообщения: 202
Откуда: Д-3 =)
оч. хорошо имитирует аберрации в линзах).

_________________
------------------------------------------
don't!.. don't believe what you see!...
don't!.. don't believe what you read!...
:krut:


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 23 ноя 2009, 18:16 
Не в сети

Зарегистрирован: 28 янв 2009, 15:39
Сообщения: 21
Очень интересная статья :idea:
А как производится компрессия звука и видео?
Интересно посмотреть на спекты какого нибудь звука в формате mp3 и flac например...
PS: ДА, Вам как обычно мегареспект :hat:


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 23 ноя 2009, 20:58 
Не в сети
Site Admin

Зарегистрирован: 03 сен 2008, 16:09
Сообщения: 4290
Откуда: Д-3
Компрессия звука тоже основана на исключении тех частот, которые имеют малую амплитуду, но для этого приходится делать преобразование Фурье с движущимся окном. Я планировал ввести вейвлеты в лекции по ФМО на третьем курсе, но не получается, не хватает времени. Поэтому решил, что через некоторое время просто сделаю доп. материал по курсу, в который войдет то, что считаю важным, но о чем не успеваю рассказать на лекциях.

Спектры во FLAC, кстати, должны быть такие же как у WAV-формата. А вот MP3 - да, отличия там видны хорошо, особенно если битрейт низкий :-)

:hat:
Спасибо за добрые слова.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 22 ноя 2011, 14:36 
Не в сети
Аватара пользователя

Зарегистрирован: 19 сен 2011, 00:38
Сообщения: 139
Откуда: Г-101
А у меня скорее технический вопрос.
Аналогичную программу ведь можно реализовать и на С++. Единственная проблема (и, наверно, самая сложная) - написать модуль работы с изображением. Как Mathlab разбивает файл на пиксели и слои RGB? По HEX или тут что-то совершенно иное? :-?

_________________
"Mathematics is the art of giving the same name to different things." - Jules Henri Poincare


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 22 ноя 2011, 18:46 
Не в сети
Site Admin

Зарегистрирован: 03 сен 2008, 16:09
Сообщения: 4290
Откуда: Д-3
Цветное изображение - это три матрицы, для красного, зеленого и синего цветов. Так что работать с ними несложно. Другое дело - формат файла. Битмап читается легко, а вот всякие jpeg требуют для получения из них матриц специальных библиотек. Но это реально, библиотеки С++ для работы с графическими форматами доступны.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 23 ноя 2011, 02:56 
Не в сети
Аватара пользователя

Зарегистрирован: 19 сен 2011, 00:38
Сообщения: 139
Откуда: Г-101
Ну, с библиотеками понятно. А если с нуля, каким образом эти матрицы сохраняются в файл, и по какому принципу осуществляется парсинг файлов для извлечения из них матриц?
На "высоком" уровне понятно, для каждого пикселя задается один из трех его цветов, а уж глаз наш их перемешивает, позволяя нам видеть целую картину.
Если открыть любой файл в НЕХ-эдиторе, видим матрицу из значений, с обозначением смещения. И все это в шестнадцатеричном формате. Вот многие лоадеры (из тех, что мне доводилось видеть на практике, с реализацией через MFC :oops: ) извлекают данные, преобразуя их из шестнадцатеричной системы, заносят в массив и следуют с заранее известным шагом. А тут как это дело происходит? По-идее, смещение - это же тоже адрес в памяти... :-?

_________________
"Mathematics is the art of giving the same name to different things." - Jules Henri Poincare


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
СообщениеДобавлено: 23 ноя 2011, 20:37 
Не в сети
Site Admin

Зарегистрирован: 03 сен 2008, 16:09
Сообщения: 4290
Откуда: Д-3
Вообще-то, все зависит от формата файла. Если речь идет о хранении битмапа, то в файле содержатся как раз матрицы для R,G и B.

Для хранения одного элемента такой матрицы нужен 1 байт. Все возможные значения переменной, занимающей 1 байт, можно описать двумя шестнадцатеричными числами: 00 -> 0, FF -> 255. Поэтому и используются hex-едиторы (для удобства работы с бинарными файлами). Программе же все равно - она оперирует с байтами, не задумываясь о системе представления чисел. Из дискового файла считывается поток байтов, и значение каждого байта помещается в матрицу в оперативной памяти, в случае C/C++ эта память обычно адресуется двойным указателем.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 12 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


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

Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB