How to match an image subset in an image?

9 views (last 30 days)
KAE
KAE on 18 Sep 2019
Edited: KAE on 19 Sep 2019
Let's say I have image #1, and a second smaller image #2 containing some of the pixels from image #1. The pixels in image #2 were selected from image #1 so there is no shuffling of their location, but image #2 is a cropped version of #1, and some of the selected pixels are not adjacent. How can I identify the location of pixels in #1 which are the same as those in #2? Below is what I tried, but it doesn't seem to work due to the interior non-selected pixels. I have the Image Processing and Computer Vision toolboxes.
% Image # 1, full size
IFull = imread('liftingbody.png'); % Example image on Matlab path
% Image #2, subset
ISubset = uint8(255*ones(size(IFull)));
% There are 3 boxed regions included in this selection
% (Reproducing how Photoshop saves multiple-region selections)
boxList = [124 164 148 184
156 306 178 325
424 264 446 283];
for iBox = 1:size(boxList, 1)
x1 = boxList(iBox, 1);
y1 = boxList(iBox, 2);
x2 = boxList(iBox, 3);
y2 = boxList(iBox, 4);
ISubset(y1:y2, x1:x2) = IFull(y1:y2, x1:x2);
end
% Trim white space border (unfortunately not optional)
iXLeft = 124; % Leftmost point to include
iXRight = 446; % Rightmost point to include
iYBot = 164; % Bottommost point to include
iYTop = 325; % Topmost point to include
ISubset = ISubset(iYBot:iYTop, iXLeft:iXRight);
% What to do with the non-selected pixels? Here make them NaNs, but keeping them white doesn't work either
ISubset(ISubset == 255) = NaN;
f1 = figure('Name', 'Full Image and Subset');
subplot(121);
imshow(IFull); hold on;
title('Full Image');
subplot(122);
imshow(ISubset); hold on;
title('Subset');
% Perform cross-correlation, and display the result
corrMat = normxcorr2(ISubset, IFull); % corrMat is padded, not sure how
f2 = figure('Name', 'X-Corr of Subset and Full Image');
pcolor(corrMat);
shading flat;
set(gca, 'ydir', 'rev'); % Make same orientation as an image
axis equal; grid off;
% Find the peak in cross-correlation.
% Max cross-correlation at the estimated location of the
% lower-right corner of the section
[yPeak, xPeak] = find(corrMat==max(corrMat(:)));
% Account for the padding that normxcorr2 adds
yOffset = yPeak - size(ISubset, 1);
xOffset = xPeak - size(ISubset, 2);
% Display the matched area.
figure(f1); subplot(121);
plot(xOffset, yOffset, 'y*', 'clipping', 'off');
% Draw rectangle showing identified subset
imrect(gca, [xOffset+1, yOffset+1, size(ISubset, 2), size(ISubset, 1)]);
I will add that this question stems from wanting to make a selection in Photoshop, then in Matlab perform operations on the pixels I selected, in case someone else is trying to do this.

Accepted Answer

KAE
KAE on 18 Sep 2019
Edited: KAE on 18 Sep 2019
This is slow (15 seconds on my machine) but it seems to return the expected location,
% Create a mask for selected pixels in ISubset
iMask = true(size(ISubset));
iMask(ISubset==255) = false;
[nRowFull, nColFull] = size(IFull);
[nRowSub, nColSub] = size(ISubset);
corrMat = zeros(size(IFull)); % Where correlation values will be stored
x = double(ISubset(iMask)); % First input to correlation is ISubset
for iRow = 1:nRowFull
iRowSlice = (1:nRowSub) + iRow-1;
if max(iRowSlice) <= nRowFull % If subset fits in IFull
for iCol = 1:nColFull
% Index to subset sized chunk
iColSlice = (1:nColSub) + iCol-1;
if max(iColSlice) <= nColFull % If subset fits in IFull
temp = IFull(iRowSlice, iColSlice); % Extract subset sized chunk from IFull
y = double(temp(iMask)); % Second input to correlation is IFull
R = corrcoef(x,y); % Get correlation coefficient
% Place results in upper right of subset sized chunk
iRowOffset = iRowSlice(1); % y-offset
iColOffset = iColSlice(1); % x-offset
corrMat(iRowOffset, iColOffset) = R(1,2); % Off diagonal value
end
end
end
end
% Offset of ISubset in full image, based on the max correlation
[yOffset, xOffset] = find(corrMat == max(corrMat(:)));
% Find x,y pixel locations of selected regions
xSelection = []; ySelection = []; % x,y pixel locations of selection
for iRow = 1:nRowSub
for iCol = 1:nColSub
if iMask(iRow,iCol) % True if pixel is in selection
ySelection = [ySelection iRow+yOffset-1];
xSelection = [xSelection iCol+xOffset-1];
end
end
end
% Display image and selected points
f3 = figure;
imshow(IFull); % Show full image
plot(xSelection, ySelection, 'y.'); % Selected points in IFull coordinates
plot([124 446 446 124 124], [164 164 325 325 164], 'r'); % Bounding box of selection, to confirm

More Answers (1)

Matt J
Matt J on 18 Sep 2019
This might be applicable,
You can do normalized cross-correlation giving zero weight to pixels that don't participate.
  1 Comment
KAE
KAE on 18 Sep 2019
Thanks so much. It was helpful to try. For some reason I can't get this to return the correct x,y location, probably because of an error in my understanding, so I used a brute force approach as listed in my answer.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!