Generate specific matrix in on line - matlab

I try to generate the following two matrix within one line (e.g. repmat, reshape) but I can not find a solution:
This is the first matrix
And this is the second matrix:
Edit:
Homework would be fun...background:
I try to implement a simple image resize algorithm. Finally I want use the codegenerator to create the corresponding C code. This is the current implementation:
function [ J ] = resize( I, sc ) %#codegen
% Function implements an algorithm to scale down given image 'I' by factor 'sc':
%
% Input data description:
% I : Grayscale 2-dimensional image
% sc: Image scale factor [-]
% -------------------------------------------------------------------------
assert( isa( I , 'uint8' ) );
assert( isa( sc, 'uint8' ) );
assert( ( sc >= 0 ) && ( sc <= 10 ) );
% Calculate scaled image size [pixel]:
ns = uint8( fix( size( I ) / single( sc ) ) );
nr = ns( 1 );
nc = ns( 2 );
% Number of elements within window:
nw = sc * sc;
% Resulting image:
J = zeros( ns, 'uint8' );
% Create index lookup table to access windows within 'I':
ri = reshape( 1 : sc * nr, sc, nr );
ci = reshape( 1 : sc * nc, sc, nc );
% Loop over image 'I' and calculate mean for each window 'w' of size [sc sc]:
% coder.unroll( );
for c = 1 : nc
% coder.unroll( );
for r = 1 : nr
% Extract window 'I_w' of fixed size [sc sc] from image 'I':
I_w = I( ri( :, r ), ci( :, c ) );
% Calculate mean of window 'I_w':
s = uint16( 0 );
% coder.unroll( );
for i = 1 : nw
s = s + uint16( I_w( i ) );
end
J( r, c ) = s / uint16( nw );
end
end
This works well. With I=[120 160], sc=6 I get:
/* MATLAB Function: '<S4>/Resize' */
for (loop_ub = 0; loop_ub < 26; loop_ub++) {
for (r = 0; r < 20; r++) {
s = 0U;
for (nz = 0; nz < 36; nz++) {
s = (uint16_T)((uint32_T)rtu_I[((ci[loop_ub * 6 + nz / 6] - 1) * 120 +
ri[r * 6 + nz % 6]) - 1] + s);
}
z = (uint16_T)(s / 36U);
s = (uint16_T)((uint32_T)s - (uint16_T)(z * 36U));
if ((s > 0) && (s >= 18)) {
z++;
}
rtb_I_sc[r + 20 * loop_ub] = (uint8_T)z;
}
}
Variables ci, ri are pre- computed by the codegenerator and const arrays within the C code. Nice. Calculating the image index has still a lot overhead:
s = (uint16_T)((uint32_T)rtu_I[((ci[loop_ub * 6 + nz / 6] - 1) * 120 + ri[r * 6 + nz % 6]) - 1] + s);
Now my idea was to pre- compute all required indicies:
% Create index lookup table to access windows within 'I':
% ri = repelem( reshape( 1 : sc * nr, sc, [] ), sc, 1 );
% ri = repmat( ri, 1, nr );
%
% ci = repelem( reshape( 1 : sc * nc, sc, [] ), 1, nc );
% ci = repmat( ci, sc, 1 );
%
% id = sub2ind( size( I ), ri(:), ci(:) );
%
% id = reshape( id, N, [] );
%
% % Loop over image 'I' and calculate mean for each window 'w' of size [sc sc]:
% for c = 1 : nc
% for r = 1 : nr
% % Extract window 'I_w' of fixed size [sc sc] from image 'I':
% I_w = I( id( :, r * c ) );
%
% % Calculate mean of window 'I_w':
% s = uint16( 0 );
% for i = 1 : N
% s = s + uint16( I_w( i ) );
% end
% J( r, c ) = s / uint16( N );
% end
% end
Above code is not working properly at all, but the main issue is that the indicies are not pre-computed. The implementation seems to be too complicate for the code generator. Therefore I was looking for some magic reshape (whatever) commands to setup the lookup tables.

Related

Image Transformation Without Loop

I am writing image transformation function in matlab instead of using predefined functions like 'imwarp or imtransform'. I am done with writing the code roughly but it is taking too long due to the use of loop.
Please suggest me a solution which can achieve the same result without loops
function I2 = f_transform(A, I1)
%A is an affine transformation matrix
%I1 is original image to be transformed
s=size(A);
if(s(1)~=3 || s(2)~=3)
disp("Invalid Transforming Matrix");
I2=0;
return;
end
if(det(A)==0)
disp("The given Transforming Matrix is Singular");
I2=0;
return;
end
[r, c]=size(I1);
extremeValues = [1 1 r r ; 1 c 1 c; 1 1 1 1];
newExtremeValues = A * extremeValues;
minRow = floor( min( newExtremeValues(1,:) ) );
maxRow = ceil( max( newExtremeValues(1,:) ) );
minCol = floor( min( newExtremeValues(2,:) ) );
maxCol = ceil( max( newExtremeValues(2,:) ) );
I2 = zeros(maxRow - minRow + 1, maxCol - minCol + 1);
for i = minRow:maxRow
for j=minCol:maxCol
b = A \ [i j 1]';
p = b(1) / b(3);
q = b(2) / b(3);
if(p >= 1 && p <= r && q >= 1 && q <= c)
I2(i - minRow + 1, j - minCol + 1) = I1(round(p),round(q));
end
end
end
I2 = uint8(I2);
return;
end

Matlab - Creating two arrays that consider all possible values for two objects

I have two physical "objects." I am representing their positions with two different arrays.
• Object 1 moves in the xy-plane only
• Object 2 moves in all three physical dimensions
Objective: Vectorize the four for loops without distorting the data. Also, the intent is to perform this operation for all possible values of object 1 to be compared with object 2.
Here is the code snippet:
Npos = 21;
Nsam = 200;
% dummy initialisation
AX = rand(1, Npos);
AY = zeros(1, Npos);
AZ = rand(1, Npos);
Bx = rand(Nsam);
By = rand(Nsam);
Bz = rand(Nsam);
for qx = 1 : Npos
for yx = 1 : Npos
for zx = 1 : Nsam
for cx = 1 : Nsam
Tx2Array( qx, yx, zx, cx ) = sqrt( ( AX( qx ) - Bx( zx, cx ) ).^2 + ( AY( yx ) - By( zx, cx ) ).^2 + ( AZ( yx ) - Bz( zx, cx ) ).^2 );
end
end
end
end
% Result is a 21 x 21 x 200 x 200 matrix filled with all real numbers
Legend
AX, AY, AZ are 1 x 21 arrays and represent the (x,y=0,z) of Object 1
AY is all zeros, but for readability is still included (hence no fifth loop!)
Bx, By, Bz are all 200 x 200 arrays and represent the (x,y,z) of Object 2
Npos = 21; Nsam = 200;
The formula used above is:
sqrt( (a1-b1)^2 + (a2-b2)^2 + (a3-b3)^2 )
If you have the Statistics Toolbox available, you can use pdist2 to calculate the distance between each coordinate for Object 1 and each coordinate for Object 2:
[X1, Z1] = ndgrid(AX(:), AZ(:)); % X1 and Z1 will be 21x21
D = pdist2([X1(:), zeros(size(X1(:))), Z1(:)], [Bx(:), By(:), Bz(:)]);
The output in this case will be a 441 x 40,000 array where D(i, j) gives you the distance between point i of Object 1 and point j of Object 2, both using linear indexing.
You can avoid the to inner loops by replacing zx and cx with : as follows:
Tx2Array = zeros(Npos, Npos, Nsam, Nsam); % preallocate memory
for qx = 1 : Npos
for yx = 1 : Npos
Tx2Array( qx, yx, :, : ) = sqrt( ( AX( qx ) - Bx( :, : ) ).^2 + ( AY( yx ) - By( :, : ) ).^2 + ( AZ( yx ) - Bz( :, : ) ).^2 );
end
end
In this way, the largest dimensions are vectorised. So, the largest improvement is already done.
By converting your B* to 4D and generating a mesh for your A* matrices, you can even remove all the for loops as follows:
[AX_, AZ_] = meshgrid(AX, AZ);
AX_ = AX_';
AZ_ = AZ_';
AY_ = zeros(Npos);
Bx_(1, 1, :, :) = Bx;
By_(1, 1, :, :) = By;
Bz_(1, 1, :, :) = Bz;
Tx2Array2 = sqrt( ( AX_ - Bx_ ).^2 + ( AY_ - By_ ).^2 + ( AZ_ - Bz_ ).^2 );
You can check the the results are the same using the following check:
max(max(max(max(abs(Tx2Array - Tx2Array2))))) < eps
If the arrays are correctly initialized your task will be very simple:
Initialize the arrays with the correct dimensions
AX = rand( Npos,1);
AY = zeros(1, Npos);
AZ = rand(1, Npos);
Bx = rand(1,1,Nsam,Nsam);
By = rand(1,1,Nsam,Nsam);
Bz = rand(1,1,Nsam,Nsam);
Then in MATLAB r2016b / Octave you can simply write:
Tx2Array = sqrt( ( AX - Bx ).^2 + ( AY - By ).^2 + ( AZ - Bz ).^2 );
In pre r2016b you can use bsxfun:
Tx2Array = sqrt(bsxfun(#plus,bsxfun(#plus,bsxfun(#minus,AX , Bx).^2,bsxfun(#minus,AY , By).^2),bsxfun(#minus,AZ , Bz).^2));

Vector field over a 3D mesh

I am currently writing my own Matlab implementation of a paper from 2003, Fast Texture Synthesis on Arbitrary Mesh.
Everything is going quite well, except for the rotation part of the similarity transform, which implies the creation of a vector field accross the 3D surface. This is a very important part of the algorithm because it gives a more natural and coherent textural aspect all over the 3D surface.
The problem is, I just have no idea how to do this. Litterature I've found on the subject is quite obscur to me, so I'm now looking for a more pragmatic (and programmatic) way to perform this.
Any idea ?
[EDIT] Just in case that may be relevant, I tried this code, which use barycentric interpolation to map a texture image to a 3D mesh. HOWEVER, in the example given texture vertex indices are known beforehand, hence, as far as my understanding goes, I'm still stuck with the rotation part of the similarity transform between the texture image and the 3D mesh. I still need to create a vector field around the surface.
Finally, here is the code I wrote, about the texture preprocessing part of Magda and Kriegman algorithm :
%% Implementation inspired by the work of Magda & Kriegman(2003), "Fast Texture Synthesis on Arbitrary Mesh"
function [TextonImage, LUT, TextonBucket] = GenerateTextons( SampleImage, gaussianSize, nbKmeansCenters )
% Create Gaussian kernel
h = fspecial( 'gaussian', gaussianSize );
% Generate feature vectors
FeatureVectors = ComputeFeatureVectors( h, SampleImage );
% Perform k-mean clustering, classify feature vectors (i.e. assign labels)
[IDX,C] = kmeans( FeatureVectors, nbKmeansCenters );
% Create texton texture
LUT = randi( 255, size( C, 1 ), 3 );
[TextonImage, TextonBucket] = CreateTextonTexture( C, SampleImage, LUT, h );
end
function Vectors = ComputeFeatureVectors( Kernel, Image )
offset = floor( size( Kernel, 1 ) / 2 );
vectorsSize = ( size( Image, 1 ) - 2 * offset ) * ( size( Image, 2 ) - 2 * offset );
Vectors = zeros( vectorsSize, size( Kernel, 1 ) * size( Kernel, 1 ) );
kk = 1;
for ii = ( 1 + offset ):( size( Image, 1 ) - offset )
for jj = ( 1 + offset ):( size( Image, 2 ) - offset )
temp = Kernel .* double( Image( ii - offset:ii + offset, jj - offset:jj + offset ) );
Vectors( kk, : ) = reshape( temp, size( Kernel, 1 ) * size( Kernel, 1 ), 1 )';
kk = kk + 1;
end
end
end
function [ TextonImage, TextonBucket ] = CreateTextonTexture( Centroids, Image, LUT, Kernel )
offset = floor( size( Kernel, 1 ) / 2 );
TextonImage = zeros( size( Image, 1 ), size( Image, 2 ), 3 );
TextonBucket = struct;
IndexTable = zeros( size( Centroids, 1 ), 1 );
for ii = ( 1 + offset ):(size( Image, 1 ) - offset)
for jj = ( 1 + offset ):(size( Image, 2 ) - offset)
temp = Kernel .* double( Image( ii - offset:ii + offset, jj - offset:jj + offset ) );
Vector = reshape( temp, size( Kernel, 1 ) * size( Kernel, 1 ), 1 )';
minDist = 10000;
Index = 0;
for k=1:size( Centroids, 1 )
% Calculate distance of test point to training point.
d = sum( Vector - Centroids( k, : ) ) .^ 2;
% if smaller...
if d < minDist
minDist = d;
Index = k;
end
end
TextonImage( ii, jj, : ) = LUT( Index, : );
cellName = strcat('B',num2str(Index));
IndexTable( Index ) = IndexTable( Index ) + 1;
TextonBucket.(cellName){ IndexTable( Index ) } = [ jj, ii ];
end
end
end
Thank you.

Radon transform matrix representation

I am looking for a MATLAB solution to generate the matrix representation of a discrete Radon transform (DRT). That is, given a vectorized version of an MxN image, X, I'd like to generate the matrix R such that R*X(:) is a DRT of the image. In MATLAB, I am expecting it to look something like the following:
>> X = 2D_Image_Of_Size_MxN;
>> R = DRT_Matrix_Of_Size_LPxMN;
>> DRT = reshape( R * X(:), L, P );
I know there are several ways to define a DRT, so I'll just say that I am looking for a normal or standard or not-too-out-of-the-ordinary implmentation.
function [ R rho theta ] = radonmatrix( drho, dtheta, M, N )
% radonmatrix - Discrete Radon Trasnform matrix
%
% SYNOPSIS
% [ R rho theta ] = radonmatrix( drho, dtheta, M, N )
%
% DESCRIPTION
% Returns a matrix representation of a Discrete Radon
% Transform (DRT).
%
% INPUT
% drho Radial spacing the the DRT.
% dtheta Angular spacing of the DRT (rad).
% M Number of rows in the image.
% N Number of columns in the image.
%
% OUTPUT
% R LP x MN DRT matrix. The values of the L and
% P will depend on the radial and angular spacings.
% rho Vector of radial sample locations.
% theta Vector of angular sample locations (rad).
%
% For each angle, we define a set of rays parameterized
% by rho. We then find the pixels on the MxN grid that
% are closest to each line. The elements in R corresponding
% to those pixels are given the value of 1.
% The maximum extent of the region of support. It's for
% rho = 0 and theta = pi/4, the line that runs caddy-corner.
W = sqrt( M^2 + N^2 );
rho = -W/2 : drho : W/2;
theta = 0 : dtheta : 180 - dtheta;
L = length( rho );
P = length( theta );
R = false( L*P, M*N );
% Define a meshgrid w/ (0,0) in the middle that
% we can use a standard coordinate system.
[ mimg nimg ] = imggrid( 1, 1, [ M N ] );
% We loop over each angle and define all of the lines.
% We then just figure out which indices each line goes
% through and put a 1 there.
for ii = 1 : P
phi = theta(ii) * pi/180;
% The equaiton is rho = m * sin(phi) + n * cos(phi).
% We either define a vector for m and solve for n
% or vice versa. We chose which one based on angle
% so that we never g4et close to dividing by zero.
if( phi >= pi/4 && phi <= 3*pi/4 )
t = -W : min( 1/sqrt(2), 1/abs(cot(phi)) ) : +W;
T = length( t );
rhom = repmat( rho(:), 1, T );
tn = repmat( t(:)', L, 1 );
mline = ( rhom - tn * cos(phi) ) ./ sin(phi);
for jj = 1 : L
p = round( tn(jj,:) - min( nimg ) ) + 1;
q = round( mline(jj,:) - min( mimg ) ) + 1;
inds = p >= 1 & p <= N & q >= 1 & q <= M;
R( (ii-1)*L + jj, unique( sub2ind( [ M N ], q(inds), p(inds) ) ) ) = 1;
end
else
t = -W : min( 1/sqrt(2), 1/abs(tan(phi)) ) : +W;
T = length( t );
rhon = repmat( rho(:)', T, 1 );
tm = repmat( t(:), 1, L );
nline = ( rhon - tm * sin(phi) ) ./ cos(phi);
for jj = 1 : L
p = round( nline(:,jj) - min( nimg ) ) + 1;
q = round( tm(:,jj) - min( mimg ) ) + 1;
inds = p >= 1 & p <= N & q >= 1 & q <= M;
R( (ii-1)*L + jj, unique( sub2ind( [ M N ], q(inds), p(inds) ) ) ) = 1;
end
end
end
R = double( sparse( R ) );
return;
Here is the imggrid function used in the above.
function [ m n ] = imggrid( dm, dn, sz )
% imggrid -- Returns rectilinear coordinate vectors
%
% SYNOPSIS
% [ m n ] = imggrid( dm, dn, sz )
%
% DESCRIPTION
% Given the sample spacings and the image size, this
% function returns the row and column coordinate vectors
% for the image. Both vectors are centered about zero.
%
% INPUT
% dm Spacing between rows.
% dn Spacing between columns.
% sz 2x1 vector of the image size: [ Nrows Ncols ].
%
% OUTPUT
% m sz(1) x 1 row coordinate vector.
% n 1 x sz(2) column coordinate vector.
M = sz(1);
N = sz(2);
if( mod( M, 2 ) == 0 )
m = dm * ( ceil( -M/2 ) : floor( M/2 ) - 1 )';
else
m = dm * ( ceil( -M/2 ) : floor( M/2 ) )';
end
if( mod( N, 2 ) == 0 )
n = dn * ( ceil( -N/2 ) : floor( N/2 ) - 1 );
else
n = dn * ( ceil( -N/2 ) : floor( N/2 ) );
end
image = phantom();
projection = radon(image);
R = linsolve(reshape(image,1,[]), reshape(projection,1,[]));

Gabor Phase ?? my values are too small

Hi every one >> hope you all are doing fine
I wanted to ask you about calculating the phase values for an image ,, you see I used the Gabor wavlet like so :
k = ( Kmax / ( f ^ v ) ) * exp( 1i * u * pi / 8 );% Wave Vector
kn2 = ( abs( k ) ) ^ 2;
GW = zeros ( R , C );
for m = -R/2 + 1 : R/2
for n = -C/2 + 1 : C/2
GW(m+R/2,n+C/2) = ( kn2 / Delt2 ) * exp( -0.5 * kn2 * ( m ^ 2 + n ^ 2 ) / Delt2) * ( exp( 1i * ( real( k ) * m + imag ( k ) * n ) ) - exp ( -0.5 * Delt2 ) );
end
end
I=imread('a.pgm');
Myimage=conv2(I,double(GW),'same');
then I called the image and the filter with different orientations and scales and stored the phase in P then I wanted to quantize it with rang 4 i:
close all;
clear all;
clc;
% Parameter Setting
R = 32;
C = 32;
Kmax = pi;
f = sqrt( 2 );
Delt = 2 * pi;
Delt2 = Delt * Delt;
% Show the Gabor Wavelets
for v=1:7 %v = 1 : 7
for u = 1:5 % u= 1: 5
[GW,Myimage]= GaborWavelet ( R, C, Kmax, f, u, v, Delt2 ); % Create the Gabor wavelets
figure;
subplot( 5, 8, v * 7 + u ),imshow ( real( GW ) ,[]); % Show the real part of Gabor wavelets
end
figure ;
subplot( 1, 5, v + 1 ),imshow ( abs( GW ),[]); % Show the magnitude of Gabor wavelets
end
%clear I;
R=real(GW);
I=imag(GW);
M=abs(Myimage);
P=atan(imag(Myimage)/real(Myimage)); <<<< is this even right ??
%P=atan(I/R);
save P P;
[xx,yy] = size (P);
DATA =zeros(size(P));
for i=1:48
for j=1:48
for zz=1:3
if (360* zz/4) <= abs(P(i,j))&& abs(P(i,j))<(360*(zz+1)/4)
DATA(i,j)=zz ; end;
end;
end;
end;
save DATA DATA ;
But the data is so small like : -1.49279186693682 1.50990968797986 -1.39225915272978 0.966151874072431
which leads to quantized value of 0 >> Where did I go wrong
I think values seem small because they are given in radians and you expect them in degrees. As for getting the magnitude and angle of a complex number, take a look at http://www.mathworks.fr/fr/help/matlab/ref/angle.html.
I quote:
"For complex Z, the magnitude R and phase angle theta are given by
R = abs(Z)
theta = angle(Z)"
Z would be your GW.
Hope this helps!