Combine RGB Of Different Dimension - matlab

I am newbie to Matlab Programming,
i have R , G , B values with different size(for example dimension R is 30000x1 and G is 35000x1) and want to make them same size to use cat(3,RColor , GColor, BColor); to combine them and produce image.

You might resample all your R,G and B vectors to have the same length.
You can choose an arbitrary length like m = 4000, to interpolate data by factor of m and decimate it by factor of length(~).
m = 4000;
R = double(R);
G = double(G);
B = double(B);
R = resample(R,m,length(R));
G = resample(G,m,length(G));
B = resample(B,m,length(B));
ImageRGB = cat(3,R,G,B);
Then you could change them back to R = uint8(R);, if you wish.

Related

Creating random binary 3D matrix with specified rank

I need to create k number of n by m binary matrixes (lets call each of them Hi where i from 1 to k) where for each of these matrixes their rank should be equal to m. Therefore, rank(Hi) = m.
I think I can create them by using (not sure):
function [Y,rk] = generateMatrix(w,y,rank)
P = orth(randi([0 1], w, rank));
Q = orth(randi([0 1], y, rank))';
Y = P*Q;
rk = rank(Y);
end
Now, I want to achieve rank(Hc) = min(n, k*m) where Hc = [H1 H2 ... Hk].
How can I achieve this?

MATLAB: efficient generating of block matrices using a block vector

Suppose
x = [x1;x2; ...; xn]
where each xi is a column vector with length l(i). We can set L = sum(l), the total length of x. I would like to generate 2 matrices based on x:
Let's call them A and B. For example, when x only as 2 blocks x1 and x2 then:
A = [x1*x1' zeros(l(1),l(2)); zeros(l(2),l(1)), x2*x2'];
B = [x1 zeros(l(1),1);
zeros(l(2),1), x2];
In the notation of the problem, A is always L by L and B is L by n. I can generate A and B given x using loops but it is tedious. Is there a clever (loop-free) way to generate A and B. I am using MATLAB 2018b but you can assume earlier version of MATLAB if necessary.
I think it is both short and fast:
B = x .* (repelem((1:numel(l)).',l)==(1:numel(l)));
A = B * B.';
If you have large data It is better to use sparse matrix:
B = sparse(1:numel(x), repelem(1:numel(l), l), x);
A = B * B.';
The following should work. In this case I do an inefficient conversion to cell arrays so there may be a more efficient implementation possible.
cuml = [0; cumsum(l(:))];
get_x = #(idx) x((1:l(idx))+cuml(idx));
x_cell = arrayfun(get_x, 1:numel(l), 'UniformOutput', false);
B = blkdiag(x_cell{:});
A = B*B';
Edit
After running some benchmarks I found a direct loop based implementation to be about twice as fast as the cell based approach above.
A = zeros(sum(l));
B = zeros(sum(l), numel(l));
prev = 0;
for idx = 1:numel(l)
xidx = (1:l(idx))+prev;
A(xidx, xidx) = x(xidx,1) * x(xidx,1)';
B(xidx, idx) = x(idx,1);
prev = prev + l(idx);
end
Here's an alternative approach:
s = repelem(1:numel(l), l).';
t = accumarray(s, x, [], #(x){x*x'});
A = blkdiag(t{:});
t = accumarray(s, x, [], #(x){x});
B = blkdiag(t{:});

Gradient descent for small and large values of multidimensional matrix

I have a matrix R which I want to estimate using gradient descent method. The code is working good for small dimension matrix (e.g. 100x1) but it gives NaN values as I increase dimension (e.g. 10x3). Please help!
R =[196,242,3;186,302,3;22,377,1;244,51,2;166,346,1;298,474,4;115,265,2;253,465,5;305,451,3;6,86,3];
N = length(R);
M = size(R,2);
K = 3;
P = rand(N,K);
Q = rand(M,K);
alpha = 0.002;
beta = 0.02;
for iter = 1 : 5000
e = R - P*Q';
P_new = P + 2*alpha*(e*Q-beta*P);
Q_new= Q + 2*alpha*(e'*P-beta*Q);
mse2(iter) = norm(R - P*Q')/norm(R);
P=P_new;
Q=Q_new;
end
R_est = P*Q';
Your problem lies in the for loop. The largest double matlab can store is 1.7977e+308, after 7 runs of the loop your values for P and Q are on the order of 10^101 and after 8 runs inf. I'm not sure what you mean by estimate matrix but your nanvalues are coming from the way P an Q grow so rapidly. One other things of note, the mse2 variable is not to used. What is its purpose?

Inserting matrix into another matrix with Matlab

I want to put a small matrix (p-by-q) called B into a bigger matrix (m-by-n) called A. How can I do it? Matrix B should be put on the right corner of matrix A:
You can do this with basic array indexing, for example:
m = 3;
n = 4;
A = rand(m,n)
p = 2;
q = 3;
B = rand(p,q)
A(end-p+1:end,end-q+1:end) = B
... assuming that p <= m and q <= n of course.

filter detection

I have to determine, which filter was used on a random picture - is there a common way to detect the right one (gaussian, prewitt, sobel, average, ...) or would it be clever to code some sort of 'brute force'-detection ?
I tried to find it with Matlab, but I have no glue how to search more efficiently. At the moment it`s like finding a needle in a Haystack. I also thought of using some bash-script and imagemagick, but this would be to resource hungry.
I tought this wouldn't be a problem, but it's very time-consuming to guess a filter and try it like this
f = fspecial('gaussian', [3 3], 1);
res = imfilter(orginal, f);
corr2(res, pic);
Let f be the original image, g be the filtered one, and h the filter applied to f, so that:
f * h = g
Passing that to the frequency domain:
F.H = G, so H = G/F
The problem is that inverting F is VERY sensitive to noise.
How to implement that in MATLAB:
close all;
f = imread('cameraman.tif');
[x,y] = size(f);
figure,imshow(f);
h = fspecial('motion', 20, 40); % abitrary filter just for testing the algorithm
F = fft2(f);
H = fft2(h,x,y);
G = F.*H;
g = ifft2(G); % the filtered image
figure, imshow(g/max(g(:)));
% Inverting the original image
epsilon = 10^(-10);
small_values = find(abs(F)<epsilon);
F(small_values) = epsilon;
F_i = ones(x,y)./F;
H_calculated = G.*F_i;
h_calculated = ifft2(H_calculated);
% remove really small values to try to infer the original size of h
r = sum(h_calculated,1)<epsilon;
c = sum(h_calculated,2)<epsilon;
h_real = h_calculated(~r,~c);
% Calculate error
% redo the filtering with the found filter
figure,g_comp = ifft2(fft2(f).*fft2(h_real,x,y));
imshow(g_comp/max(g_comp(:)));
rmse = sqrt(mean(mean((double(g_comp) - double(g)).^2,2),1))
edit: Just to explain the epsilon part:
It can be that some values in F are zero, or very close to zero. If we try to invert F with these small values, we would have problems with infinity. The easy way to solve that is to truncate every value in F that is smaller than an arbitrarily small limit, epsilon on the code.
Mathematically, what was done is this:
For all F < epsilon, F = epsilon