Píxel loop of a multispectral image - matlab

I have a multispectral image with 6 bands.
imagen1=imread('re_2008.tif')
size2=size(imagen1);
nrow= size2(1);
ncol= size2(2);
nband= size2(3);
What I want to do is get every pixel of every band (in the same position) with their value, do an interpolation and with a new value located in other wavelength, replace it. Maybe you understand me more if I show you the code.
imagen3_2 = zeros(nrow, ncol, nband);
var1= [1 2 3 4 5 6]'; %'
for row=1:nrow;
for column=1:ncol;
for band=1:nband;
v = imagen1(nrow(1),nband(2),:); v = v(:);
t= 0:100;
interplan= interp1(var1, v, t,'cubic');
y5 = interplan(5); % I get the value of the interpolation on this position
y12 = interplan(12);
y20 = interplan(20);
y50 = interplan(50);
y80 = interplan(80);
y90 = interplan(90);
imagen3_2(:,:,1)= (y5); % and I replace it
imagen3_2(:,:,2)= (y12);
imagen3_2(:,:,3)= (y20);
imagen3_2(:,:,4)= (y50);
imagen3_2(:,:,5)= (y80);
imagen3_2(:,:,6)= (y90);
end
end
end
I get the same value as a result, not for every pixel.
Thanks in advance,

How about
imagen3_2 = zeros(nrow, ncol, nband);
var1= [1 2 3 4 5 6]'; %'
for row=1:nrow;
for column=1:ncol;
v = imagen1(row, column, :); v = v(:);
t= 0:100;
interplan= interp1(var1, v, t,'cubic');
y5 = interplan(5); % I get the value of the interpolation on this position
y12 = interplan(12);
y20 = interplan(20);
y50 = interplan(50);
y80 = interplan(80);
y90 = interplan(90);
imagen3_2(row,column,1)= (y5); % and I replace it
imagen3_2(row,column,2)= (y12);
imagen3_2(row,column,3)= (y20);
imagen3_2(row,column,4)= (y50);
imagen3_2(row,column,5)= (y80);
imagen3_2(row,column,6)= (y90);
end
end

I see that Shai already answered your question, however if you are not really interested in variables y5, y12 etc. there is a way to make the code compacter and easier to maintain:
imagen3_2 = zeros(nrow, ncol, nband);
var1= [1 2 3 4 5 6]'; %'
for row=1:nrow;
for column=1:ncol;
v = imagen1(row, column, :); v = v(:);
t= 0:100;
interplan= interp1(var1, v, t,'cubic');
y = [5 12 20 50 80 90];
for i = 1:length(y)
imagen3_2(row,column, i)= interplan(y(i));% repace interpolation value
end
end
end

For efficiency, try to avoid loops in Matlab, you can try something like this:
x = [1 2 3 4 5 6];
y = imread('re_2008.tif');
y_size = size((y(:,:,1)));
xi = 0:100;
yi = zeros([y_size,numel(xi)]);
for i_pix=1:prod(y_size)
[aux_x,aux_y] = ind2sub(y_size,i_pix);
yi(aux_x,aux_y,:) = interp1(x,squeeze(y(aux_x,aux_y,:)),xi,'cubic');
end
Or even like this:
x = [1 2 3 4 5 6];
y = imread('re_2008.tif');
xi = 0:100;
yi = arrayfun(#(y1,y2,y3,y4,y5,y6) interp1(x,[y1,y2,y3,y4,y5,y6],xi,'cubic'), ...
y(:,:,1), y(:,:,2), y(:,:,3), y(:,:,4), y(:,:,5), y(:,:,6))
I couldn't check the code, so there could be errors; but it is just to give ideas about other kinds of implementation.

Related

Cumulative count of unique element in Matlab array

Working with Matlab 2019b.
x = [10 10 10 20 20 30]';
How do I get a cumulative count of unique elements in x, which should look like:
y = [1 2 3 1 2 1]';
EDIT:
My real array is actually much longer than the example given above. Below are the methods I tested:
x = randi([1 100], 100000, 1);
x = sort(x);
% method 1: check neighboring values in one loop
tic
y = ones(size(x));
for ii = 2:length(x)
if x(ii) == x(ii-1)
y(ii) = y(ii-1) + 1;
end
end
toc
% method 2 (Wolfie): count occurrence of unique values explicitly
tic
u = unique(x);
y = zeros(size(x));
for ii = 1:numel(u)
idx = (x == u(ii));
y(idx) = 1:nnz(idx);
end
toc
% method 3 (Luis Mendo): triangular matrix
tic
y = sum(triu(x==x'))';
toc
Results:
Method 1: Elapsed time is 0.016847 seconds.
Method 2: Elapsed time is 0.037124 seconds.
Method 3: Elapsed time is 10.350002 seconds.
EDIT:
Assuming that x is sorted:
x = [10 10 10 20 20 30].';
x = sort(x);
d = [1 ;diff(x)];
f = find(d);
d(f) = f;
ic = cummax(d);
y = (2 : numel(x) + 1).' - ic;
When x is unsorted use this:
[s, is] = sort(x);
d = [1 ;diff(s)];
f = find(d);
d(f) = f;
ic = cummax(d);
y(is) = (2 : numel(s) + 1).' - ic;
Original Answer that only works on GNU Octave:
Assuming that x is sorted:
x = [10 10 10 20 20 30].';
x = sort(x);
[~, ic] = cummax(x);
y = (2 : numel(x) + 1).' - ic;
When x is unsorted use this:
[s, is] = sort(x);
[~, ic] = cummax(s);
y(is) = (2 : numel(s) + 1).' - ic;
You could loop over the unique elements, and set their indices to 1:n each time...
u = unique(x);
y = zeros(size(x));
for ii = 1:numel(u)
idx = (x == u(ii));
y(idx) = 1:nnz(idx);
end
This is a little inefficient because it generates an intermediate matrix, when actually only a triangular half is needed:
y = sum(triu(x==x.')).';
Here's a no-for-loop version. On my machine it's a bit faster than the previous working methods:
% if already sorted, can omit this first and last line
[s, is] = sort(x);
[u,~,iu] = unique(s);
c = accumarray(iu,1);
cs = cumsum([0;c]);
z = (1:numel(x))'-repelem(cs(1:end-1),c);
y(is) = z;

Laguerre's method to obtain poly roots

I have to write using Laguerre's method a piece of code to find real and complex roots of poly:
f(x)=a4x4+a3x3+a2x2+a1x+a0 , [a4 a3 a2 a1 a0]=[-2 5 5 2 1]
I got something:
function y = laguerre (x,coef)
tol = 10^(-10);
%polynomial order
n = length(coef);
i = 0;
while (abs(polyval(coef,x)) > tol)
i = i + 1
x
polyval(coef,x)
%second derivative
a=polyval(polyder(polyder(coef)), x);
%first derivative
b=polyval(polyder(coef), x);
%polynomial value
c=polyval(coef, x);
%square root
r = sqrt((n-1)*[(n-1)*b^2-n*a*c]);
d1 = b + r;
d2 = b - r;
%highest abs value denominator chosen
if (abs(d1) > abs(d2))
d = d1;
else
d = d2;
end
%next iteration value obtained
z = n*c/d;
x = x - z;
end
i = i + 1
x
polyval(coef,x)
y = x;
return
end
and I want to draw and/ or obtain my roots:
coef = [-2 5 5 2 1];
fh = #poly;
%diary on
%plot of the function
figure(1);
fplot(fh, [-500 500]);
hold on;
figure(2);
fplot(fh, [-1.5 3]);
hold on;
%roots obtained using MM2
%z1(1) = MM2(-500,coef);
%z1(2) = MM2(500,coef);
%z1(3) = MM2(1 + i, coef);
%z1(4) = MM2(0 - 2i, coef);
%roots obtained using Laguerre's
%z2(1) = laguerre(-500,coef);
z2(2) = laguerre(500,coef);
%z2(3) = laguerre(1 + i, coef);
%z2(4) = laguerre(0 - 2i, coef);
%additional points on plot
p = [z1(1) z2(2)];
plot(p,[0 0],'r*');
legend('function','zeros');
hold off;
figure(1);
plot(p,[0 0],'r*');
plot([-500 500],[0 0], 'b*');
legend('function','zeros','START points');
diary off;
hold off;
As you see, some part of code is commented because I really don't know how to move on. I got many warnings. I got one error in 1st part of the code. I am looking for some tips or direction what to do.
Your code works perfectly well, you should get the roots
x=-500 => x=-0.6694729, p(x)=-8.882D-16 in 9 steps
x= 500 => x=3.3489712, p(x)=1.621D-14 in 8 steps
x=1 + i => x=-0.0897491+i*0.4636332, p(x)=i*8.327D-17 in 4 steps
x=0 - 2i => x=-0.0897491-i*0.4636332, p(x)=i*5.551D-17 in 4 steps
To illustrate the bigger picture, the iteration map for the Laguerre method with initial values in [-4,4]+[-4,4]*i looks like
Every color shade represents one step. There is nothing nefarious in this polynomial preventing convergence of the method.
To compare with, the Halley iteration map is
and the Newton fractal

copy move forgery detection stuck with algorithm

I am trying to implement the paper detection of copy move forgery using histogram of oriented gradients.
The algorithm is:
Divide the image into overlapping blocks.
Calculate feature vectors for each block and store them in a matrix.
Sorting the matrix lexicographically
Using block matching to identify forged regions.
https://www.researchgate.net/publication/276518650_Detection_of_copy-move_image_forgery_using_histogram_of_orientated_gradients
I am stuck with the 3rd step and can't proceed.
The code I have implemented is:
clc;
clear all;
close all;
%read image
img = imread('006_F.png');
img=rgb2gray(img);
img=imresize(img, 1/4);
figure(1);
imshow(img);
b=16; %block size
nrc=5; %no. of rows to check
td=416; %threshold
[r, c]=size(img);%Rows and columns;
column=(r-b+1)*(c-b+1);
M= zeros(column,4);
Mi = zeros(1,2);
i=1;
disp('starting extraction of features');
for r1 = 1:r-b+1
for c1 = 1:c-b+1
% Extract each block
B = img(r1:r1+b-1,c1:c1+b-1);
features = extractHOGFeatures(B);%extracting features
M(i, :) = features;
Mi(i,:) = [r1 c1];
i=i+1;
end
end
[S, index] = sortrows(M , [ 1 2 3 4]);
P= zeros(1,6);
b2=r-b+1;
disp('Finding Duplicates');
for i = 1:column
iv = index(i);
xi=mod(iv,b2) + 1;
yi=ceil(iv/b2);
j = i+1;
while j < column && abs(i - j) < 5
jv=index(j);
xj=mod(jv,b2) + 1;
yj=ceil(jv/b2);
z=sqrt(power(xi-xj,2) + power(yi-yj,2));
% only process those whose size is above Nd
if z > 16
offset = [xi-xj yi-yj];
P = [P;[xi yi xj yj xi-xj yi-yj]];
end
j = j + 1;
end
end
rows = size(P,1);
P(:,6) = P(:,6) - min(P(:,6));
P(:,5) = P(:,5) - min(P(:,5));
maxValP = max(P(:,6)) + 1;
P(:,5) = maxValP .* P(:,5) + P(:,6);
mostfrequentval = mode(P(:,5));
disp('Creating Image');
idx = 2;
% Create a copy of the image and mask it
RI = img;
while idx < rows
x1 = P(idx,1);
y1 = P(idx,2);
x2 = P(idx,3);
y2 = P(idx,4);
if (P(idx,5) == mostfrequentval)
RI(y1:y1,x1:x1) = 0;
RI(y2:y2,x2:x2) = 0;
end
idx = idx + 1;
end;
After going through some references indicated in the paper you are working on (ref. [8] and [20]):
The lexicographic sorting is the equivalent of the alphabetical one, for numbers i.e., [1 1 1 1] < [1 1 2 1] < [2 3 4 5] < [2 4 4 5]
So, in your case, you case use the function sortrows() in the following way:
A = [1 1 1 1;1 1 1 2;1 1 1 4;1 2 2 2; 1 2 2 1; 1 4 6 3; 2 3 4 5; 2 3 6 6]; % sample matrix
[B,idx] = sortrows(A,[1 2 3 4]); % Explicit notation but it is the Matlab default setting so equivalent to sortrows(A)
It means: Sort the rows of A by first looking at the first column and, in case of equality, looking at the second one, and so on.
If your are looking for a reverse order, you specify '-' before the number of the column.
So in the end, your code is good and if the results are not as expected it has to come from another step of the implementation...
Edit: the parameter idx records the original index of the sorted rows.

avoid loop matlab in 2D bspline surface interpolation

I want to speed up my code. I always use vectorization. But in this code I have no idea how to avoid the for-loop. I would really appreciate a hint how to proceed.
thank u so much for your time.
close all
clear
clc
% generating sample data
x = linspace(10,130,33);
y = linspace(20,100,22);
[xx, yy] = ndgrid(x,y);
k = 2*pi/50;
s = [sin(k*xx+k*yy)];
% generating query points
xi = 10:5:130;
yi = 20:5:100;
[xxi, yyi] = ndgrid(xi,yi);
P = [xxi(:), yyi(:)];
% interpolation algorithm
dx = x(2) - x(1);
dy = y(2) - y(1);
x_ = [x(1)-dx x x(end)+dx x(end)+2*dx];
y_ = [y(1)-dy y y(end)+dy y(end)+2*dy];
s_ = [s(1) s(1,:) s(1,end) s(1,end)
s(:,1) s s(:,end) s(:,end)
s(end,1) s(end,:) s(end,end) s(end,end)
s(end,1) s(end,:) s(end,end) s(end,end)];
si = P(:,1)*0;
M = 1/6*[-1 3 -3 1
3 -6 3 0
-3 0 3 0
1 4 1 0];
tic
for nn = 1:numel(P(:,1))
u = mod(P(nn,1)- x_(1), dx)/dx;
jj = floor((P(nn,1) - x_(1))/dx) + 1;
v = mod(P(nn,2)- y_(1), dy)/dy;
ii = floor((P(nn,2) - y_(1))/dy) + 1;
D = [s_(jj-1,ii-1) s_(jj-1,ii) s_(jj-1,ii+1) s_(jj-1,ii+2)
s_(jj,ii-1) s_(jj,ii) s_(jj,ii+1) s_(jj,ii+2)
s_(jj+1,ii-1) s_(jj+1,ii) s_(jj+1,ii+1) s_(jj+1,ii+2)
s_(jj+2,ii-1) s_(jj+2,ii) s_(jj+2,ii+1) s_(jj+2,ii+2)];
U = [u.^3 u.^2 u 1];
V = [v.^3 v.^2 v 1];
si(nn) = U*M*D*M'*V';
end
toc
scatter3(P(:,1), P(:,2), si)
hold on
mesh(xx,yy,s)
This is the full example and is a cubic B-spline surface interpolation algorithm in 2D space.

Sequence of dots in matlab and psychotoolbox

How would i display one by one dots that are in a 3x3 matrix such as in the code below?
I would like to have dot1 appears in position [x1,y1] of the grid for a time t1, then dot2 to appears in position [x2,y2] of the grid for a time t2. Only one dot is being shown at each time.
Thanks for help
%grid
dim = 1
[x, y] = meshgrid(-dim:1:dim, -dim:1:dim);
pixelScale = screenYpixels / (dim * 2 + 2);
x = x .* pixelScale;
y = y .* pixelScale;
% Calculate the number of dots
numDots = numel(x);
% Make the matrix of positions for the dots.
dotPositionMatrix = [reshape(x, 1, numDots); reshape(y, 1, numDots)];
% We can define a center for the dot coordinates to be relaitive to.
dotCenter = [xCenter yCenter];
dotColors = [1 0 0];
dotSizes = 20;
Screen('DrawDots', window, dotPositionMatrix,...
dotSizes, dotColors, dotCenter, 2);
I think you want something like this?
%positions of each successive dots:
x_vec = [1,2,3,1,2,3,1,2,3];
y_vec = [1,1,1,2,2,2,3,3,3];
%wait times in sec for each dot:
wait_times = [1,1,2,1,1,2,1,1,2]
dotColor = [1 0 0];
dotSize = 400;
num_dots = length(x_vec);
for i = 1:num_dots
scatter(x_vec(i),y_vec(i),dotSize,dotColor,'filled');
xlim([0,max(x_vec)])
ylim([0,max(y_vec)])
pause(wait_times(i));
end