Conversion function for 3D value into 2D in MATLAB - matlab

I have written a function for converting 3D values into 2D, but not able to get it working may be I am parsing the wrong values.
I am passing the value in the valuse as 2 coordinates and trying to get into Output in 2D. Can anyone please do the correction in the function below and help me in running the function?
% Perspective Projection
function Output = perspective_projection(Input)
Output = zeros(size(Input));
for ii = 1: length(Input)
Output(ii,1) = Input(ii,1)/Input(ii,3);
Output(ii,2)=Input(ii,2)/Input(ii,3);
end
value = [6,4,2];
[a1,b1] = perspective_projection(a1)

BSXFUN method as suggested by Rody is an elegant way, but if you would like to keep your loop, try this -
% Perspective Projection
function Output = perspective_projection(Input)
Output = zeros(size(Input,1),2);
for ii = 1: size(Input,1)
Output(ii,1) = Input(ii,1)/Input(ii,3);
Output(ii,2) = Input(ii,2)/Input(ii,3);
end

If I understand you correctly, you should rewrite your function as:
function Output = perspective_projection(Input)
Output = bsxfun(#rdivide, Input(:,1:2), Input(:,3));
end
or, judging from the way you seem to be calling it:
function [OutputX,OutputY] = perspective_projection(Input)
OutputX = Input(:,1)./Input(:,3);
OutputY = Input(:,2)./Input(:,3);
end
Note that your function is quite simple (I wouldn't even use a function):
[X,Y] = deal(Input(:,1)./Input(:,3), Input(:,2)./Input(:,3));
As for your original function: the error is in the initialization:
function Output = perspective_projection(Input)
%// WRONG: this initializes a 3D array!
Output = zeros(size(Input));
%// ...but you want a 2D array
for ii = 1: length(Input)
Output(ii,1) = Input(ii,1)/Input(ii,3);
Output(ii,2) = Input(ii,2)/Input(ii,3);
end
end
and of course, the multiple outputs (but it's not quite clear to me whether you want that or not...)

Related

Integrating function with two variables in Matlab

Hey I'm having trouble integrating a function in MATLAB, constantly getting errors. I'm trying to fill a matrix with the function. exp(x-1)*x^j+k
I2 = zeros(26,3);
k = [0.13, 0.0024, 0.000035];
for i = 1:length(k)
for j = 0:25
fun = #(x,j) exp(x-1).*x.^j+k(i);
I2(j,i) = integral(fun,0,1);
end %end j-loop
end %end i-loop
display(I2);
Thanks.
In the current form the function handle is expecting two inputs but you want a function with a single input for integral. Changing your function handle definition to the following should fix this.
fun = #(x) exp(x-1)*x^j+k(i);

Average filter Matlab

I have written the 3x3 average filter. It works fine but it shows the same output image three times instead of one. How to resolve the problem?
The code is
function [filtr_image] = avgFilter(noisy_image)
[x,y] = size(noisy_image);
filtr_image = zeros(x,y);
for i = 2:x-1
for j =2:y-1
sum = 0;
for k = i-1:i+1
for l = j-1:j+1
sum = sum+noisy_image(k,l);
end
end
filtr_image(i,j) = sum/9.0;
filtr_image = uint8(filtr_image);
end
end
end
thanks in advance
What is most likely happening is the fact that you are supplying a colour image when the code is specifically meant for grayscale. The reason why you see "three" is because when you do this to allocate your output filtered image:
[x,y] = size(noisy_image)
If you have a 3D matrix, the number of columns reported by size will be y = size(noisy_image,2)*size(noisy_image,3);. As such, when you are iterating through each pixel in your image, in column major order each plane would be placed side by side each other. What you should do is either convert your image into grayscale from RGB or filter each plane separately.
Also, you have an unnecessary casting performed in the loop. Just do it once outside of the loop.
Option #1 - Filter per plane
function [filtr_image] = avgFilter(noisy_image)
[x,y,z] = size(noisy_image);
filtr_image = zeros(x,y,z,'uint8');
for a = 1 : z
for i = 2:x-1
for j =2:y-1
sum = 0;
for k = i-1:i+1
for l = j-1:j+1
sum = sum+noisy_image(k,l,a);
end
end
filtr_image(i,j,a) = sum/9.0;
end
end
end
end
Then you'd call it by:
filtr_image = avgFilter(noisy_image);
Option #2 - Convert to grayscale
filtr_image = avgFilter(rgb2gray(noisy_image));
Minor Note
You are using sum as a variable. sum is an actual function in MATLAB and you would be overshadowing this function with your variable. This will have unintended consequences if you have other functions that rely on sum later down the line.
I can't see why your code would repeat the image (unless it's a pattern cause by an integer overflow :/ ) but here are some suggestions:
if you want to use loops, at least drop the inner loops:
[x,y] = size(noisy_image);
filtr_image = zeros(x,y);
for i = 2:x-1
for j =2:y-1
% // you could do this in 1 line if you use mean2(...) instead
sub = noisy_image(i-1:i+1, j-1:j+1);
filtr_image = uint8(mean(sub(:)));
end
end
However do you know about convolution? Matlab has a built in function for this:
filter = ones(3)/9;
filtr_image = uint8(conv2(noisy_image, filter, 'same'));

How to use function return values as matrix rows?

I was trying to plot function return values, one based on another. My function definition is:
function [final_speed, voltage] = find_final_speed(simulink_output)
As you can see, it returns two variables. I need a matrix that looks like this:
final_speed_1 voltage_1
final_speed_2 voltage_1
final_speed_3 voltage_1
final_speed_4 voltage_1
final_speed_5 voltage_1
In the end, voltages should be plotted on X axis, speeds on Y axis.
I originally tried this:
speedpervoltage = [find_final_speed(DATA_1); find_final_speed(DATA_2); ... ];
But that would only result in this matrix, all voltage info gone:
final_speed_1
final_speed_2
...
After all google searches and attempts failed, I did this:
[s1 v1] = find_final_speed(DATA_1);
[s2 v2] = find_final_speed(DATA_2);
[s... v...] = find_final_speed(DATA_...);
speedpervoltage = [0 0;s1 v1;s2 v2;s... v....;];
% Just contains the figure call along with graph properties.
plot_speedpervoltage(speedpervoltage);
This is really not optimal or practical solution. How can I do this more dynamically? Ideally, I'd like to have function create_speedpervoltage which would take array of data matrixes as argument:
plot_speedpervoltage(create_speedpervoltage([DATA_1 DATA_2 ...]));
if you know how many datasets you have, you encapsulate everything in a for loop like this:
Data = [DATA_1, DATA_2,....DATA_N] ;
outMat = [] ;
for i = 1 : length (Data)
[s v] = find_final_speed(Data(i));
outMat = [outMat ; s,v]
end
There is an easy way of doing this in Matlab. This answer is different from User1551892's answer because it doesn't dynamically reallocate the variable thus resulting in faster performance. The code is as follows.
% Declare Return Vectors
final_speed = zeros(20,1);
voltage = zeros(20,1);
% Loop through each data point
for i = 1: length( data )
[final_speed(i,:),voltage(i,:)] = find_final_speed( data(i) );
end
Now this assumes that data is a vector with each element corresponding to final and voltage speeds.
EDIT:
Another method to improve the speed even more is using arrayfun. Assuming your data is 1D, by feeding in the function as a handle into arrayfun, you can replace the 3 line loop with this line and preallocation with this code, which should give you even better performance and less lines.
[final_speed,voltage] = arrayfun( #find_final_speed, data );
Here is a solution with cellfun.
[s, v] = cellfun(#find_final_speed, [{DATA_1}, {DATA_2},... {DATA_N}]);
speedpervoltage = [s(:) v(:)];

First input must be function handle error using arrayfun()

I'm trying to use arrayfun() to map a function over a cell array. The following is happening:
>> arrayfun(solveFunc, equArray)
Error using arrayfun
First input must be a function handle.
Error in solve>genGuess (line 33)
funcVals = abs(arrayfun(inFunc, xValues));
Error in solve (line 8)
x = genGuess(inFunc, varargin{1}, varargin{2});
Error in makeSolveFunc>#(func)solve(func,start,stop) (line 3)
sFunc = #(func) solve(func, start, stop);
But, the first input IS a function handle. Also... if I manually apply the function to each element of the provided cell array, everything works fine:
>> solveFunc(equArray{1})
ans =
4.7335
>> solveFunc(equArray{2})
ans =
4.7356
Does anyone know why this would be happening? I assumed that if I could manually apply the function to each element of my array, and the return type of the function was consistent and one of the allowed types (you can't for example have arrayfun return an array of function handles... I already tried doing that), it should work. Perhaps that is not the only requirement.
Here is some code that generates this error:
solve.m
function solution = solve(inFunc, start, stop)
%SOLVE solve an equation using Newton's Method
x = genGuess(inFunc, start, stop);
for i = 1:100
m = getSlope(inFunc, x);
x = (m*x - inFunc(x))/m;
end
solution = x;
end
function slope = getSlope(inFunc, x)
%SLOPE calculate the slope at a given point
inc = 1e-5;
if x ~= 0
inc = inc * x;
end
slope = (inFunc(x + inc) - inFunc(x - inc))/(2*inc);
end
function guess = genGuess(inFunc, start, stop)
%GENGUESS get an initial guess to the solution
xValues = linspace(start, stop, 101);
funcVals = abs(arrayfun(inFunc, xValues));
[~, minIndex] = min(funcVals);
guess = xValues(minIndex);
end
charEqu.m
function equ = charEqu(a)
%CHAREQU create a KP model characteristic equation with provided p
equ = #(x) x + a;
end
makeSolveFunc.m
function sFunc = makeSolveFunc(start, stop)
%MAKESOLVEFUNC return a function that solves an equation
sFunc = #(func) solve(func, start, stop);
end
test.m
pArray = 1:5;
equArray = cell(1,arrayLen);
for i = 1:5
equArray{i} = charEqu(pArray(i));
end
solveFunc = makeSolveFunc(1.1*pi, 2*pi);
alphaAArray = arrayfun(solveFunc, equArray);
I have narrowed down the error to something in genGuess(). For some reason, in the line funcVals = abs(arrayfun(inFunc, xValues)); the variable inFunc is a 1x1 cell array containing a function handle. I have no idea why that would be the case. I traced this back to the anonymous function call #(func) solve(func, start, stop); in the makeSolveFunc() function. There it is still a 1x1 cell array containing a function handle. I'm not really sure where that cell array is coming from as that function is getting called from arrayfun().
Background information on what I'm trying to do in case someone wants to suggest a better way:
I'm trying to solve equations using Newton's method. I have written a function that can solve an equation given an initial guess range. This function is the solve() function you can see in the first error message. It takes a function, and the guess range and returns a function that I'm calling solveFunc(). solveFunc() takes a function and solves it using the initial guess range previously provided.
Maybe I'm just too used to functional programming and should just use a loop.
If the arguments passed to the function handle are contents of elements of a cell array, you need to use cellfun instead of arrayfun:
cellfun(solveFunc, equArray)
This is equivalent to
for i=1:length(equArray)
out(i) = solveFunc(equArray{i});
end
since solveFunc is already a function handle.
Check where the error comes from. This line causes the error:
funcVals = abs(arrayfun(inFunc, xValues));
The first input argument is a 1x1 cell containing one function handle. This is caused because equArray is a cell, thus use cellfun as Jonas already mentioned:
pArray = 1:5;
equArray = cell(1,arrayLen);
for i = 1:5
equArray{i} = charEqu(pArray(i));
end
solveFunc = makeSolveFunc(1.1*pi, 2*pi);
alphaAArray = cellfun(solveFunc, equArray);

Error with arrayfun

I have the following function:
function x = dataParser(y)
%// Importing list of places
places = textread('UKPlaceNames.txt' ,'%s');
%// Picking two places
place = char(places(y)); %// Converting them to an array of chars
placeInt = place - 'A' + 1;
x = placeInt;
end
In a separate function, I create:
myVector = 1:6
and then call
myVectorB = arrayfun(dataParser, myVector)
However, MATLAB throws an error on:
place = char(places(y));
stating that there are not enough parameters, where
places = textread('test.txt' ,'%s');
I am a bit confused as to where the error is, since the function takes one paramater and I am providing it...
Thanks!
You should do the following in your main script/function:
myVectorB = arrayfun(#dataParser, myVector)
Note the # in front of dataParser: this passes a function handle of dataParser to arrayfun, instead of evaluating the function dataParser() and passing the result to arrayfun.