Skip to main content

What is the fastest way to locate an image inside a larger image?


let b =


enter image description here




let c =


enter image description here




How to do:


find[c,b]


that returns the bounding box of c in b?


Notes



  • Original b is not scaled, this is only the case in this post.

  • (Update: this may actually not be the case.) Because b contains an exact copy of c, this can be thought of as a problem of finding a submatrix in a larger matrix.


Links to original images



Update



Here are the results so far:


enter image description here


Final Result (using Heike's answer)


enter image description here



Answer



Using ImageCorrelate, you can do something like


bbox[img_, crop_] := {#, # + Reverse@ImageDimensions[crop] - 1} &@
Position[ImageData@
Binarize[
ImageCorrelate[img, crop, SquaredEuclideanDistance,

Padding -> None], .001], 0][[1]]

Example


img = ExampleData[{"TestImage", "Mandrill"}]
crop = ImageTake[img, {40, 80}, {141, 200}]

bbox[img, crop]


{{40, 141}, {80, 200}}


Edit


In response to the OP's question,here is an explanation of how bbox works.


ImageCorrelate in bbox creates a new image by calculating the Euclidean distance between crop and each of the sub images of img with the same dimensions as crop. The option Padding -> None is to make sure that the pixel at {i,j} in the result of ImageCorrelate corresponds to the sub image whose upper left corner is at position {i,j} in the original image.


The Euclidean distance between two images is zero only if they are the same, so to find the position of crop in img we just need to extract the position of the pixels with value {0.,0.,0.} from the image data of ImageCorrelate which is what Position[ImageData@Binarize[....]], 0] does.


This will give us the position of the upper left corner of crop. The lower right corner is then the upper-left corner plus the dimensions of crop (note that since ImageDimensions returns {number of cols, number of rows}, and the bounding box is given as {{rowMin, colMin}, {roxMaw, colMax}} we need to reverse ImageDimensions)


Edit 2


As Szabolcs pointed out, the cut off in Binarize is somewhat arbitrary, and might cause false positives. As an alternative you could do something like this instead, which would find the best fit in the image:


bbox[img_, crop_] := {#, # + Reverse@ImageDimensions[crop] - 1} &@
(Position[#, Min[#]][[1]] &@

ImageData[ColorConvert[
ImageCorrelate[img, crop, SquaredEuclideanDistance,
Padding -> None], "Graylevel"]])

Comments

Popular posts from this blog

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1....