How to find optimal overlap of noisy bivalent matricies - algorithm
I'm dealing with an image processing problem that I've simplified as follows. I have three 10x10 matrices, each with the values 1 or -1 in each cell. Each matrix has an irregular object located somewhere, and there is some noise in the matrix. I'd like to figure out how to find the optimal alignment of the matrices that would let me line up the objects so I can get their average.
With the 1/-1 coding, I know that the product of two matrices (using element-wise multiplication, not matrix multiplication) will yield 1 if there is a match between two multiplied cells and -1 if there is a mismatch, thus the sum of the products yields a measure of overlap. With this, I know I can try out all possible alignments of two matrices to find that which yields the optimal overlap, but I'm not sure how to do this with 3 matrices (or more - I really have 20+ in my actual data set).
To help clarify the problem, here is some code, written in R, that sets up the sort of matricies I'm dealing with:
#set up the 3 matricies
m1 = c(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1)
m1 = matrix(m1,10)
m2 = c(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1)
m2 = matrix(m2,10)
m3 = c(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,-1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1)
m3 = matrix(m3,10)
#show the matricies
image(m1)
image(m2)
image(m3)
#notice there's a "+" shaped object in each
#create noise
set.seed(1)
n1 = sample(c(1,-1),100,replace=T,prob=c(.95,.05))
n1 = matrix(n1,10)
n2 = sample(c(1,-1),100,replace=T,prob=c(.95,.05))
n2 = matrix(n2,10)
n3 = sample(c(1,-1),100,replace=T,prob=c(.95,.05))
n3 = matrix(n3,10)
#add noise to the matricies
mn1 = m1*n1
mn2 = m2*n2
mn3 = m3*n3
#show the noisy matricies
image(mn1)
image(mn2)
image(mn3)
Here is a program in Mathematica that does what you want (I think).
I may explain it in more detail, if you need.
(*define temp tables*)
r = m = Table[{}, {100}];
(*define noise function*)
noise := Partition[RandomVariate[BinomialDistribution[1, .05], 100],
10];
For[i = 1, i <= 100, i++,
(*generate 100 10x10 matrices with the random cross and noise added*)
w = RandomInteger[6]; h = w = RandomInteger[6];
m[[i]] = (ArrayPad[CrossMatrix[4, 4], {{w, 6 - w}, {h, 6 - h}}] +
noise) /. 2 -> 1;
(*Select connected components in each matrix and keep only the biggest*)
id = Last#
Commonest[
Flatten#(mf =
MorphologicalComponents[m[[i]], CornerNeighbors -> False]), 2];
d = mf /. {id -> x, x_Integer -> 0} /. {x -> 1};
{minX, maxX, minY, maxY} =
{Min#Thread[g[#]] /. g -> First,
Max#Thread[g[#]] /. g -> First,
Min#Thread[g[#]] /. g -> Last,
Max#Thread[g[#]] /. g -> Last} &#Position[d, 1];
(*Trim the image of the biggest component *)
r[[i]] = d[[minX ;; maxX, minY ;; maxY]];
]
(*As the noise is low, the more repeated component is the image*)
MatrixPlot ## Commonest#r
Result:
Related
The plots of co-variance functions should start from 0-shift
The following was my question given by my teacher, Generate a sequence of N = 1000 independent observations of random variable with distribution: (c) Exponential with parameter λ = 1 , by inversion method. Present graphically obtained sequences(except for those generated in point e) i.e. e.g. (a) i. plot in the coordinates (no. obs., value of the obs) ii. plot in the coordinates (obs no n, obs. no n + i) for i = 1, 2, 3. iii. plot so called covariance function for some values. i.e. and averages: I have written the following code, (*****************************************************************) (*Task 01(c) and 02(a)*) (*****************************************************************) n = 1000; taskC = Table[-Log[RandomReal[]], {n}]; ListPlot[taskC, AxesLabel->{"No. obs", "value of the obs"}] i = 1; ListPlot[Table[ {taskC[[k]], taskC[[k+i]]}, {k, 1, n-i,1}], AxesLabel->{"obs.no.n", "obs.no.n+1"}] i++; ListPlot[Table[ {taskC[[k]], taskC[[k+i]]}, {k, 1, n-i,1}], AxesLabel-> {"obs.no.n", "obs.no.n+2"}] i++; ListPlot[Table[ {taskC[[k]], taskC[[k+i]]}, {k,1,n-i,1}], AxesLabel->{"obs.no.n", "obs.no.n+3"}] avg = (1/n)*Sum[taskC[[i]], {i,n}]; ListPlot[Table[1/(n-tau) * Sum[(taskC[[i]]-avg)*(taskC[[i+tau]] - avg), n], {tau, 1,100}], Joined->True, AxesLabel->"Covariance Function"] He has commented, The plots of co-variance functions should start from 0-shift. Note that for larger than 0 shifts you are estimating co-variance between independent observations which is zero, while for 0 shift you are estimating variance of observation which is large. Thus the contrast between these two cases is a clear indication that the observations are uncorrelated. What did I do wrong? How can I correct my code?
Zero-shift means calculating the covariance for tau = 0, which is simply the variance. Labeled[ListPlot[Table[{tau, 1/(n - tau)*Sum[(taskC[[i]] - avg)*(taskC[[i + tau]] - avg), {i, n - tau}]}, {tau, 0, 5}], Filling -> Axis, FillingStyle -> Thick, PlotRange -> All, Frame -> True, PlotRangePadding -> 0.2, AspectRatio -> 1], {"Covariance Function K(n)", "n"}, {{Top, Left}, Bottom}] Variance[taskC] 0.93484 Covariance[taskC, taskC] 0.93484 (* n = 1 *) Covariance[Most[taskC], Rest[taskC]] 0.00926913
How do I implement cross-correlation to prove two images of the same scene are similar? [duplicate]
How can I select a random point on one image, then find its corresponding point on another image using cross-correlation? So basically I have image1, I want to select a point on it (automatically) then find its corresponding/similar point on image2. Here are some example images: Full image: Patch: Result of cross correlation:
Well, xcorr2 can essentially be seen as analyzing all possible shifts in both positive and negative direction and giving a measure for how well they fit with each shift. Therefore for images of size N x N the result must have size (2*N-1) x (2*N-1), where the correlation at index [N, N] would be maximal if the two images where equal or not shifted. If they were shifted by 10 pixels, the maximum correlation would be at [N-10, N] and so on. Therefore you will need to subtract N to get the absolute shift. With your actual code it would probably be easier to help. But let's look at an example: (A) We read an image and select two different sub-images with offsets da and db Orig = imread('rice.png'); N = 200; range = 1:N; da = [0 20]; db = [30 30]; A=Orig(da(1) + range, da(2) + range); B=Orig(db(1) + range, db(2) + range); (b) Calculate cross-correlation and find maximum X = normxcorr2(A, B); m = max(X(:)); [i,j] = find(X == m); (C) Patch them together using recovered shift R = zeros(2*N, 2*N); R(N + range, N + range) = B; R(i + range, j + range) = A; (D) Illustrate things figure subplot(2,2,1), imagesc(A) subplot(2,2,2), imagesc(B) subplot(2,2,3), imagesc(X) rectangle('Position', [j-1 i-1 2 2]), line([N j], [N i]) subplot(2,2,4), imagesc(R); (E) Compare intentional shift with recovered shift delta_orig = da - db %--> [30 10] delta_recovered = [i - N, j - N] %--> [30 10] As you see in (E) we get exactly the shift we intenionally introduced in (A). Or adjusted to your case: full=rgb2gray(imread('a.jpg')); template=rgb2gray(imread('b.jpg')); S_full = size(full); S_temp = size(template); X=normxcorr2(template, full); m=max(X(:)); [i,j]=find(X==m); figure, colormap gray subplot(2,2,1), title('full'), imagesc(full) subplot(2,2,2), title('template'), imagesc(template), subplot(2,2,3), imagesc(X), rectangle('Position', [j-20 i-20 40 40]) R = zeros(S_temp); shift_a = [0 0]; shift_b = [i j] - S_temp; R((1:S_full(1))+shift_a(1), (1:S_full(2))+shift_a(2)) = full; R((1:S_temp(1))+shift_b(1), (1:S_temp(2))+shift_b(2)) = template; subplot(2,2,4), imagesc(R); However, for this method to work properly the patch (template) and the full image should be scaled to the same resolution. A more detailed example can also be found here.
Solving systems of second order differential equations
I'm working on a script in mathematica that will take simulate a string held at either end and plucked, by solving the wave equation via numerical methods. (http://en.wikipedia.org/wiki/Wave_equation#Investigation_by_numerical_methods) n = 5; (*The number of discreet elements to be used*) L = 1.0; (*The length of the string that is vibrating*) a = 1.0/3.0; (*The distance from the left side that the string is \ plucked at*) T = 1; (*The tension in the string*) [Rho] = 1; (*The length density of the string*) y0 = 0.1; (*The vertical distance of the string pluck*) [CapitalDelta]x = L/n; (*The length of each discreet element*) m = ([Rho]*L)/n;(*The mass of each individual node*) c = Sqrt[T/[Rho]];(*The speed at which waves in the string propogate*) I set all my variables Y[t] = Array[f[t], {n - 1, 1}]; MatrixForm(*Creates a vector size n-1 by 1 of functions \ representing each node*) I define my Vector of nodal position functions K = MatrixForm[ SparseArray[{Band[{1, 1}] -> -2, Band[{2, 1}] -> 1, Band[{1, 2}] -> 1}, {n - 1, n - 1}]](*Creates a matrix size n by n governing the coupling \ between each node*) I create the stiffness matrix relating all the nodal functions to one another Y0 = MatrixForm[ Table[Piecewise[{{(((i*L)/n)*y0)/a, 0 < ((i*L)/n) < a}, {(-((i*L)/n)*y0)/(L - a) + (y0*L)/(L - a), a < ((i*L)/n) < L}}], {i, 1, n - 1}]] I define the initial positions of each node using a piecewise function NDSolve[{Y''[t] == (c/[CapitalDelta]x)^2 Y[t].K, Y[0] == Y0, Y'[0] == 0}, Y, {t, 0, 10}];(*Numerically solves the system of second order DE's*) Finally, This should solve for the values of the individual nodes, but it returns an error: "NDSolve::ndinnt : Initial condition [Y0 table] is not a number or a rectangular array" So , it would seem that I don't have a firm grasp on how matrices work in mathematica. I would greatly appreciate it if anyone could help me get this last line of code to run properly. Thank you, Brad
I don't think you should use MatrixForm when defining the matrices. MatrixForm is used to format a list of list as a matrix, usually when you display it. Try removing it and see if it works.
Cross-Correlation between two images
How can I select a random point on one image, then find its corresponding point on another image using cross-correlation? So basically I have image1, I want to select a point on it (automatically) then find its corresponding/similar point on image2. Here are some example images: Full image: Patch: Result of cross correlation:
Well, xcorr2 can essentially be seen as analyzing all possible shifts in both positive and negative direction and giving a measure for how well they fit with each shift. Therefore for images of size N x N the result must have size (2*N-1) x (2*N-1), where the correlation at index [N, N] would be maximal if the two images where equal or not shifted. If they were shifted by 10 pixels, the maximum correlation would be at [N-10, N] and so on. Therefore you will need to subtract N to get the absolute shift. With your actual code it would probably be easier to help. But let's look at an example: (A) We read an image and select two different sub-images with offsets da and db Orig = imread('rice.png'); N = 200; range = 1:N; da = [0 20]; db = [30 30]; A=Orig(da(1) + range, da(2) + range); B=Orig(db(1) + range, db(2) + range); (b) Calculate cross-correlation and find maximum X = normxcorr2(A, B); m = max(X(:)); [i,j] = find(X == m); (C) Patch them together using recovered shift R = zeros(2*N, 2*N); R(N + range, N + range) = B; R(i + range, j + range) = A; (D) Illustrate things figure subplot(2,2,1), imagesc(A) subplot(2,2,2), imagesc(B) subplot(2,2,3), imagesc(X) rectangle('Position', [j-1 i-1 2 2]), line([N j], [N i]) subplot(2,2,4), imagesc(R); (E) Compare intentional shift with recovered shift delta_orig = da - db %--> [30 10] delta_recovered = [i - N, j - N] %--> [30 10] As you see in (E) we get exactly the shift we intenionally introduced in (A). Or adjusted to your case: full=rgb2gray(imread('a.jpg')); template=rgb2gray(imread('b.jpg')); S_full = size(full); S_temp = size(template); X=normxcorr2(template, full); m=max(X(:)); [i,j]=find(X==m); figure, colormap gray subplot(2,2,1), title('full'), imagesc(full) subplot(2,2,2), title('template'), imagesc(template), subplot(2,2,3), imagesc(X), rectangle('Position', [j-20 i-20 40 40]) R = zeros(S_temp); shift_a = [0 0]; shift_b = [i j] - S_temp; R((1:S_full(1))+shift_a(1), (1:S_full(2))+shift_a(2)) = full; R((1:S_temp(1))+shift_b(1), (1:S_temp(2))+shift_b(2)) = template; subplot(2,2,4), imagesc(R); However, for this method to work properly the patch (template) and the full image should be scaled to the same resolution. A more detailed example can also be found here.
difference in mathematica between Inverse[_] and (_)^(-1) for WishartDistribution
Does anyone know why the following random distributions of matrices generate different plots? (This is code to generate a plot of the PDFs for first cells from a set of 10x10 matrices sampled using an inverse Wishart distribution; amazingly, the plots are different depending on the way one performs the matrix inverse - and it seems the right plots are obtained by Inverse[_], why?) base code: << MultivariateStatistics`; Module[{dist, p, k, data, samples, scale, graphics, distribution}, p = 10; k = 13; samples = 500; dist = WishartDistribution[IdentityMatrix[p], k]; (* a samples x p x p array *) data = Inverse[#] & /# RandomVariate[dist, samples]; (* distribution graphics *) distribution[i_, j_] := Module[{fiber, f, mean, rangeAll, colorHue}, fiber = data[[All, i, j]]; dist = SmoothKernelDistribution[fiber]; f = PDF[dist]; Plot[f[z], {z, -2, 2}, PlotLabel -> ("Mean=" <> ToString[Mean[fiber]]), PlotRange -> All] ]; Grid # Table[distribution[i, j], {i, 1, 3}, {j, 1, 5}] ] code variant: above, change line data = Inverse[#] & /# RandomVariate[dist, samples]; by this data = #^(-1) & /# RandomVariate[dist, samples]; and you will see the plotted distributions are different.
Inverse computes a matrix inverse, i.e. if a is a square matrix, then Inverse[a].a will be the identity matrix. a^(-1) is the same as 1/a, i.e. it gives you the reciprocal of each matrix element. The ^ operator gives powers element-wise. If you want a matrix power, use MatrixPower.