function xc = bayer2rgb(xb, M, N, method) %BAYER2RGB Summary of this function goes here % Detailed explanation goes here % Initializes the struct that's going to store the RGB image xc = struct; xc.red = zeros(M, N); xc.green = zeros(M, N); xc.blue = zeros(M, N); % Initializes helper variables bayerPatternDimY = size(xb, 1); bayerPatternDimX = size(xb, 2); % Calculates the distance between two grid points for both axes gridPointsStepLengthY = (bayerPatternDimY - 1) / (M - 1); gridPointsStepLengthX = (bayerPatternDimX - 1) / (N - 1); % Calculates the coordinates of the grid points for both axes gridPointsCoordinatesY = (1:gridPointsStepLengthY:bayerPatternDimY)'; gridPointsCoordinatesX = (1:gridPointsStepLengthX:bayerPatternDimX)'; if (strcmp(method, 'nearest')) % Determines the indeces of the even rows of the original image % that are closest to each ordinate of the new image grid gridPointYmod2 = mod(gridPointsCoordinatesY, 2) >= 1; nearestEvenRow = floor(gridPointsCoordinatesY); nearestEvenRow(gridPointYmod2) = nearestEvenRow(gridPointYmod2)+1; nearestEvenRow(nearestEvenRow > bayerPatternDimY) = ... nearestEvenRow(nearestEvenRow > bayerPatternDimY) - 2; % Determines the indeces of the odd rows of the original image that % are closest to each ordinate of the new image grid nearestOddRow = floor(gridPointsCoordinatesY); nearestOddRow(~gridPointYmod2) = nearestOddRow(~gridPointYmod2)+1; nearestOddRow(nearestOddRow > bayerPatternDimY) = ... nearestOddRow(nearestOddRow > bayerPatternDimY) - 2; % Determines the indeces of the even columns of the original image % that are closest to each abscissa of the new image grid gridPointXmod2 = mod(gridPointsCoordinatesX, 2) >= 1; nearestEvenCol = floor(gridPointsCoordinatesX); nearestEvenCol(gridPointXmod2) = nearestEvenCol(gridPointXmod2)+1; nearestEvenCol(nearestEvenCol > bayerPatternDimX) = ... nearestEvenCol(nearestEvenCol > bayerPatternDimX) - 2; % Determines the indeces of the odd columns of the original image % that are closest to each abscissa of the new image grid nearestOddCol = floor(gridPointsCoordinatesX); nearestOddCol(~gridPointXmod2) = nearestOddCol(~gridPointXmod2)+1; nearestOddCol(nearestOddCol > bayerPatternDimX) = ... nearestOddCol(nearestOddCol > bayerPatternDimX) - 2; % Determines the indeces of the rows (even or odd) of the original % image that are closest to each ordinate of the new image grid totalNearestRow = round(gridPointsCoordinatesY); % Determines the indeces of the columns (even or odd) of the % original image that are closest to each abscissa of the new image totalNearestCol = round(gridPointsCoordinatesX); % Closest neighbors for red and blue can be determined by observing % the Bayer pattern xc.red = xb(nearestOddRow, nearestEvenCol); xc.blue = xb(nearestEvenRow, nearestOddCol); for currentRow = 1:M for currentCol = 1:N if ((mod(totalNearestRow(currentRow), 2) == 0 && ... mod(totalNearestCol(currentCol), 2)) ~= 0 || ... (mod(totalNearestRow(currentRow), 2) ~= 0 && ... mod(totalNearestCol(currentCol), 2) == 0)) % This point of the original image doesn't contain % information about the green colour % Calculates the vertical displacement of the two % diagonal lines that cross this point b1 = totalNearestRow(currentRow) - ... totalNearestCol(currentCol); b2 = totalNearestRow(currentRow) + ... totalNearestCol(currentCol); % Calculates the ordinate of the two diagonals at the % abscissa of the current point (currentCol) y1 = gridPointsCoordinatesX(currentCol) + b1; y2 = -gridPointsCoordinatesX(currentCol) + b2; % Initializes temporary coordinates of the point which % will be selected as the closest one fixedNearestRow = totalNearestRow(currentRow); fixedNearestCol = totalNearestCol(currentCol); % Checks the relative position between the point and % the two diagonals if (gridPointsCoordinatesY(currentRow) >= y1 && ... gridPointsCoordinatesY(currentRow) >= y2) fixedNearestRow = totalNearestRow(currentRow) - 1; elseif (gridPointsCoordinatesY(currentRow) < y1 && ... gridPointsCoordinatesY(currentRow) < y2) fixedNearestRow = totalNearestRow(currentRow) + 1; elseif (gridPointsCoordinatesY(currentRow) >= y1 && ... gridPointsCoordinatesY(currentRow) < y2) fixedNearestCol = totalNearestCol(currentCol) - 1; elseif (gridPointsCoordinatesY(currentRow) < y1 && ... gridPointsCoordinatesY(currentRow) >= y2) fixedNearestCol = totalNearestCol(currentCol) + 1; end if (fixedNearestRow < 1) % Fix for the marginal first row case xc.green(currentRow, currentCol) = ... xb(1, fixedNearestCol - 1); else xc.green(currentRow, currentCol) = ... xb(fixedNearestRow, fixedNearestCol); end else xc.green(currentRow, currentCol) = ... xb(totalNearestRow(currentRow), ... totalNearestCol(currentCol)); end end end elseif (strcmp(method, 'linear')) % Calculates helper variables flooredCoordinatesY = floor(gridPointsCoordinatesY); flooredCoordinatesX = floor(gridPointsCoordinatesX); % Calculates the ordinate of the upper couple of nearest points % that will be used in the interpolation for the blue colour upperBlueY = flooredCoordinatesY; upperBlueY(mod(upperBlueY, 2) ~= 0) = ... upperBlueY(mod(upperBlueY, 2) ~= 0) - 1; upperBlueY = upperBlueY + 2; % Calculates the ordinate of the upper couple of nearest points % that will be used in the interpolation for the red colour upperRedY = flooredCoordinatesY; upperRedY(mod(upperRedY, 2) == 0) = ... upperRedY(mod(upperRedY, 2) == 0) - 1; upperRedY = upperRedY + 2; % Calculates the abscissa of the left couple of nearest points that % will be used in the interpolation for the blue colour leftBlueX = flooredCoordinatesX; leftBlueX(mod(leftBlueX, 2) == 0) = ... leftBlueX(mod(leftBlueX, 2) == 0) - 1; leftBlueX = leftBlueX + 2; % Calculates the abscissa of the left couple of nearest points that % will be used in the interpolation for the red colour leftRedX = flooredCoordinatesX; leftRedX(mod(leftRedX, 2) ~= 0) = ... leftRedX(mod(leftRedX, 2) ~= 0) - 1; leftRedX = leftRedX + 2; % Determines the indeces of the rows (even or odd) of the original % image that are closest to each ordinate of the new image grid centerPointRow = round(gridPointsCoordinatesY); % Determines the indeces of the columns (even or odd) of the % original image that are closest to each abscissa of the new image centerPointCol = round(gridPointsCoordinatesX); % Adds a padding to the original image, replicating the last two % rows and columns of each egde xbPadded = [xb(:, end - 1) xb(:, end - 2) xb xb(:, end - 2) ... xb(:, end - 1)]; xbPadded = [xbPadded(1, :); xbPadded(2, :); xbPadded; ... xbPadded(end - 2, :); xbPadded(end - 1, :)]; for currentRow = 1:M lowerInterpPointBlue = ... ((leftBlueX + 2 - gridPointsCoordinatesX) / 2)' .* ... xbPadded(upperBlueY(currentRow) + 2, leftBlueX) + ... ((gridPointsCoordinatesX - leftBlueX) / 2)' .* ... xbPadded(upperBlueY(currentRow) + 2, leftBlueX + 2); upperInterpPointBlue = ... ((leftBlueX + 2 - gridPointsCoordinatesX) / 2)' .* ... xbPadded(upperBlueY(currentRow), leftBlueX) + ... ((gridPointsCoordinatesX - leftBlueX) / 2)' .* ... xbPadded(upperBlueY(currentRow), leftBlueX + 2); xc.blue(currentRow, :) = ... ((upperBlueY(currentRow) - ... gridPointsCoordinatesY(currentRow)) / 2) * ... lowerInterpPointBlue + ... ((gridPointsCoordinatesY(currentRow) - ... upperBlueY(currentRow) + 2) / 2) * ... upperInterpPointBlue; lowerInterpPointRed = ... ((leftRedX + 2 - gridPointsCoordinatesX) / 2)' .* ... xbPadded(upperRedY(currentRow) + 2, leftRedX) + ... ((gridPointsCoordinatesX - leftRedX) / 2)' .* ... xbPadded(upperRedY(currentRow) + 2, leftRedX + 2); upperInterpPointRed = ... ((leftRedX + 2 - gridPointsCoordinatesX) / 2)' .* ... xbPadded(upperRedY(currentRow), leftRedX) + ... ((gridPointsCoordinatesX - leftRedX) / 2)' .* ... xbPadded(upperRedY(currentRow), leftRedX + 2); xc.red(currentRow, :) = ... ((upperRedY(currentRow) - gridPointsCoordinatesY(currentRow)) / 2) * ... lowerInterpPointRed + ... ((gridPointsCoordinatesY(currentRow) - upperRedY(currentRow) + 2) / 2) * ... upperInterpPointRed; for currentCol = 1:N if ((mod(centerPointRow(currentRow), 2) == 0 && ... mod(centerPointCol(currentCol), 2)) == 0 || ... (mod(centerPointRow(currentRow), 2) ~= 0 && ... mod(centerPointCol(currentCol), 2) ~= 0)) % This point of the original image DOES contain % information about the green colour % Calculates the vertical displacement of the two % diagonal lines that cross this point b1 = centerPointRow(currentRow) - ... centerPointCol(currentCol); b2 = centerPointRow(currentRow) + ... centerPointCol(currentCol); % Calculates the ordinate of the two diagonals at the % abscissa of the current point (currentCol) y1 = gridPointsCoordinatesX(currentCol) + b1; y2 = -gridPointsCoordinatesX(currentCol) + b2; % Initializes temporary coordinates of the point which % will be selected as the center fixedCenterPointRow = centerPointRow(currentRow); fixedCenterPointCol = centerPointCol(currentCol); % Checks the relative position between the point and % the two diagonals if (gridPointsCoordinatesY(currentRow) >= y1 && ... gridPointsCoordinatesY(currentRow) >= y2) fixedCenterPointRow = centerPointRow(currentRow) - 1; elseif (gridPointsCoordinatesY(currentRow) < y1 && ... gridPointsCoordinatesY(currentRow) < y2) fixedCenterPointRow = centerPointRow(currentRow) + 1; elseif (gridPointsCoordinatesY(currentRow) >= y1 && ... gridPointsCoordinatesY(currentRow) < y2) fixedCenterPointCol = centerPointCol(currentCol) - 1; elseif (gridPointsCoordinatesY(currentRow) < y1 && ... gridPointsCoordinatesY(currentRow) >= y2) fixedCenterPointCol = centerPointCol(currentCol) + 1; end if (fixedCenterPointRow < 1) % Fix for the marginal first row case fixedCenterPointRow = 1; fixedCenterPointCol = fixedCenterPointCol - 1; end xc.green(currentRow, currentCol) = ... tiltedInterp(gridPointsCoordinatesX(currentCol), ... gridPointsCoordinatesY(currentRow), ... fixedCenterPointCol, fixedCenterPointRow, xbPadded); else xc.green(currentRow, currentCol) = ... tiltedInterp(gridPointsCoordinatesX(currentCol), ... gridPointsCoordinatesY(currentRow), ... centerPointCol(currentCol), ... centerPointRow(currentRow), xbPadded); end end end end % Combines colours to a single image array and shows the result rgbImage = cat(3, xc.blue, xc.green, xc.red); figure(); imshow(rgbImage); end function value = tiltedInterp(xw, yw, xc, yc, xbPadded) % Calculates the vertical displacement of the main diagonal that % crosses this point bw = yw - xw; % Calculates the abscissas of the points of intersection x1 = (yc + xc - 1 - bw) / 2; %x2 = (yc + xc + 1 - bw) / 2; % Calculates perpendicular distance of point w to the line connecting % the lower point and the left point dist = sqrt((x1 - xw) ^ 2 + (x1 + bw - yw) ^ 2); % Calculates the lengths of the upper parts of the lines connecting the % points h1 = sqrt(((xc - 1 - xw) ^ 2 + (yc - yw) ^ 2) - dist ^ 2); lowerLeftInterpPoint = ... ((sqrt(2) - h1) / sqrt(2)) * ... xbPadded(yc + 2, xc - 1 + 2) + ... (h1 / sqrt(2)) * ... xbPadded(yc + 1 + 2, xc + 2); upperRightInterpPoint = ... ((sqrt(2) - h1) / sqrt(2)) * ... xbPadded(yc - 1 + 2, xc + 2) + ... (h1 / sqrt(2)) * ... xbPadded(yc + 2, xc + 1 + 2); value = ... (sqrt(2) - dist) / sqrt(2) * lowerLeftInterpPoint + ... dist / sqrt(2) * upperRightInterpPoint; end