簡體   English   中英

如何根據標准圖像校正圖像的顏色

[英]How to correct color of an image based on a standard image

請看圖:數字 image1 是要校正的圖像,image2 是在黑匣子中拍攝的標准圖像。 兩個圖像中都有一個三角形,顏色略有不同,我想通過基於image2的三角形來校正image1,這樣image1中的圓形和正方形也可以被校正。

我怎樣才能做到這一點?

我嘗試過的:

得到image1和image2中三角形的B、G、R均值,分別除以得到KB、KG、KR,然后將image1的B、G、R通道與KB、KG、KR相乘,最后合並3個通道得到校正后的圖像

使用 OpenCV 在 python 中的演示代碼:

triangle_image1 = cv2.mean(image1, mask1)[:3]
triangle_image2 = cv2.mean(image2, mask2)[:3]

k_b, k_g, k_r = triangle_image2 / triangle_image1
b, g, r = cv2.split(image1)

corrected = b * k_b, g * k_g, r * k_r
corrected = np.clip(corrected, 0, 255)
corrected = cv2.merge(np.array(corrected, np.uint8))

結果圖像看起來不錯,但實際上不正確,因為校正后的圖像和圖像 2 中的三角形的色差 (delta E) 約為 6。

我嘗試執行色適應變換,但我無法判斷結果是否正確。

請注意,色度適應會校正色度,但不會校正發光(只有顏色,但不會變亮)。
Chromatic Adaptation Transform用於色彩平衡(White Balance),不知道是否適合你的情況。

我重用了 MATLAB 實現(我沒有尋找 Python 示例)。

即使您不了解 MATLAB,並且解決方案不是您想要的,您也可以從中學習(例如線性化 RGB 值)。

這是代碼:

T = imread('image.png');       % Load input image (two images side by side).
image1 = T(:, 1:end/2, :);     % Left side
image2 = T(:, end/2+1:end, :); % Right side
I = image1; % Source image is named I

% Use color components in range [0, 1] (colors were found by manual picking).
src_sRGB = [205, 232, 32]/255; %Triangle sRGB color from image 1 "source image" 
dst_sRGB = [13, 133, 38]/255;  %Triangle sRGB color from image 2 "destination image"

%Linearize gamma-corrected RGB values (image values are in sRGB color space, we need to Linearize them).
srcRGB = rgb2lin(src_sRGB)';
dstRGB = rgb2lin(dst_sRGB)';
linI = rgb2lin(double(I)/255); % I in linear RGB color space.


% Color correction by Chromatic Adaptation:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
% Convert from XYZ D65 color space to Linear sRGB color space.
XYZD65_to_sRGB = [ 3.2404542 -1.5371385 -0.4985314
                  -0.9692660  1.8760108  0.0415560
                   0.0556434 -0.2040259  1.0572252];

% Convert from Linear sRGB color space to XYZ D65 color space.
sRGBtoXYZD65 =   [0.4124564  0.3575761  0.1804375; ...
                  0.2126729  0.7151522  0.0721750; ...
                  0.0193339  0.1191920  0.9503041];

% Convert srcRGB and dstRGB to XYZ color space
srcXYZ = sRGBtoXYZD65 * srcRGB;
dstXYZ = sRGBtoXYZD65 * dstRGB;

% Convert srcXYZ and dstXYZ to xyY color space (get only xy out of xyY - xy applies chromaticity).
xySrc = XYZ2xy(srcXYZ);
xyDst = XYZ2xy(dstXYZ);

xyzSrc = xy2XYZ(xySrc, 1); %normalize Y to 1 so D65 luminance comparable
xyzDst = xy2XYZ(xyDst, 1); %normalize Y to 1 so D65 luminance comparable

% Chromatic adaptation transform
catType = 'bradford'; %Bradford transformation is recommended by Bruce Lindbloom http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
estMAT = cbCAT(xyzSrc, xyzDst, catType);

% Ascale estMAT by XYZD65_to_sRGB before apply color correction 
M = estMAT * XYZD65_to_sRGB;

linI = cbreshape(linI);

% Destination image - apply color correction be multiplying by correction matrix M
linJ = M*linI;

linJ = cbunshape(linJ, size(I));

% Convet J from Linear to sRGB
J = lin2rgb(linJ);


% Convert from double to uint8 (multiply by 255).
J = im2uint8(J);


% Display result
figure;imshow(J);title('Corrected image1');impixelinfo
figure;imshow(image2);title('image2');impixelinfo

% Save result
imwrite(image2, 'image2.png');
imwrite(J, 'J.png');


function xy = XYZ2xy(xyz)
    %xy = XYZ2xy(xyz)
    % Converts CIE XYZ to xy chromaticity.
    X = xyz(1, :);
    Y = xyz(2, :);
    s = sum(xyz);
    xy = [X./s; Y./s];
end


function XYZ = xy2XYZ(xy,Y)
    %XYZ = xy2XYZ(xy,Y)
    % Converts xyY chromaticity to CIE XYZ.
    x = xy(1); y = xy(2);
    XYZ = [Y/y*x; Y; Y/y*(1-x-y)];
end



function outMat = cbCAT(xyz_src, xyz_dst, type)
    %https://web.stanford.edu/~sujason/ColorBalancing/adaptation.html
    %M = cbCAT(xyz_src, xyz_dst, type)
    % Chromatic adaptation transform via von Kries's method.
    %  type     chooses the LMS-like space to apply scaling in, valid options:
    %           'vonKries', 'bradford', 'sharp', 'cmccat2000', 'cat02', 'xyz'
    % See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html


    xyz_src = makecol(xyz_src);
    xyz_dst = makecol(xyz_dst);

    % the following are mostly taken from S. Bianco. "Two New von Kries Based
    % Chromatic Adaptation Transforms Found by Numerical Optimization."
    if strcmpi(type,'vonKries') %Hunt-Pointer-Estevez normalized to D65
        Ma = [0.40024 0.7076 -0.08081; -0.2263 1.16532 0.0457; 0 0 0.91822];
    elseif strcmpi(type,'bradford')
        Ma = [0.8951 0.2664 -0.1614; -0.7502 1.7135 0.0367; 0.0389 -0.0685 1.0296];
    elseif strcmpi(type,'sharp')
        Ma = [1.2694 -0.0988 -0.1706; -0.8364 1.8006 0.0357; 0.0297 -0.0315 1.0018];
    elseif strcmpi(type,'cmccat2000')
        Ma = [0.7982 0.3389 -0.1371; -0.5918 1.5512 0.0406; 0.0008 0.239 0.9753];
    elseif strcmpi(type,'cat02')
        Ma = [0.7328 0.4296 -0.1624; -0.7036 1.6975 0.0061; 0.0030 0.0136 0.9834];
    else
        Ma = eye(3);
    end

    %Chromatic Adaptation Transforms:
    %1. Transform from XYZ into a cone response domain (ro, gamma, beta)
    %2. Scale the vector components by factors dependent upon both the source and destination reference whites.
    %3. Transform from (ro, gamma, beta) back to XYZ using the inverse transform of step 1.

    %D is diagonal matrix marked as inv(Ma)*diag(roD/roS, gammaD/gammaS, betaD/betaS)*Ma.
    %Matrix D applies ratios in "cone response domain".
    D = diag((Ma*xyz_dst)./(Ma*xyz_src));

    %Transform back to XYZ domain:
    M = Ma\D*Ma;

    sRGBtoXYZ =   [0.4124564  0.3575761  0.1804375; ...
                   0.2126729  0.7151522  0.0721750; ...
                   0.0193339  0.1191920  0.9503041];

    outMat = sRGBtoXYZ\M*sRGBtoXYZ;
end



function x = makecol(x)
    %x = makecol(x)
    % returns x as a column vector

    s = size(x);
    if (length(s) == 2) && (s(1) < s(2))
        x = x.';
    end
end


function out = cbreshape(im)
    %out = cbreshape(im)
    % Takes a width x height x 3 RGB image and returns a matrix where each column is an RGB
    % pixel.
    if (size(im, 3) == 3)
        out = reshape(permute(im, [3, 1, 2]), [3, numel(im)/3, 1]);
    else
        out = (im(:))';
    end
end


function out = cbunshape(mat,s)
    %out = cbunshape(im,[height, width])
    % Takes a 3xn matrix of RGB pixels and returns a height x width x 3 RGB
    % image

    height = s(1); width = s(2);

    if (size(mat,1) == 3)
        %In case mat is 3 rows, convert to 3D matrix
        out = reshape(mat,[3,height,width]);
        out = permute(out,[2 3 1]);
    else
        %In case mat is 1 row, convert to 2D matrix
        out = reshape(mat, [height, width]);
    end
end

結果:
在此處輸入圖片說明


更新:

與發光調整相同的解決方案:

如果您需要校正發光,請在“通過色彩適應進行顏色校正”之前添加以下代碼:

% Scale the input so the mean of the triangle in image1 and image2 will be the same.
% The scaling is eqivalent to adjusting the exposure level of the camera.
rgb_scale = mean(dstRGB) / mean(srcRGB);
srcRGB = srcRGB*rgb_scale;
linI = linI*rgb_scale;

結果:
在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM