В этом примере показано, как использовать blockproc вычислять статистику из больших изображений и затем использовать эту информацию для более точной обработки изображений в блоке. blockproc функция хорошо подходит для применения операции к изображению в блоке, сборки результатов и возврата их в виде нового изображения. Многие алгоритмы обработки изображений, однако, требуют «глобальной» информации об изображении, которая недоступна, когда рассматривается только один блок данных изображения за раз. Эти ограничения могут оказаться проблематичными при работе с изображениями, которые слишком велики для полной загрузки в память.
В этом примере выполняется задача, аналогичная задаче, описанной в примере «Улучшить многоспектральные цветные составные изображения», но адаптированная для больших изображений с использованием blockproc. Вы будете расширять видимые области файла Erdas LAN rio.lan. Эти типы методов обработки блоков обычно более полезны для больших изображений, но небольшое изображение будет работать с целью этого примера.
Используя blockproc, прочтите данные из rio.lan, файл, содержащий изображения тематического отображения Landsat в формате Erdas LAN. blockproc имеет встроенную поддержку только для чтения файлов TIFF и JPEG2000. Для чтения файлов других типов необходимо написать класс Image Adapter для поддержки операций ввода-вывода для конкретного формата файла. В этом примере используется предварительно созданный класс Image Adapter, LanAdapter, который поддерживает чтение файлов LAN. Дополнительные сведения о записи классов адаптера изображения см. в разделе Выполнение блочной обработки файлов изображений в неподдерживаемых форматах.
Формат локальной сети Erdas содержит видимый красный, зеленый и синий спектр в диапазонах 3, 2 и 1 соответственно. Использовать blockproc для извлечения видимых полос в изображение RGB.
Создайте объект LanAdapter, связанный с rio.lan.
input_adapter = LanAdapter('rio.lan');Выберите видимые области R, G и B.
input_adapter.SelectedBands = [3 2 1];
Создайте функцию блока, чтобы просто вернуть данные блока без изменений.
identityFcn = @(block_struct) block_struct.data;
Создайте исходное изображение цвета.
truecolor = blockproc(input_adapter,[100 100],identityFcn);
Просмотрите результаты перед расширением.
imshow(truecolor)
title('Truecolor Composite (Not Enhanced)')
Результирующее изображение truecolor аналогично изображению paris.lan в примере «Расширение многоспектральных цветных составных изображений». Изображение RGB выглядит тусклым, с небольшим контрастом.
Сначала попробуйте растянуть данные в динамическом диапазоне с помощью blockproc. Эта первая попытка просто определяет новый дескриптор функции, который вызывает stretchlim и imadjust по каждому блоку данных по отдельности.
adjustFcn = @(block_struct) imadjust(block_struct.data,... stretchlim(block_struct.data)); truecolor_enhanced = blockproc(input_adapter,[100 100],adjustFcn); imshow(truecolor_enhanced) title('Truecolor Composite with Blockwise Contrast Stretch')

Сразу видно, что результаты неверны. Проблема в том, что stretchlim функция вычисляет гистограмму на входном изображении и использует эту информацию для вычисления пределов растяжения. Поскольку каждый блок настраивается в отрыве от своих соседей, каждый блок вычисляет различные пределы из своей локальной гистограммы.
Чтобы проверить распределение данных по динамическому диапазону изображения, можно вычислить гистограмму для каждой из трех видимых полос.
При работе с достаточно большими изображениями нельзя просто позвонить imhist для создания гистограммы изображения. Одним из способов пошагового построения гистограммы является использование blockproc с классом, который суммирует гистограммы каждого блока при перемещении по изображению.
Осмотрите HistogramAccumulator класс.
type HistogramAccumulator% HistogramAccumulator Accumulate incremental histogram.
% HistogramAccumulator is a class that incrementally builds up a
% histogram for an image. This class is appropriate for use with 8-bit
% or 16-bit integer images and is for educational purposes ONLY.
% Copyright 2009 The MathWorks, Inc.
classdef HistogramAccumulator < handle
properties
Histogram
Range
end
methods
function obj = HistogramAccumulator()
obj.Range = [];
obj.Histogram = [];
end
function addToHistogram(obj,new_data)
if isempty(obj.Histogram)
obj.Range = double(0:intmax(class(new_data)));
obj.Histogram = hist(double(new_data(:)),obj.Range);
else
new_hist = hist(double(new_data(:)),obj.Range);
obj.Histogram = obj.Histogram + new_hist;
end
end
end
end
Класс представляет собой простую обертку вокруг hist функция, позволяющая добавлять данные к гистограмме инкрементно. Он не специфичен для blockproc. Соблюдайте следующее простое использование HistogramAccumulator класс.
Создать HistogramAccumulator объект.
hist_obj = HistogramAccumulator;
Разбейте образец изображения на 2 половины.
full_image = imread('liftingbody.png');
top_half = full_image(1:256,:);
bottom_half = full_image(257:end,:);Выполните пошаговое вычисление гистограммы.
addToHistogram(hist_obj,top_half); addToHistogram(hist_obj,bottom_half); computed_histogram = hist_obj.Histogram;
Сравните с результатами IMHIST.
normal_histogram = imhist(full_image);
Изучите результаты. Гистограммы численно идентичны.
figure subplot(1,2,1) stem(computed_histogram,'Marker','none') title('Incrementally Computed Histogram') subplot(1,2,2) stem(normal_histogram','Marker','none') title('IMHIST Histogram')

Теперь используйте HistogramAccumulator класс с blockproc для построения гистограммы красной полосы данных в rio.lan. Можно определить дескриптор функции для blockproc который вызовет addToHistogram способ на каждом блоке данных. Просматривая эту гистограмму, можно увидеть, что данные сконцентрированы в небольшой части доступного динамического диапазона. Другие видимые полосы имеют сходные распределения. Это одна из причин, почему оригинальный трюкоколоровый композит выглядит унылым.
Создайте объект HistingedAccumulator.
hist_obj = HistogramAccumulator;
Настроить blockproc дескриптор функции
addToHistFcn = @(block_struct) addToHistogram(hist_obj, block_struct.data);
Вычислите гистограмму красного канала. Обратите внимание, что addToHistFcn дескриптор функции генерирует любые выходные данные. Поскольку дескриптор функции передан blockproc ничего не возвращает, blockproc тоже ничего не вернет.
input_adapter.SelectedBands = 3; blockproc(input_adapter,[100 100],addToHistFcn); red_hist = hist_obj.Histogram;
Просмотрите результаты.
figure stem(red_hist,'Marker','none') title('Histogram of Red Band (Band 3)')

Теперь можно выполнить правильное растягивание контрастности изображения. Для обычных рабочих процессов в памяти можно просто использовать stretchlim функция для вычисления аргументов для imadjust (например, MultispectralImageEnhancementExample пример). При работе с большими изображениями, как мы видели, stretchlim не легко адаптируется для использования с blockproc поскольку она опирается на полную гистограмму изображения.
После вычисления гистограмм изображения для каждой видимой области вычислите соответствующие аргументы для imadjust от руки (аналогично тому, как stretchlim делает.
Сначала вычислите гистограммы для зеленой и синей полос.
hist_obj = HistogramAccumulator; addToHistFcn = @(block_struct) addToHistogram(hist_obj,block_struct.data); input_adapter.SelectedBands = 2; blockproc(input_adapter,[100 100],addToHistFcn); green_hist = hist_obj.Histogram; hist_obj = HistogramAccumulator; addToHistFcn = @(block_struct) addToHistogram(hist_obj,block_struct.data); input_adapter.SelectedBands = 1; blockproc(input_adapter,[100 100],addToHistFcn); blue_hist = hist_obj.Histogram;
Вычислите CDF каждой гистограммы.
computeCDF = @(histogram) cumsum(histogram) / sum(histogram); findLowerLimit = @(cdf) find(cdf > 0.01, 1, 'first'); findUpperLimit = @(cdf) find(cdf >= 0.99, 1, 'first'); red_cdf = computeCDF(red_hist); red_limits(1) = findLowerLimit(red_cdf); red_limits(2) = findUpperLimit(red_cdf); green_cdf = computeCDF(green_hist); green_limits(1) = findLowerLimit(green_cdf); green_limits(2) = findUpperLimit(green_cdf); blue_cdf = computeCDF(blue_hist); blue_limits(1) = findLowerLimit(blue_cdf); blue_limits(2) = findUpperLimit(blue_cdf);
Подготовьте аргумент для IMADJUST.
rgb_limits = [red_limits' green_limits' blue_limits'];
Масштабировать до диапазона [0, 1].
rgb_limits = (rgb_limits - 1) / (255);
Создание нового adjustFcn применение глобальных ограничений растяжения и использование blockproc для настройки цвета изображения.
adjustFcn = @(block_struct) imadjust(block_struct.data,rgb_limits);
Выберите полные данные RGB.
input_adapter.SelectedBands = [3 2 1]; truecolor_enhanced = blockproc(input_adapter,[100 100],adjustFcn);
Просмотрите результат. Получаемое изображение значительно улучшено, данные охватывают больше динамического диапазона и используются blockproc вы избегаете загрузки всего изображения в память.
imshow(truecolor_enhanced)
title('Truecolor Composite with Corrected Contrast Stretch')
blockproc | imadjust | imhist | stretchlim