mnr
mnr

Reputation: 566

Using R to match image subset with larger image

I am using R for some very simple image analysis. Specifically, I'm trying to determine if one image is a cropped version of another image.

There has got to be a "simple" way to do this in R - but I'm not finding it. I suspect I'm over-thinking the problem - so looking for guidance on what I'm missing.

Specifically, consider the following:

install.packages("jpeg")
library(jpeg)

image.main <- readJPEG("path to a jpeg image")
image.main.sub <- readJPEG("path to another jpeg image, cropped version of the first")

if (someMagicFunctionThatFindsSubImage(image.main,image.main.sub)) {
    # TRUE - image.main.sub is a subset of image.main 
} else {
    # FALSE - image.main.sub is NOT a subset of image.main
}

someMagicFunctionThatFindsSubImage <- function (bigImage,smallImage) {
  # the matrix of values that represent smallImage is also present
  # in the matrix of values that represent bigImage
  # bigImage and smallImage can be megabytes in size
  # bigImage and smallImage can be limited to RGB Jpeg data (array of X,Y and 3 layers)
}

I've tried:

I've been collecting results at this github and will keep it updated.

THANK YOU

mnr

Upvotes: 1

Views: 2701

Answers (1)

mnr
mnr

Reputation: 566

Actually, it turns out there is an "easy" way to do this. I was fortunate to spend Christmas with a Professor in Image Analysis. It took him upwards of one minute to suggest using cross-covariance or cross-correlation. Both are present in R as part of the stats package.

>? ccf

Here's how it works:

In my example above, I import a JPEG image using...

> install.packages("jpeg")
> library(jpeg)

> image.main <- readJPEG("path to a jpeg image")
> image.main.sub <- readJPEG("path to another jpeg image, cropped version of the first")

This loads image.main and image.main.sub with the contents of the jpeg image - something like this...

> str(image.main)
num [1:3456, 1:5184, 1:3] 0.839 0.839 0.827 0.831 0.835 ..

For the sake of this discussion, I'm going to create a highly simplified version of this data. Bear with me for a second...

> image.main <- sample(1:20,20)
> image.main.sub <- image.main[5:8]

Imagine image.main contains a very small jpeg image.

image.main.sub contains a subset of image.main.

They look like this...

> image.main
[1]  2 10  8  9 19  5 11  3  7 16 20 15  6 14 17  1 13 18 12  4
> image.main.sub
[1] 19  5 11  3

Now, we can determine where image.main.sub is located within image.main with the ccf function

> ccf(image.main,image.main.sub,plot=FALSE)

Autocorrelations of series ‘X’, by lag

   -3     -2     -1      0      1      2      3 
0.440 -0.332  0.295 -0.935  0.327 -0.010  0.215 

ccf shows the correlation between the two data sets at different offsets (lags). A value of 1 indicates a 100% correlation. Observe the result if we subset image.main to match image.main.sub...

> ccf(image.main[5:8],image.main.sub,plot=FALSE)

Autocorrelations of series ‘X’, by lag

    -3     -2     -1      0      1      2      3 
-0.398  0.281 -0.382  1.000 -0.382  0.281 -0.398 

Note the value of 1.000 at a lag of 0. A match!

Related to this procedure is template matching.

I've built out the entire solution at my github page.

mnr

Upvotes: 8

Related Questions