BGR to Color

Matlab Programming

Git

BGR to colour; aligns a set of images of the same subject matter that were taken with a red, green and blue filter respectively, to produce a colour image.

Split Images

Splits the image vertically into 3 equal size images.

To split the image I find the height of the image and divide that by 3 (round down), then create three new images for the blue, green and red channels.

[h w] = size( image );
h = floor( h/3 ); % Height / 3 (round down)
imageB = image( 1:h, : );         % 1st third
imageG = image( h+1:h*2, : );     % 2nd third
imageR = image( (h*2)+1:h*3, : ); % 3rd third

Subsample Images

Subsamples the images by 4 (0.25) & 2 (0.5).

To subsample the images I resize them by 4 (0.25) and 2 (0.5).

imageSub1R = imresize( imageR, 0.25 ); % Pass 1
imageSub1G = imresize( imageG, 0.25 ); % Pass 1
imageSub1B = imresize( imageB, 0.25 ); % Pass 1
imageSub2R = imresize( imageR, 0.5 );  % Pass 2
imageSub2G = imresize( imageG, 0.5 );  % Pass 2
imageSub2B = imresize( imageB, 0.5 );  % Pass 2

Filtered Images

Provides edge detected images for 3 passes.

To filter edge detected images of the subsampled images and split images. This uses the user specified filter (Sobel method default), and the user specified thresh and h values, which are optional for certain filters and are only used if the user has specified them.

if fThresh == false % Filter ('sobel' default)
    imageEdge1R = edge( imageSub1R, filter ); % Pass 1
    imageEdge1G = edge( imageSub1G, filter ); % Pass 1
    imageEdge1B = edge( imageSub1B, filter ); % Pass 1
    imageEdge2R = edge( imageSub2R, filter ); % Pass 2
    imageEdge2G = edge( imageSub2G, filter ); % Pass 2
    imageEdge2B = edge( imageSub2B, filter ); % Pass 2
    imageEdge3R = edge( imageR, filter ); % Pass 3
    imageEdge3G = edge( imageG, filter ); % Pass 3
    imageEdge3B = edge( imageB, filter ); % Pass 3
elseif fH == false % User specified thresh value
    imageEdge1R = edge( imageSub1R, filter, thresh ); % Pass 1
    imageEdge1G = edge( imageSub1G, filter, thresh ); % Pass 1
    imageEdge1B = edge( imageSub1B, filter, thresh ); % Pass 1
    imageEdge2R = edge( imageSub2R, filter, thresh ); % Pass 2
    imageEdge2G = edge( imageSub2G, filter, thresh ); % Pass 2
    imageEdge2B = edge( imageSub2B, filter, thresh ); % Pass 2
    imageEdge3R = edge( imageR, filter, thresh ); % Pass 3
    imageEdge3G = edge( imageG, filter, thresh ); % Pass 3
    imageEdge3B = edge( imageB, filter, thresh ); % Pass 3
else % User specified thresh & h values
    imageEdge1R = edge( imageSub1R, filter, thresh, h ); % Pass 1
    imageEdge1G = edge( imageSub1G, filter, thresh, h ); % Pass 1
    imageEdge1B = edge( imageSub1B, filter, thresh, h ); % Pass 1
    imageEdge2R = edge( imageSub2R, filter, thresh, h ); % Pass 2
    imageEdge2G = edge( imageSub2G, filter, thresh, h ); % Pass 2
    imageEdge2B = edge( imageSub2B, filter, thresh, h ); % Pass 2
    imageEdge3R = edge( imageR, filter, thresh, h ); % Pass 3
    imageEdge3G = edge( imageG, filter, thresh, h ); % Pass 3
    imageEdge3B = edge( imageB, filter, thresh, h ); % Pass 3
end

Translation Coordinates

Calculates the vertical & horizontal translation coordinates for the red & blue images for the 3 passes.

To calculate the translation coordinates I find the height of the subsampled pass 1 image and divide that by 2 (round up), then I calculate default shift values using the sum of squared dif- ferences. For pass 1, I loop through all the possible translation coordinates using the height and width values, I compare the new shift value with the current (or default) shift value to de- termine if the new translation coordinates are further accurate than the previous, if they are, I record the horizontal and vertical values. I then divide the height and width by 2 (round up) again for a shorter loop. For pass 2, I use the same loop as before but use the final shift verti- cal and horizontal values from pass 1 to define the middle area for the loop. I then divide the height and width by 2 (round up) again for a shorter loop. For pass 3, I use the same loop as before but use the final shift vertical and horizontal values from pass 2 to define the middle area for the loop.

[h w] = size( imageEdge1G );
h = ceil( h/2 ); % Height / 2 (round up)
w = ceil( w/2 ); % Width / 2 (round up)
% Default shift values
shift1R = sum( sum( ( imageEdge1G-imageEdge1R).^2) );
shift1B = sum( sum( ( imageEdge1G-imageEdge1B).^2) );
shift2R = sum( sum( ( imageEdge2G-imageEdge2R).^2) );
shift2B = sum( sum( ( imageEdge2G-imageEdge2B).^2) );
shift3R = sum( sum( ( imageEdge3G-imageEdge3R).^2) );
shift3B = sum( sum( ( imageEdge3G-imageEdge3B).^2) );
shift1VR = 0; % Shift vertical value pass 1
shift1HR = 0; % Shift horizontal value pass 1
shift1VB = 0; % Shift vertical value pass 1
shift1HB = 0; % Shift horizontal value pass 1
shift2VR = 0; % Shift vertical value pass 2
shift2HR = 0; % Shift horizontal value pass 2
shift2VB = 0; % Shift vertical value pass 2
shift2HB = 0; % Shift horizontal value pass 2
shift3VR = 0; % Shift vertical value pass 3
shift3HR = 0; % Shift horizontal value pass 3
shift3VB = 0; % Shift vertical value pass 3
shift3HB = 0; % Shift horizontal value pass 3
% Loop all possible translation coordinates pass 1
for i = -h:h
    for j = -w:w
        % Shift value
        shift = sum( sum( ( imageEdge1G-circshift( imageEdge1R, [i, j] ) ).^2) );
        % If new shift value is less than current shift value
        % Then set new shift horizontal & vertical values
        if shift < shift1R
            shift1R = shift;
            shift1VR = i;
            shift1HR = j;
        end
        % Shift value
        shift = sum( sum( ( imageEdge1G-circshift( imageEdge1B, [i, j] ) ).^2) );
        % If new shift value is less than current shift value
        % Then set new shift horizontal & vertical values
        if shift < shift1B
            shift1B = shift;
            shift1VB = i;
            shift1HB = j;
        end
    end
end
h = ceil( h/2 ); % Height / 2 (round up)
w = ceil( w/2 ); % Width / 2 (round up)
% Loop all possible translation coordinates pass 2
for i = -h:h
    for j = -w:w
        % Shift value
        shift = sum( sum( ( imageEdge2G-circshift( imageEdge2R, [shift1VR+i, shift1HR+j] ) ).^2) );
        % If new shift value is less than current shift value
        % Then set new shift horizontal & vertical values
        if shift < shift2R
            shift2R = shift;
            shift2VR = i;
            shift2HR = j;
        end
        % Shift value
        shift = sum( sum( ( imageEdge2G-circshift( imageEdge2B, [shift1VB+i, shift1HB+j] ) ).^2) );
        % If new shift value is less than current shift value
        % Then set new shift horizontal & vertical values
        if shift < shift2B
            shift2B = shift;
            shift2VB = i;
            shift2HB = j;
        end
    end
end
h = ceil( h/2 ); % Height / 2 (round up)
w = ceil( w/2 ); % Width / 2 (round up)
% Loop all possible translation coordinates pass 3
for i = -h:h
    for j = -w:w
        % Shift value
        shift = sum( sum( ( imageEdge3G-circshift( imageEdge3R, [shift2VR+i, shift2HR+j] ) ).^2) );
        % If new shift value is less than current shift value
        % Then set new shift horizontal & vertical values
        if shift < shift3R
            shift3R = shift;
            shift3VR = i;
            shift3HR = j;
        end
        % Shift value
        shift = sum( sum( ( imageEdge3G-circshift( imageEdge3B, [shift2VB+i, shift2HB+j] ) ).^2) );
        % If new shift value is less than current shift value
        % Then set new shift horizontal & vertical values
        if shift < shift3B
            shift3B = shift;
            shift3VB = i;
            shift3HB = j;
        end
    end
end

Shift Images

Shifts the red & blue images to align with the green image.

To shift the images, I use circshift using the final vertical and horizontal values from pass 3. I decided to shift the red and blue images to align with the green image as the green image is the middle image.

imageOriginalR = imageR;
imageOriginalB = imageB;
imageR = circshift( imageR, [shift3VR, shift3HR] ); % Shifts image
imageB = circshift( imageB, [shift3VB, shift3HB] ); % Shifts image

Display Colour Original & Colour Aligned Images

Creates the colour images and 2 figures for the colour original and colour aligned images.

To create a colour image, I combine the red, green and blue images respectively.

imageOriginal = cat( 3, imageOriginalR, imageG, imageOriginalB );
image = cat( 3, imageR, imageG, imageB );
figure( 'Name', 'Colour Original', 'NumberTitle', 'off' );
imshow( imageOriginal );
figure( 'Name', 'Colour Aligned', 'NumberTitle', 'off' );
imshow( image );

Filter Edge Detection Comparison

After viewing the results of each filter, the Canny method appears to be the most accurate for both the red and blue images and produces a true colour image. Although, there is not a large difference between the other filters, but it can be seen that an accurate alignment is not always possible with each filter.