I have two images with rectangular regions at different locations in the images. I have gotten the pixel locations of each region in the images and stored them in separate matrices. What I wish to do is compare the elements in the matrices to each other and remove duplicates from the second matrix. I also want to remove elements in the second matrix that fall within a certain range of the first matrix.
For example:
Region start and end locations of first matrix(image 1) =
3 18
81 96
109 124
165 180
199 209
299 312
Region start and end locations of second matrix(image 2) =
3 18
25 41
71 83
127 144
164 179
337 354
In the above, the [3 18] should be removed from the second matrix. Also, the [164 179] of the second matrix falls within the [165 180] of the first image and should be removed.
The matrices are not of the same dimensions and the values will be different depending on the images. What would be the best way to remove instances like this? If it's not possible to remove them from the matrix, would there be a way to store them in their own matrix? I looked at using setdiff, which causes instances like [3 18] to be left out, but does not address elements within range. Thanks to anyone who can provide some help.

4 commentaires

dpb
dpb le 21 Mar 2016
For the first, look at
doc intersect % and friends
For the latter, [164 179] is not within [165 180]. The upper is but the lower bound isn't. So what's the precise definition or "within" here?
Niamh Shiel
Niamh Shiel le 21 Mar 2016
Thank you for the reply, I'll look into using intersect. I understand your confusion. What I really should have said was if a value is within range of another, it should be removed.
So, lets say, if a value in the second matrix is either plus or minus 1 of a value in the first matrix, it should be removed, e.g., for [164 179] both of these numbers are -1 compared to [165 180]. The element should also be removed if it were +1 : [166 181], or a combination of the two : [164 181], [166 179].
I tried to keep it as general as possible in my original post as I'm not sure how many pixels either side will be necessary to factor in, this can be figured out through trial and error though once I get a working example. I hope this helps to clarify what I am looking for, and if you have any more questions please ask. Thanks.
Guillaume
Guillaume le 22 Mar 2016
What about runs that overlap? Should they be collapsed into one? For example, should the [81 96] of image 1 and [71 83] of image 2 become [71 96]?
Niamh Shiel
Niamh Shiel le 22 Mar 2016
Modifié(e) : Niamh Shiel le 22 Mar 2016
No, it shouldn't. The reason instances such as [164 179] should be removed is because it is a shadow or artifact of [165 180]. These images are roads beside each other and each region is a vehicle. [71 83] should not be touched because it is first detected 10 pixels before the vehicle in image 1. The fact they overlap at all is just down to timing and length of the vehicles, I would imagine.

Connectez-vous pour commenter.

 Réponse acceptée

Guillaume
Guillaume le 22 Mar 2016
Modifié(e) : Guillaume le 22 Mar 2016

0 votes

You can use uniquetol (from R2015a and up) to find duplicate rows with tolerance, applied to the concatenation of the two matrices. It just then is a matter of tracking which of the rows identified as duplicate come from the second matrix:
img1runs = [3 18;81 96; 109 124; 165 180; 199 209; 299 312]
img2runs = [3 18; 25 41; 71 83; 127 144; 164 179; 337 354]
tolerance = 1; %allow interval with ends within +/- 1 of each others
[~, origin] = uniquetol([img1runs; img2runs], tolerance, 'ByRows', true, 'DataScale', 1, 'OutputAllIndices', 1);
origin = origin(cellfun(@numel, origin) > 1); %only keep rows of origin that contain duplicate
origin = vertcat(origin{:}); %concatenate into one row
origin = origin - size(img1runs, 1); %subtract index offset from 1st image. Only indices > 0 come from the second image
img2runs(origin(origin > 0), :) = [] %remove duplicate rows in second image

3 commentaires

Niamh Shiel
Niamh Shiel le 22 Mar 2016
Thank you for your contribution, this works great for what I was asking! Is there a way to print the removed rows also or are they unattainable once the tolerance has been applied?
Before the last line, add:
removedrows = img2runs(origin(origin > 0), :)
Niamh Shiel
Niamh Shiel le 22 Mar 2016
That's perfect, thanks a lot!

Connectez-vous pour commenter.

Plus de réponses (1)

Image Analyst
Image Analyst le 22 Mar 2016

0 votes

Why not simply leave them as binary images and deal with them that way? First expand the canvass so that they are the same size. You could use imdilate() to include pixels with a certain "tolerance" (as you say). Then you could use xor() to remove pixels in common. It seems a lot simpler than having to deal with individual coordinates or ranges of where those pixels lie.

3 commentaires

Niamh Shiel
Niamh Shiel le 22 Mar 2016
Thanks for your contribution, that does sound simpler. Would this be possible if the matrix dimensions are different? Or is that what you mean by "expand the canvas"?
Like if one image is 300x400 and the other is 280x450, make both images 300x450 so they are the same size. You can simply find the largest rows and columns and set the last pixel to be false to expand each image
[rows1, columns1] = size(binaryImage1);
[rows2, columns2] = size(binaryImage2);
% Find the largest of any image in each direction.
bigRows = max([rows1, rows2]);
bigColumns = max([columns1, columns2]);
% Enlarge images by growing to the right and down.
binaryImage1(bigRows, bigColumns) = false;
binaryImage2(bigRows, bigColumns) = false;
Niamh Shiel
Niamh Shiel le 23 Mar 2016
Okay, thank you. I'll implement it and see if it's better for the project. Thanks a lot!

Connectez-vous pour commenter.

Catégories

Community Treasure Hunt

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

Start Hunting!

Translated by