1. 程式人生 > >【超解析度】python中的影象空間的轉換 RGB--YCBCR

【超解析度】python中的影象空間的轉換 RGB--YCBCR

由於人眼對顏色不敏感,而對光亮通道更加敏感。因此在超解析度任務中,我們通常需要將RGB通道轉換為Ycbcr通道。在Python的程式碼實現中,我發現opencv的RGB轉Ycbcr的計算方式和Matlab的實現方式有些不同,而NTIRE的評估往往是在matlab平臺的。因此,這裡需要注意。

Python RGB轉Ycbcr通道

對於Set5中的baby影象

Code:

img = cv2.imread(imgpath)
img = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
img_y = img[:,:,0]

Result:

array([[253, 253, 253, ..., 254, 254, 254],
       [253, 253, 253, ..., 254, 254, 254],
       [253, 253, 253, ..., 254, 254, 254],
       ...,
       [ 62,  70,  72, ...,  67,  67,  67],
       [ 54,  58,  59, ...,  69,  68,  68],
       [ 49,  52,  53, ...,  70,  70,  69]], dtype=uint8)

實驗原理:
在這裡插入圖片描述

參考連結:https://docs.opencv.org/3.0.0/de/d25/imgproc_color_conversions.html


Matlab RGB轉Ycbcr通道

Code:

im  = imread(imgpath);
im = rgb2ycbcr(im);
im = im(:, :, 1);

Result:
在這裡插入圖片描述

Matlab實現方式:

function ycbcr = rgb2ycbcr(varargin)
%RGB2YCBCR Convert RGB color values to YCbCr color space.
%   YCBCRMAP =
RGB2YCBCR(MAP) converts the RGB values in MAP to the YCBCR % color space. MAP must be a M-by-3 array. YCBCRMAP is a M-by-3 matrix % that contains the YCBCR luminance (Y) and chrominance (Cb and Cr) color % values as columns. Each row represents the equivalent color to the % corresponding row in the RGB colormap. % % YCBCR = RGB2YCBCR(RGB) converts the truecolor image RGB to the % equivalent image in the YCBCR color space. RGB must be a M-by-N-by-3 % array. % % If the input is uint8, then YCBCR is uint8 where Y is in the range [16 % 235], and Cb and Cr are in the range [16 240]. If the input is a double, % then Y is in the range [16/255 235/255] and Cb and Cr are in the range % [16/255 240/255]. If the input is uint16, then Y is in the range [4112 % 60395] and Cb and Cr are in the range [4112 61680]. % % Class Support % ------------- % If the input is an RGB image, it can be uint8, uint16, or double. If the % input is a colormap, then it must be double. The output has the same class % as the input. % % Examples % -------- % Convert RGB image to YCbCr. % % RGB = imread('board.tif'); % YCBCR = rgb2ycbcr(RGB); % % Convert RGB color space to YCbCr. % % map = jet(256); % newmap = rgb2ycbcr(map); % % See also NTSC2RGB, RGB2NTSC, YCBCR2RGB. % Copyright 1993-2010 The MathWorks, Inc. % References: % C.A. Poynton, "A Technical Introduction to Digital Video", John Wiley % & Sons, Inc., 1996, p. 175 % % Rec. ITU-R BT.601-5, "STUDIO ENCODING PARAMETERS OF DIGITAL TELEVISION % FOR STANDARD 4:3 AND WIDE-SCREEN 16:9 ASPECT RATIOS", % (1982-1986-1990-1992-1994-1995), Section 3.5. rgb = parse_inputs(varargin{:}); %initialize variables isColormap = false; %must reshape colormap to be m x n x 3 for transformation if (ndims(rgb) == 2) %colormap isColormap=true; colors = size(rgb,1); rgb = reshape(rgb, [colors 1 3]); end % This matrix comes from a formula in Poynton's, "Introduction to % Digital Video" (p. 176, equations 9.6). % T is from equation 9.6: ycbcr = origT * rgb + origOffset; origT = [65.481 128.553 24.966;... -37.797 -74.203 112; ... 112 -93.786 -18.214]; origOffset = [16;128;128]; % The formula ycbcr = origT * rgb + origOffset, converts a RGB image in the range % [0 1] to a YCbCr image where Y is in the range [16 235], and Cb and Cr % are in that range [16 240]. For each class type (double,uint8, % uint16), we must calculate scaling factors for origT and origOffset so that % the input image is scaled between 0 and 1, and so that the output image is % in the range of the respective class type. scaleFactor.double.T = 1/255; % scale output so in range [0 1]. scaleFactor.double.offset = 1/255; % scale output so in range [0 1]. scaleFactor.uint8.T = 1/255; % scale input so in range [0 1]. scaleFactor.uint8.offset = 1; % output is already in range [0 255]. scaleFactor.uint16.T = 257/65535; % scale input so it is in range [0 1] % and scale output so it is in range % [0 65535] (255*257 = 65535). scaleFactor.uint16.offset = 257; % scale output so it is in range [0 65535]. % The formula ycbcr = origT*rgb + origOffset is rewritten as % ycbcr = scaleFactorForT * origT * rgb + scaleFactorForOffset*origOffset. % To use imlincomb, we rewrite the formula as ycbcr = T * rgb + offset, where T and % offset are defined below. classIn = class(rgb); T = scaleFactor.(classIn).T * origT; offset = scaleFactor.(classIn).offset * origOffset; %initialize output ycbcr = zeros(size(rgb),classIn); for p = 1:3 ycbcr(:,:,p) = imlincomb(T(p,1),rgb(:,:,1),T(p,2),rgb(:,:,2), ... T(p,3),rgb(:,:,3),offset(p)); end if isColormap ycbcr = reshape(ycbcr, [colors 3 1]); end %%% %Parse Inputs %%% function X = parse_inputs(varargin) narginchk(1,1); X = varargin{1}; if ndims(X)==2 % For backward compatibility, this function handles uint8 and uint16 % colormaps. This usage will be removed in a future release. validateattributes(X,{'uint8','uint16','double'},{'nonempty'},mfilename,'MAP',1); if (size(X,2) ~=3 || size(X,1) < 1) error(message('images:rgb2ycbcr:invalidSizeForColormap')) end if ~isa(X,'double') warning(message('images:rgb2ycbcr:notAValidColormap')) X = im2double(X); end elseif ndims(X)==3 validateattributes(X,{'uint8','uint16','double'},{},mfilename,'RGB',1); if (size(X,3) ~=3) error(message('images:rgb2ycbcr:invalidTruecolorImage')) end else error(message('images:rgb2ycbcr:invalidInputSize')) end

實驗可發現兩種實現方式的結果存在著不同, 這是因為兩者的內部實現原理不同。這裡提供一個與Matlab的Ycbcr空間轉換類似的函式:


def rgb2ycbcr(img, only_y=True):
    '''same as matlab rgb2ycbcr
    only_y: only return Y channel
    Input:
        uint8, [0, 255]
        float, [0, 1]
    '''
    in_img_type = img.dtype
    img.astype(np.float32)
    if in_img_type != np.uint8:
        img *= 255.
    # convert
    if only_y:
        rlt = np.dot(img, [65.481, 128.553, 24.966]) / 255.0 + 16.0
    else:
        rlt = np.matmul(img, [[65.481, -37.797, 112.0], [128.553, -74.203, -93.786],
                              [24.966, 112.0, -18.214]]) / 255.0 + [16, 128, 128]
    if in_img_type == np.uint8:
        rlt = rlt.round()
    else:
        rlt /= 255.
    return rlt.astype(in_img_type)