Matlab matrix to cell - algorithm

I'm trying to avoid loops in Matlab. How can I do the following matrix to cell conversion vectorized?
m1 = ones(10, 2);
i = [1:10]';
m2 = [i i];
c = cell(10, 2);
for i=1:10
c{i, 1} = m1(i, :);
c{i, 2} = m2(i, :);
end

As mentioned by #beaker mat2cell() is the function to use here...this should work:
c = mat2cell([m1,m2],ones(10,1),[2,2])

Related

How to properly process images with mixed noise types

The picture with noise is like this.
Noised picture: Image3.bmp
I was doing image processing in MatLab with some built-in and self-implemented filters.
I have already tried a combination of bilateral, median and gaussian. bilateral and gaussian code are at the end of this post.
img3 = double(imread('Image3.bmp')); % this is the noised image
lena = double(imread('lena_gray.jpg')); % this is the original one
img3_com = bilateral(img3, 3, 2, 80);
img3_com = medfilt2(img3_com, [3 3], 'symmetric');
img3_com = gaussian(img3_com, 3, 0.5);
img3_com = bilateral(double(img3_com), 6, 100, 13);
SNR3_com = snr(img3_com,img3_com - lena); % 17.1107
However, the result is not promising with SNR of only 17.11.
Filtered image: img3_com
The original picture is like this.
Clean original image: lena_gray.jpg
Could you please give me any possible ideas about how to process it? Like what noise generators generated the noised image and what filtering methods or image processing method I can use to deal with it. Appreciate!!!
My bilateral function bilateral.m
function img_new = bilateral(img_gray, window, sigmaS, sigmaI)
imgSize = size(img_gray);
img_new = zeros(imgSize);
for i = 1:imgSize(1)
for j = 1:imgSize(2)
sum = 0;
simiSum = 0;
for a = -window:window
for b = -window:window
x = i + a;
y = j + b;
p = img_gray(i,j);
q = 0;
if x < 1 || y < 1 || x > imgSize(1) || y > imgSize(2)
% q=0;
continue;
else
q = img_gray(x,y);
end
gaussianFilter = exp( - double((a)^2 + (b)^2)/ (2 * sigmaS^2 ) - (double(p-q)^2)/ (2 * sigmaI^2 ));
% gaussianFilter = gaussian((a^2 + b^2)^(1/2), sigma) * gaussian(abs(p-q), sigma);
sum = sum + gaussianFilter * q;
simiSum = simiSum + gaussianFilter;
end
end
img_new(i,j) = sum/simiSum;
end
end
% disp SNR
lena = double(imread('lena_gray.jpg'));
SNR1_4_ = snr(img_new,img_new - lena);
disp(SNR1_4_);
My gaussian implementation gaussian.m
function img_gau = gaussian(img, hsize, sigma)
h = fspecial('gaussian', hsize, sigma);
img_gau = conv2(img,h,'same');
% disp SNR
lena = double(imread('lena_gray.jpg'));
SNR1_4_ = snr(img_gau,img_gau - lena);
disp(SNR1_4_);

Implement convolution in matlab

I have a equation that used to compute sigma, in which i is index from 1 to N,* denotes convolution operation, Omega is image domain.
I want to implement it by matlab code. Currently, I have three options to implement the above equation. Could you look at my equation and said to me which one is correct? I spend so much time to see what is differnent amongs methods but I could not find. Thanks in advance
The different between Method 1 and Method 2 that is method 1 compute the sigma after loop but Method 2 computes it in loop.
sigma(1:row,1:col,1:dim) = nu/d;
Does it give same result?
===========Matlab code==============
Method 1
nu = 0;
d = 0;
I2 = I.^2;
[row,col] = size(I);
for i = 1:N
KuI2 = conv2(u(:,:,i).*I2,k,'same');
bc = b.*(c(:,:,i));
bcKuI = -2*bc.*conv2(u(:,:,i).*I,k,'same');
bc2Ku = bc.^2.*conv2(u(:,:,i),k,'same');
nu = nu + sum(sum(KuI2+bcKuI+bc2Ku));
ku = conv2(u(:,:,i),k,'same');
d = d + sum(sum(ku));
end
d = d + (d==0)*eps;
sigma(1:row,1:col,1:dim) = nu/d;
Method 2:
I2 = I.^2;
[row,col] = size(I);
for i = 1:dim
KuI2 = conv2(u(:,:,i).*I2,k,'same');
bc = b.*(c(:,:,i));
bcKuI = -2*bc.*conv2(u(:,:,i).*I,k,'same');
bc2Ku = bc.^2.*conv2(u(:,:,i),k,'same');
nu = sum(sum(KuI2+bcKuI+bc2Ku));
ku = conv2(u(:,:,i),k,'same');
d = sum(sum(ku));
d = d + (d==0)*eps;
sigma(1:row,1:col,i) = nu/d;
end
Method 3:
I2 = I.^2;
[row,col] = size(I);
for i = 1:dim
KuI2 = conv2(u(:,:,i).*I2,k,'same');
bc = b.*(c(:,:,i));
bcKuI = -2*bc.*conv2(u(:,:,i).*I,k,'same');
bc2Ku = bc.^2.*conv2(u(:,:,i),k,'same');
ku = conv2(u(:,:,i),k,'same');
d = ku + (ku==0)*eps;
sigma(:,:,i) = (KuI2+bcKuI+bc2Ku)./d;
end
sigma = sigma + (sigma==0).*eps;
I think that Method 1 is assume that sigma1=sigma2=...sigman because you were computed out of loop function
sigma(1:row,1:col,1:dim) = nu/d;
where nu and d are cumulative sum for each iteration.
While, the Method 2 shown that sigma1 !=sigma 2 !=..sigman because each sigma is calculated in loop function
Hope it help

Why I got this Error The variable in a parfor cannot be classified

I'm trying to use parfor to estimate the time it takes over 96 sec and I've more than one image to treat but I got this error:
The variable B in a parfor cannot be classified
this the code I've written:
Io=im2double(imread('C:My path\0.1s.tif'));
Io=double(Io);
In=Io;
sigma=[1.8 20];
[X,Y] = meshgrid(-3:3,-3:3);
G = exp(-(X.^2+Y.^2)/(2*1.8^2));
dim = size(In);
B = zeros(dim);
c = parcluster
matlabpool(c)
parfor i = 1:dim(1)
for j = 1:dim(2)
% Extract local region.
iMin = max(i-3,1);
iMax = min(i+3,dim(1));
jMin = max(j-3,1);
jMax = min(j+3,dim(2));
I = In(iMin:iMax,jMin:jMax);
% Compute Gaussian intensity weights.
H = exp(-(I-In(i,j)).^2/(2*20^2));
% Calculate bilateral filter response.
F = H.*G((iMin:iMax)-i+3+1,(jMin:jMax)-j+3+1);
B(i,j) = sum(F(:).*I(:))/sum(F(:));
end
end
matlabpool close
any Idea?
Unfortunately, it's actually dim that is confusing MATLAB in this case. You can fix it by doing
[n, m] = size(In);
parfor i = 1:n
for j = 1:m
B(i, j) = ...
end
end

Using matrix structure to speed up matlab

Suppose that I have an N-by-K matrix A, N-by-P matrix B. I want to do the following calculations to get my final N-by-P matrix X.
X(n,p) = B(n,p) - dot(gamma(p,:),A(n,:))
where
gamma(p,k) = dot(A(:,k),B(:,p))/sum( A(:,k).^2 )
In MATLAB, I have my code like
for p = 1:P
for n = 1:N
for k = 1:K
gamma(p,k) = dot(A(:,k),B(:,p))/sum(A(:,k).^2);
end
x(n,p) = B(n,p) - dot(gamma(p,:),A(n,:));
end
end
which are highly inefficient since it uses three for loops! Is there a good way to speed up this code?
Use bsxfun for the division and matrix multiplication for the loops:
gamma = bsxfun(#rdivide, B.'*A, sum(A.^2));
x = B - A*gamma.';
And here is a test script
N = 3;
K = 4;
P = 5;
A = rand(N, K);
B = rand(N, P);
for p = 1:P
for n = 1:N
for k = 1:K
gamma(p,k) = dot(A(:,k),B(:,p))/sum(A(:,k).^2);
end
x(n,p) = B(n,p) - dot(gamma(p,:),A(n,:));
end
end
gamma2 = bsxfun(#rdivide, B.'*A, sum(A.^2));
X2 = B - A*gamma2.';
isequal(x, X2)
isequal(gamma, gamma2)
which returns
ans =
1
ans =
1
It looks to me like you can hoist the gamma calculations out of the loop; at least, I don't see any dependencies on N in the gamma calculations.
So something like this:
for p = 1:P
for k = 1:K
gamma(p,k) = dot(A(:,k),B(:,p))/sum(A(:,k).^2);
end
end
for p = 1:P
for n = 1:N
x(n,p) = B(n,p) - dot(gamma(p,:),A(n,:));
end
end
I'm not familiar enough with your code (or matlab) to really know if you can merge the two loops, but if you can:
for p = 1:P
for k = 1:K
gamma(p,k) = dot(A(:,k),B(:,p))/sum(A(:,k).^2);
end
for n = 1:N
x(n,p) = B(n,p) - dot(gamma(p,:),A(n,:));
end
end
bxfun is slow...
How about something like the following (I might have a transpose wrong)
modA = A * (1./sum(A.^2,2)) * ones(1,k);
gamma = B' * modA;
x = B - A * gamma';

MATLAB help cropping an image

I am using MATLAB R2012a and I am trying to let the user crop the image WITHOUT the use of the built in function.
here is my code:
[x, y] = ginput(2);
m1 = [x(1), y(1)];
m2 = [x(2), y(2)];
m1 = int16(m1);
m2 = int16(m2);
[m, n] = size(manip);
s1 = (m2(1) - m1(1))+1;
s2 = (m2(2) - m2(2))+1;
temp = zeros([s1, s2],('uint8'));
p1 = 0;
p2 = 0;
for c1 = 1:m
if ((c1 <= m1(2)) && (c1 >= m2(2)))
for c2 = 1:n
if ((c2 <= m1(1)) && (c2 >= m2(1)))
temp(p1, p2) = manip(c1, c2);
end
p2 = p2 + 1;
end
end
p1 = p1 + 1;
end
out = temp;
and here is my result:
Any ideas of what I did wrong, I can's seem to be able to see it. Thanks.
I would imagine your error is here: s2 = (m2(2) - m2(2))+1; should this not be s2 = (m2(2) - m1(2))+1; ?
However you don't need that loop at all:
Iold = rand(300);
%crop 10 pixels off each side
Inew = Iold(11:end - 10, 11: end - 10);
or if you need the images the same size but with zeros where the cropped bits are:
Inew = zeros(size(Iold));
Inew(11:end - 10, 11: end - 10) = Iold(11:end - 10, 11: end - 10);
or to generalize it:
Inew(xmin:xmax, ymin:ymax) = Iold(xmin:xmax, ymin:ymax);

Resources