Этот пример показывает, как использовать blockproc
, чтобы вычислить статистику из больших изображений и затем использовать ту информацию, чтобы более точно обработать изображения blockwise. Функция blockproc
хорошо подходит для применения операции к изображению blockwise, сборки результатов и возврата их как новое изображение. Много алгоритмов обработки изображений, однако, запрашивают "глобальную" информацию об изображении, которое не доступно, когда вы только рассматриваете один блок данных изображения за один раз. Эти ограничения могут оказаться проблематичными при работе с изображениями, которые являются слишком большими, чтобы загрузить полностью в память.
Этот пример выполняет задачу, подобную найденному в Улучшающем Многоспектральном Цветном Составном примере Изображений, но адаптированный к большим изображениям с помощью blockproc
. Вы будете улучшать видимые полосы файла LAN Эрдаса rio.lan
. Эти типы методов обработки блока обычно более полезны для больших изображений, но маленькое изображение будет работать в целях этого примера.
Используя blockproc
, считанный данные из rio.lan
, файл, содержащий Landsat тематическое формирование изображений картопостроителя в формате файла LAN Эрдаса. blockproc
имеет встроенную поддержку чтения TIFF и файлов JPEG2000 только. Чтобы считать другие типы файлов, необходимо записать класс Адаптера Изображений, чтобы поддержать ввод-вывод для конкретного формата файла. Этот пример использует предварительно созданный класс Адаптера Изображений, LanAdapter
, который поддерживает файлы LAN чтения. Для получения дополнительной информации о записи классов Адаптера Изображений видят пример в Руководстве Пользователей, описывающем, как класс LanAdapter
был создан.
Формат LAN Эрдаса содержит видимый красный, зеленый, и синий спектр в полосах 3, 2, и 1, соответственно. Используйте blockproc
, чтобы извлечь видимые полосы в изображение RGB.
% Create the LanAdapter object associated with rio.lan. input_adapter = LanAdapter('rio.lan'); % Select the visible R, G, and B bands. input_adapter.SelectedBands = [3 2 1]; % Create a block function to simply return the block data unchanged. identityFcn = @(block_struct) block_struct.data; % Create the initial truecolor image. truecolor = blockproc(input_adapter,[100 100],identityFcn); % Display the un-enhanced results. figure; imshow(truecolor); title('Truecolor Composite (Un-enhanced)');
Получившееся изображение истинного цвета подобно тому из 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); figure 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
.
% Create the HistogramAccumulator object. hist_obj = HistogramAccumulator(); % Split a sample image into 2 halves. full_image = imread('liftingbody.png'); top_half = full_image(1:256,:); bottom_half = full_image(257:end,:); % Compute the histogram incrementally. addToHistogram(hist_obj, top_half); addToHistogram(hist_obj, bottom_half); computed_histogram = hist_obj.Histogram; % Compare against the results of IMHIST. normal_histogram = imhist(full_image); % Examine the results. The histograms are numerically identical. 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
на каждый блок данных. Путем просмотра этой гистограммы вы видите, что данные сконцентрированы в небольшой части доступного динамического диапазона. У других видимых полос есть подобные дистрибутивы. Это - одна причина, почему исходный составной объект истинного цвета кажется тусклым.
% Create the HistogramAccumulator object. hist_obj = HistogramAccumulator(); % Setup blockproc function handle addToHistFcn = @(block_struct) addToHistogram(hist_obj, block_struct.data); % Compute histogram of the red channel. Notice that the addToHistFcn % function handle does generate any output. Since the function handle we % are passing to blockproc does not return anything, blockproc will not % return anything either. input_adapter.SelectedBands = 3; blockproc(input_adapter,[100 100],addToHistFcn); red_hist = hist_obj.Histogram; % Display results. figure stem(red_hist,'Marker','none'); title('Histogram of Red Band (Band 3)');
Можно теперь выполнить соответствующий контрастный фрагмент на изображении. Для обычных, рабочих процессов в оперативной памяти можно просто использовать функцию stretchlim
, чтобы вычислить аргументы к imadjust
(как пример MultispectralImageEnhancementExample
, делает). При работе с большими изображениями, как мы видели, stretchlim
легко не адаптируется к использованию с blockproc
, поскольку это полагается на гистограмму полного образа.
Если вы вычислили гистограммы изображений для каждой из видимых полос, вычислите соответствующие аргументы к imadjust
вручную (подобный тому, как stretchlim
делает).
Сначала вычислите гистограммы для зеленых и синих полос.
% Compute histogram for green channel. 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; % Compute histogram for blue channel. 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 каждой гистограммы и подготовьтесь вызывать imadjust
.
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); % Prepare argument for IMADJUST. rgb_limits = [red_limits' green_limits' blue_limits']; % Scale to [0,1] range. rgb_limits = (rgb_limits - 1) / (255);
Создайте новый adjustFcn
, который применяется, глобальная переменная превышают лимиты и используют blockproc
, чтобы настроить изображение истинного цвета.
adjustFcn = @(block_struct) imadjust(block_struct.data,rgb_limits); % Select full RGB data. input_adapter.SelectedBands = [3 2 1]; truecolor_enhanced = blockproc(input_adapter,[100 100],adjustFcn); figure; imshow(truecolor_enhanced) title('Truecolor Composite with Corrected Contrast Stretch')
Получившееся изображение очень улучшено с данными, покрывающими больше динамического диапазона, и при помощи blockproc
вы стараетесь не загружать целое изображение в память.
blockproc
| imadjust
| imhist
| stretchlim