Seamless Cloning

This tutorial demonstrates how to use OpenCV seamless cloning module.

The program takes as input a source and a destination image (for first three methods) and outputs the cloned image.

Test images are downloaded from opencv_extra on Github.

Sources:

Contents

Test images

download required test images from Github

dirRoot = fullfile(mexopencv.root(), 'test', 'cloning');
dirs = {
    'Normal_Cloning'
    'Mixed_Cloning'
    'Monochrome_Transfer'
    'color_change'
    'Illumination_Change'
    'Texture_Flattening'
};
imgs = {
    'source1.png'
    'mask.png'
    'destination1.png'
};
if ~isdir(dirRoot)
    mkdir(dirRoot);
    disp('Downloading images...')
    baseURL = 'https://cdn.rawgit.com/opencv/opencv_extra/3.2.0/testdata/cv/cloning/';
    for i=1:numel(dirs)
        d = fullfile(dirRoot, dirs{i});
        if ~isdir(d)
            mkdir(d);
            N = numel(imgs);
            if i > 3, N = N - 1; end
            for j=1:N
                f = fullfile(d, imgs{j});
                if exist(f, 'file') ~= 2
                    url = [baseURL, dirs{i}, '/', imgs{j}]
                    urlwrite(url, f);
                end
            end
        end
    end
end

some options

opts = {'FlipChannels',true};
showPoint = @(I,p) cv.drawMarker(I, p, 'Color',[0 255 0], ...
    'MarkerType','x', 'MarkerSize',30, 'Thickness',2, 'LineType','AA');

Normal Cloning

src = imread(fullfile(dirRoot, dirs{1}, imgs{1}));
dst = imread(fullfile(dirRoot, dirs{1}, imgs{3}));
mask = imread(fullfile(dirRoot, dirs{1}, imgs{2}));

p = [400 100];
result = cv.seamlessClone(src, dst, mask, p, 'Method','NormalClone', opts{:});

figure('Name','Normal Cloning')
subplot(221), imshow(src), title('source')
subplot(222), imshow(showPoint(dst,p)), title('destination')
subplot(223), imshow(mask), title('mask')
subplot(224), imshow(result), title('cloned')

Mixed Cloning

src = imread(fullfile(dirRoot, dirs{2}, imgs{1}));
dst = imread(fullfile(dirRoot, dirs{2}, imgs{3}));
mask = imread(fullfile(dirRoot, dirs{2}, imgs{2}));

p = [size(dst,2) size(dst,1)]/2;
result = cv.seamlessClone(src, dst, mask, p, 'Method','MixedClone', opts{:});

figure('Name','Mixed Cloning')
subplot(221), imshow(src), title('source')
subplot(222), imshow(showPoint(dst,p)), title('destination')
subplot(223), imshow(mask), title('mask')
subplot(224), imshow(result), title('cloned')

Monochrome Transfer

src = imread(fullfile(dirRoot, dirs{3}, imgs{1}));
dst = imread(fullfile(dirRoot, dirs{3}, imgs{3}));
mask = imread(fullfile(dirRoot, dirs{3}, imgs{2}));

p = [size(dst,2) size(dst,1)]/2;
result = cv.seamlessClone(src, dst, mask, p, ...
    'Method','MonochromeTransfer', opts{:});

figure('Name','Monochrome Transfer')
subplot(221), imshow(src), title('source')
subplot(222), imshow(showPoint(dst,p)), title('destination')
subplot(223), imshow(mask), title('mask')
subplot(224), imshow(result), title('cloned')

Color Change

src = imread(fullfile(dirRoot, dirs{4}, imgs{1}));
mask = imread(fullfile(dirRoot, dirs{4}, imgs{2}));

result = cv.colorChange(src, mask, 'R',1.5, 'G',0.5, 'B',0.5, opts{:});

figure('Name','Color Change')
subplot(221), imshow(src), title('source')
subplot(223), imshow(mask), title('mask')
subplot(224), imshow(result), title('cloned')

Illumination change

src = imread(fullfile(dirRoot, dirs{5}, imgs{1}));
mask = imread(fullfile(dirRoot, dirs{5}, imgs{2}));

result = cv.illuminationChange(src, mask, 'Alpha',0.2, 'Beta',0.4, opts{:});

figure('Name','Illumination change')
subplot(221), imshow(src), title('source')
subplot(223), imshow(mask), title('mask')
subplot(224), imshow(result), title('cloned')

Texture Flattening

src = imread(fullfile(dirRoot, dirs{6}, imgs{1}));
mask = imread(fullfile(dirRoot, dirs{6}, imgs{2}));

result = cv.textureFlattening(src, mask, ...
    'LowThreshold',30, 'HighThreshold',45, 'KernelSize',3, opts{:});

figure('Name','Texture Flattening')
subplot(221), imshow(src), title('source')
subplot(223), imshow(mask), title('mask')
subplot(224), imshow(result), title('cloned')