Сквозная реализация конвейера обработки цифрового фотоаппарата

Этот пример показывает реализацию традиционного конвейера обработки камеры, который представляет изображение RGB от НЕОБРАБОТАННОГО изображения массива цветового фильтра (CFA) шаблона Байера. Пример также показывает альтернативный рабочий процесс создания RGB с помощью НЕОБРАБОТАННЫХ функций поддержки формата файла в тулбоксе, таких как rawread, rawinfo, и raw2rgb.

Введение

Камеры цифрового отражения одно линзы (DSLR) и много современных телефонных камер, могут сохранить данные, собранные от датчика камеры непосредственно к НЕОБРАБОТАННОМУ файлу. Каждый пиксель Необработанных данных является количеством света, полученным соответствующим фотодатчиком камеры. Данные зависят от фиксированных характеристик оборудования камеры, таких как чувствительность каждого фотодатчика к конкретной области значений длин волн электромагнитного спектра. Данные также зависят от настроек приобретения камеры, таких как выдержка и факторы сцены, такие как источник света.

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

  1. Импортируйте НЕОБРАБОТАННОЕ содержимое файла

  2. Линеаризуйте полученное изображение CFA

  3. Масштабируйте данные о CFA к подходящей области значений

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

  5. Demosaic и вращаются

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

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

Импортируйте НЕОБРАБОТАННОЕ содержимое файла

Камеры получают изображения и создают НЕОБРАБОТАННЫЕ файлы. Эти НЕОБРАБОТАННЫЕ файлы содержат:

  • Изображение CFA зарегистрировано фотодатчиком камеры

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

В то время как НЕОБРАБОТАННЫЙ файл может также содержать сгенерированное камерой изображение предварительного просмотра 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 поле . 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

Много камер применяют нелинейное сжатие области значений к записанным сигналам прежде, чем сохранить их в НЕОБРАБОТАННЫХ файлах. Чтобы сгенерировать линейные данные, при подготовке к преобразованию данных о CFA, необходимо инвертировать это нелинейное сжатие области значений. Камеры обычно хранят это сжатие области значений как интерполяционную таблицу (LUT). Если камера не применяет сжатие области значений, LUT содержит единичное отображение. 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.

Масштабируйте изображение

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

НЕОБРАБОТАННЫЕ изображения не имеют истинного черного значения. Даже с закрытым затвором, электричество, текущее через датчики, вызывает ненулевые количества фотона. Камеры используют значение пикселей маскированных, чтобы вычислить уровень черного изображения 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);

Demosaic и Rotate

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

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) или при помощи матрицы преобразования, возвращенной в НЕОБРАБОТАННЫХ метаданных файла.

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

Преобразуйте изображение 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.

Используйте матрицу преобразования от НЕОБРАБОТАННЫХ метаданных файла

Используйте матрицу преобразования в 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.

Конвейерно обработайте сравнение

Когда этот пример показывает, можно использовать общие функции тулбокса обработки изображений и НЕОБРАБОТАННЫЕ метаданные файла, чтобы преобразовать изображение CFA в изображение sRGB. Можно также выполнить это преобразование при помощи raw2rgb функция. При использовании raw2rgb функция не обеспечивает ту же гибкость как использование метаданных, результаты сопоставимы. 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.

Функции помощника

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

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

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