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

Этот пример показывает реализацию традиционного конвейера обработки фотоаппарата, который отображает изображение RGB из изображения массива цветных фильтров RAW Bayer-pattern (CFA). В примере также показан альтернативный рабочий процесс создания RGB с использованием функций поддержки формата RAW файла в тулбоксе, таких как rawread, rawinfo, и raw2rgb.

Введение

Цифровые однообъективные рефлекторные (DSLR) камеры, а также многие современные телефонные камеры могут сохранять данные, собранные с датчика камеры, непосредственно в файл RAW. Каждый пиксель данных RAW является количеством света, захваченным соответствующим фотосенсором камеры. Данные зависят от фиксированных характеристик оборудования камеры, таких как чувствительность каждого фотосенсора к конкретной области значений длин волн электромагнитного спектра. Данные также зависят от настроек захвата камеры, таких как время экспозиции, и факторов сцены, таких как источник света.

Это основные шаги обработки в традиционном конвейере обработки камер:

  1. Импортируйте содержимое файла RAW

  2. Линеаризация полученного изображения CFA

  3. Масштабируйте данные CFA в соответствующую область значений

  4. Применить регулировку белого баланса

  5. Демосаика и вращение

  6. Преобразуйте изображение CFA в изображение RGB

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

Импорт содержимого Файла RAW

Камеры получают изображения и создают файлы. Эти RAW- файлы содержат:

  • Изображение CFA, записанное фотосенсором камеры

  • Метаданные, которые содержат всю информацию, необходимую для визуализации изображения RGB

Хотя RAW- файла может также содержать сгенерированное камерой предварительное изображение JPEG или миниатюру JPEG, для реализации конвейера камер вам нужно только изображение CFA и метаданные.

Чтение тестового изображения CFA из файла с помощью rawread и отобразите его.

fileName = "colorCheckerTestImage.NEF";

cfaImage = rawread(fileName);
whos cfaImage
  Name             Size                 Bytes  Class     Attributes

  cfaImage      4012x6034            48416816  uint16              
imshow(cfaImage,[])
title("Linear CFA Image")

Figure contains an axes. The axes with title Linear CFA Image contains an object of type image.

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

Для примера используйте rawinfo функция для извлечения метаданных из тестового изображения CFA. В метаданных обратите внимание, что значение столбца в VisibleImageSize поле меньше, чем в CFAImageSize поле. The rawread функция по умолчанию считывает только видимый фрагмент CFA.

fileInfo = rawinfo(fileName);

if fileInfo.CFASensorType ~= "Bayer"
    error( "The input file %s has CFA Image created by a % sensor." + ...
           "The camera pipeline in this example will work only for a CFA Image created by a Bayer sensor", ...
           fileName,fileInfo.CFASensorType );
end

disp(fileInfo.ImageSizeInfo)
                 CFAImageSize: [4012 6080]
             VisibleImageSize: [4012 6034]
    VisibleImageStartLocation: [1 1]
             PixelAspectRatio: 1
                ImageRotation: 0
            RenderedImageSize: [4012 6034]

Линеаризация полученного изображения CFA

Многие камеры применяют нелинейное сжатие области значений к записанным сигналам перед хранением их в файлах RAW. Чтобы сгенерировать линейные данные, в процессе подготовки к преобразованию данных CFA, необходимо отменить это нелинейное сжатие области значений. Камеры обычно хранят это сжатие области значений как интерполяционную таблицу (LUT). Если камера не применяется областью значений сжатия, LUT содержит тождества отображения. The rawread функция автоматически применяет эту LUT к данным CFA и возвращает значения линеаризованного света.

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

linTable = fileInfo.ColorInfo.LinearizationTable;

plot((0:length(linTable)-1), fileInfo.ColorInfo.LinearizationTable) 
title("Linearization Table")

Figure contains an axes. The axes with title Linearization Table contains an object of type line.

Шкала изображения

Метаданные RAW файла включают значение черного уровня, fileInfo.ColorInfo.BlackLevel, и значение белого уровня fileInfo.ColorInfo.WhiteLevel. Область значений значений пикселей в изображении CFA [fileInfo.ColorInfo.BlackLevel, fileInfo.ColorInfo.WhiteLevel]. Можно использовать эти значения для масштабирования изображения.

Изображения RAW не имеют истинного черного значения. Даже когда затвор закрыт, электричество, протекающее через датчики, вызывает ненулевое количество фотонов. Камеры используют значение маскированных пикселей, чтобы вычислить черный уровень изображения CFA. Различные форматы файлов сообщают об этом черном уровне по-разному. Некоторые форматы файлов задают черный уровень как одно скалярное значение на канал изображения CFA. Другие форматы, такие как DNG, задают черный уровень как повторяющуюся область m на n, которая начинается в левом верхнем углу видимого фрагмента CFA.

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

blackLevel = fileInfo.ColorInfo.BlackLevel;
disp(blackLevel)
   0   0   0   0
if isvector(fileInfo.ColorInfo.BlackLevel)
    cfaMultiChannel = performPerChannelBlackLevelSub(cfaImage, fileInfo);
else
    cfa = performRegionBlackLevelSub(cfaImage, fileInfo);
    
    % Transforms an interleaved CFA into an (M/2-by-N/2-by-4) array, where
    % each plane corresponds to a specific color channel.
    
    % This transformation simplifies pipeline implementation
    cfaMultiChannel = raw2planar(cfa);
end

Чтобы исправить значения данных CFA меньше, чем значение черного уровня, зажимайте значения к 0.

cfaMultiChannel( cfaMultiChannel < 0 ) = 0;

Метаданные необработанного файла часто представляют белый уровень как максимальное значение, допустимое типом данных. Если это значение белого уровня намного выше, чем самое высокое значение в изображении, использование этого значения белого уровня для масштабирования приводит к тому, что изображение темнее, чем должно быть. Чтобы избежать этого, масштабируйте изображение CFA, используя максимальное значение пикселя, найденное в изображении.

cfaMultiChannel = double(cfaMultiChannel);

whiteLevel = max(cfaMultiChannel(:));
disp(whiteLevel)
        3366
scaledCFAMultiChannel = cfaMultiChannel ./ whiteLevel;

Применение регулировки белого баланса

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

Сначала получите значение баланса белого из метаданных.

camWB = fileInfo.ColorInfo.CameraAsTakenWhiteBalance;

Затем масштабируйте множители так, чтобы значения G каналы 1.

gLoc = strfind(fileInfo.CFALayout,"G"); 
gLoc = gLoc(1);
camWB = camWB/camWB(gLoc);

disp(camWB)
    1.9336    1.0000    1.0000    1.2656
wbMults = reshape(camWB,[1 1 numel(camWB)]);
wbCFAMultiChannel = scaledCFAMultiChannel .* wbMults;

Объедините каналы, чтобы создать чередующееся изображение CFA.

cfaWB = planar2raw(wbCFAMultiChannel);

Преобразуйте перемеженное изображение CFA в 16-битное изображение.

cfaWB = im2uint16(cfaWB);

Демосаика и вращение

Преобразуйте закодированное Байером изображение CFA в изображение труколора путем демозафикации и вращения его. Это изображение находится в линейном пространстве камеры.

camspaceRGB = demosaic(cfaWB,fileInfo.CFALayout);

camspaceRGB = imrotate(camspaceRGB,fileInfo.ImageSizeInfo.ImageRotation);

imshow(camspaceRGB) 
title("Rendered Image in Linear Camera Space")

Figure contains an axes. The axes with title Rendered Image in Linear Camera Space contains an object of type image.

Преобразование изображения CFA в изображение RGB

Преобразовать изображение CFA в изображение RGB можно либо с помощью функций преобразования пространства соединений профиля (PCS), либо с помощью матрицы преобразования, возвращенной в метаданных файла RAW.

Использование преобразования пространства соединений профиля

Преобразуйте изображение CFA в выходное цветовое пространство Adobe RGB 1998. Это преобразование состоит из следующих шагов:

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

  • Преобразуйте изображение из пространства подключения профиля XYZ в цветовое пространство Adobe RGB 1998.

cam2xyz = computeXYZTransformation(fileInfo);
xyzImage = imapplymatrix(cam2xyz,im2double(camspaceRGB));

% xyz2rgb function applies Gamma Correction for Adobe RGB 1998 color space
adobeRGBImage = xyz2rgb(xyzImage,"ColorSpace","adobe-rgb-1998","OutputType","uint16");

imshow(adobeRGBImage);
title("Rendered RGB Image in Adobe RGB 1998 Color Space");

Figure contains an axes. The axes with title Rendered RGB Image in Adobe RGB 1998 Color Space contains an object of type image.

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

Используйте матрицу преобразования в fileInfo.ColorInfo.CameraTosRGB поле метаданных файла CFA для преобразования изображения из линейного пространства камеры в линейное пространство sRGB.

% This transformation produces a linear sRGB image
srgbImageLinear = imapplymatrix(fileInfo.ColorInfo.CameraTosRGB, camspaceRGB,"uint16");

% Apply gamma correction for sRGB colorspace
srgbImage = lin2rgb(srgbImageLinear);

imshow(srgbImage)
title("Rendered RGB Image in sRGB Colorspace")

Figure contains an axes. The axes with title Rendered RGB Image in sRGB Colorspace contains an object of type image.

Сравнение трубопроводов

Как показывает этот пример, можно использовать общие функции тулбокса обработки изображений и метаданные RAW файла для преобразования изображения CFA в изображение sRGB. Это преобразование можно также выполнить с помощью raw2rgb функция. При использовании raw2rgb функция не обеспечивает такой же гибкости, как использование метаданных, результаты сопоставимы. The raw2rgb функция использует libraw 0.20.0 Библиотека обработки необработанных файлов. Сравните результат raw2rgb преобразование в преобразование PCS, для цветового пространства Adobe RGB 1998 и в преобразование метаданных для цветовых пространств sRGB.

adobeRGBReference = raw2rgb(fileName,"ColorSpace","adobe-rgb-1998");

montage({adobeRGBReference, adobeRGBImage},"Size",[1 2]);
title("Adobe RGB 1998 Images: Left Image: raw2rgb, Right Image: MATLAB Pipeline")

Figure contains an axes. The axes with title Adobe RGB 1998 Images: Left Image: raw2rgb, Right Image: MATLAB Pipeline contains an object of type image.

srgbReference = raw2rgb(fileName,"ColorSpace","srgb");

montage({srgbReference, srgbImage});
title("sRGB Images: Left Image: raw2rgb, Right Image: MATLAB Pipeline");

Figure contains an axes. The axes with title sRGB Images: Left Image: raw2rgb, Right Image: MATLAB Pipeline contains an object of type image.

Вспомогательные функции

The performPerChannelBlackLevelSub функция выполняет вычитание черного уровня, когда вы задаете черный уровень как скалярное значение в относительных каналах.

function cfa = performPerChannelBlackLevelSub(cfa, fileInfo)
    % Transforms an interleaved CFA into an (M/2-by-N/2-by-4) array, where
    % each plane corresponds to a specific color channel.
    
    % This transformation simplifies pipeline implementation
    cfa = raw2planar(cfa);
    
    blackLevel = fileInfo.ColorInfo.BlackLevel;
    blackLevel = reshape(blackLevel,[1 1 numel(blackLevel)]);
    
    cfa = cfa - blackLevel;
end

The performRegionBlackLevelSub функция выполняет вычитание черного уровня, когда вы задаете его по области m на n.

function cfa = performRegionBlackLevelSub(cfa,fileInfo)
    % The m-by-n black-level must be repeated periodically across the entire image 
    repeatDims = fileInfo.ImageSizeInfo.VisibleImageSize ./ size(fileInfo.ColorInfo.BlackLevel);
    blackLevel = repmat(fileInfo.ColorInfo.BlackLevel, repeatDims);
    
    cfa = cfa - blackLevel;
end

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

function cam2xyz = computeXYZTransformation(fileInfo)
    % The CameraToXYZ matrix imposes an RGB order i.e 
    % [X, Y, Z]' = fileInfo.ColorInfo.CameraToXYZ .* [R, G, B]'.
    
    % However, the order of values for white balance mutlipliers are as per
    % fileInfo.CFALayout. Hence, we have to reorder the multipliers to
    % ensure we are scaling the correct row of the CameraToXYZ matrix.
    wbIdx = strfind(fileInfo.CFALayout,"R");
    gidx = strfind(fileInfo.CFALayout,"G"); wbIdx(2) = gidx(1); 
    wbIdx(3) = strfind(fileInfo.CFALayout,"B");
    
    wbCoeffs = fileInfo.ColorInfo.D65WhiteBalance(wbIdx);
    
    cam2xyz = fileInfo.ColorInfo.CameraToXYZ ./ wbCoeffs;
end