Этот пример показывает реализацию традиционного конвейера обработки камеры, который представляет изображение RGB от НЕОБРАБОТАННОГО изображения массива цветового фильтра (CFA) шаблона Байера. Пример также показывает альтернативный рабочий процесс создания RGB с помощью НЕОБРАБОТАННЫХ функций поддержки формата файла в тулбоксе, таких как rawread
, rawinfo
, и raw2rgb
.
Камеры цифрового отражения одно линзы (DSLR) и много современных телефонных камер, могут сохранить данные, собранные от датчика камеры непосредственно к НЕОБРАБОТАННОМУ файлу. Каждый пиксель Необработанных данных является количеством света, полученным соответствующим фотодатчиком камеры. Данные зависят от фиксированных характеристик оборудования камеры, таких как чувствительность каждого фотодатчика к конкретной области значений длин волн электромагнитного спектра. Данные также зависят от настроек приобретения камеры, таких как выдержка и факторы сцены, такие как источник света.
Это основные шаги обработки в традиционном конвейере обработки камеры:
Импортируйте НЕОБРАБОТАННОЕ содержимое файла
Линеаризуйте полученное изображение CFA
Масштабируйте данные о CFA к подходящей области значений
Примените корректировку баланса белого
Demosaic и вращаются
Преобразуйте Изображение 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")
Много камер маскируют фрагмент фотодатчика, обычно в ребрах, чтобы препятствовать тому, чтобы те разделы получили любой свет. Это позволяет вам точно определить уровень черного датчика. Для таких камер количество пикселей в изображении меньше, чем количество пикселей в датчике.
Например, используйте 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, необходимо инвертировать это нелинейное сжатие области значений. Камеры обычно хранят это сжатие области значений как интерполяционную таблицу (LUT). Если камера не применяет сжатие области значений, LUT содержит единичное отображение. rawread
функция автоматически применяет этот LUT к данным о CFA и возвращает линеаризовавшие легкие значения.
Постройте подмножество значений в LinearizationTable
поле тестовых метаданных изображения.
linTable = fileInfo.ColorInfo.LinearizationTable;
plot((0:length(linTable)-1), fileInfo.ColorInfo.LinearizationTable)
title("Linearization Table")
НЕОБРАБОТАННЫЕ метаданные файла включают значение уровня черного, 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);
Преобразуйте закодированное Байером изображение CFA в изображение истинного цвета demosaicing и вращением его. Это изображение находится в линейном пространстве камеры.
camspaceRGB = demosaic(cfaWB,fileInfo.CFALayout);
camspaceRGB = imrotate(camspaceRGB,fileInfo.ImageSizeInfo.ImageRotation);
imshow(camspaceRGB)
title("Rendered Image in Linear Camera Space")
Можно преобразовать изображение 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");
Используйте матрицу преобразования в 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")
Когда этот пример показывает, можно использовать общие функции тулбокса обработки изображений и НЕОБРАБОТАННЫЕ метаданные файла, чтобы преобразовать изображение 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")
srgbReference = raw2rgb(fileName,"ColorSpace","srgb"); montage({srgbReference, srgbImage}); title("sRGB Images: Left Image: raw2rgb, Right Image: MATLAB Pipeline");
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