MATLAB Answers

How to match an image subset in an image?

28 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.

  0 Comments

Sign in to comment.

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

  0 Comments

Sign in to comment.

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.

Sign in to answer this question.