I must to use angle = atan2(norm(cross(a,b)),dot(a,b))
, for calculating the angle between two vectors a,b
and these are double type and norm
is undefined for this type. How do I resolve this problem? I need to calculate the angle between two vectors this way.

- 102,964
- 22
- 184
- 193

- 79
- 1
- 3
- 9
-
i appreciate all your help, I do these works but not change. – Simin Soleymanpour Aug 16 '14 at 05:07
-
1it's my code:I=imread('thesis.jpg'); I = double(I); for i=1:m for j=1:n angle = atan2(norm(cross(I(i,j,:),I_avg)),dot(I(i,j,:),I_avg)); end end – Simin Soleymanpour Aug 16 '14 at 05:11
-
i want to calculate angel or cos() or tan() between I(i,j,:) and I_avg for thresholding but by cos() it is not good and i have to try tan() – Simin Soleymanpour Aug 16 '14 at 05:15
-
now when i run this code it has an error:Undefined function 'norm' for input arguments of type 'double' and attributes 'full 3d real'. – Simin Soleymanpour Aug 16 '14 at 05:18
-
Now I know why. Your vector is actually a `1x1x3` vector. `norm` interprets this as 3D data when `norm` doesn't support this. You should have put this code in your post in the beginning. I'll modify my answer. – rayryeng Aug 16 '14 at 05:28
-
excuse me i'm new in this site and dont khow how to work. – Simin Soleymanpour Aug 16 '14 at 05:37
-
That's fine. Next time just edit your post with this new information. It prevents us from going back and forth. – rayryeng Aug 16 '14 at 05:37
2 Answers
In your comments, you have shown us how you are actually writing out the angle calculation and it is not the same as how you have put it in your post.
atan2(norm(cross(I(i,j,:),I_avg)),dot(I(i,j,:),I_avg));
I
is an image you are loading in. I'm assuming it's colour because of the way you are subsetting I
. Because I
is a 3D matrix, doing I(i,j,:)
will give you a 1 x 1 x 3
vector when in fact this has to be a 1D vector. norm
does not recognize this structure which is why you're getting this error. Therefore, you need to use squeeze
to remove the singleton dimensions so that this will become a 3 x 1
vector, rather than a 1 x 1 x 3
vector. As such, you need to rewrite your code so that you're doing this instead. Bear in mind that in your comments, angle
is always overwritten inside the for
loop, so you probably want to save the results of each pixel. With this, you probably want to create a 2D array of angles that will store these results. In other words:
I=imread('thesis.jpg');
I = double(I);
angles = zeros(m,n);
I_avg = squeeze(I_avg); %// Just in case
for i=1:m
for j=1:n
pixels = squeeze(I(i,j,:)); %// Add this statement and squeeze
angles(i,j) = atan2(norm(pixels,I_avg)),dot(pixels,I_avg)); %// Change
end
end
Minor note
MATLAB has a built-in function called angle
that determines the angle from the origin to a complex number in the complex plane. It is not recommended you call your variable angle
as this will unintentionally shadow over the angle
function, and any other code that you create from this point onwards may rely on that actual angle
function, and you will get unintended results.
Another minor note
Using i
and j
as loop variables is not recommended. These letters are reserved for the complex number, and this can produce unintentional results. Take a look at this question and post by Shai here - Using i and j as variables in Matlab. As such, it is suggested you use other variable names instead.
-
+1 `norm`, `a`, `b`, something must be wrong (different than expected) between them. – Yvon Aug 15 '14 at 17:06
-
does here allow betting? I'll give you 15 rep if you don't have a green tick in 2 days – Yvon Aug 16 '14 at 05:49
-
1@Yvon - Ahahaha you have a lovely sense of humour. My bet is that I won't hear from the OP again. I solved his/her problem, and off they go about with their business. The only thing I really got from all of this is to make sure the OP posts everything about the question that doesn't distract from the overall goal. The more information like this, the better. – rayryeng Aug 16 '14 at 05:54
-
thank you so much for your help and this site.it is very good and useful.thank you again. – Simin Soleymanpour Aug 16 '14 at 16:20
-
i'm work on face retrieval and have a lot of question about it and its simulation! – Simin Soleymanpour Aug 16 '14 at 16:22
-
@SiminSoleymanpour - You're welcome. I've also slightly edited my question so you can store the angles for each pixel in the image. Please consider accepting my answer too by clicking on the checkmark icon at the top of my post, to the left underneath the up and down voting buttons. Thanks! – rayryeng Aug 16 '14 at 16:32
-
if i have other questions about another part of my code,i ask here in comments or other post? – Simin Soleymanpour Aug 17 '14 at 05:51
-
both answer of you is good and i want to give green tick to both answer .but i dont know how do this work/ – Simin Soleymanpour Aug 18 '14 at 04:00
-
@SiminSoleymanpour - Unfortunately you can't accept both answers :( You can only accept one. As such, choose either my answer or Yvon's. Good luck! – rayryeng Aug 18 '14 at 04:09
As @rayryeng has successfully answered this question, I would like to turn my post into a more general one by sharing my experience in debugging in Matlab. I hope anyone who somehow managed to find this post get more or less thinking about the habits a good programmer should have.
The question goes like: "How would I do if I get errors?"
Here's an excellent article by Eric in which he lists the rule-of-thumbs when you encounter a bug and wish to get rid of it. It's originally been cited by Stackoverflow, and that's the reason I read it.
If you still get no clue / idea how you can play with your code, see how this person does:
Pin-point the buggy line
(The number should start with 0) Make sure before running a script, you
clear
out any previously stored variables, including the notoriousi
andj
's (you should never see them in any workspace). If any one is needed for the buggy code to run,save('buggy.mat','importantvar')
beforeclear
andload('buggy.mat')
after clear.By doing so, you can isolate your buggy code from anything else, which could have bad influences. For example, in a previously called script, there is a line
double = [2,4,6]; % you should never name a variable `double`
and in the next script, you have
>> e = str2num('uint8(200)') e = 200 >> double(e) Index exceeds matrix dimensions. >> >> f = single(2.36) f = 2.3600 >> double(f) Subscript indices must either be real positive integers or logicals. >>
The reason is
double
is no longer an inbuild function, but a user-defined variable. Too bad to pick up a name carelessly!....anyway, let's
clear
the workspace and get rid ofdouble
.>> clear
Read the error message, thoroughly.
Now let's begin with OP's problem. The original code (trimmed) goes like this -
img = imread('peppers.png'); a = img(300,200,:); b = img(200,300,:); d = norm(cross(a,b));
.... hence the error
Undefined function 'norm' for input arguments of type 'uint8'. Error in untitled (line 6) d = norm(cross(a,b));
Most beginners are only interested in the first line of the error message, which by it alone usually doesn't provide any useful help, or only in the red color, which leads to the famous question "my code does not work!"
But think twice. You still have another 2 lines unread!
Error in untitled (line 6)
says I'm running a script nameduntitled
and the (first) error lies in line 6, and the code in that line isd = norm(cross(a,b));
.Now, at least you know a little more about your code - "My code
d = norm(cross(a,b));
doesn't work!"Although most likely we may also vote this kind of question to get closed, it's still much much better than a simply "It does not work!".
Now we can pin-point the buggy line
try % this line will raise an error d = norm(cross(a,b)); catch err disp(err.message) end
Look into the functions
First, make sure the inner function cross
works as expected -
>> cross(a,b)
ans(:,:,1) =
0
ans(:,:,2) =
255
ans(:,:,3) =
0
>>
Good. So now we can even narrow down the error to the outer norm
.
One more thing to mention. You can always find Mathworks' documentation for any in-build function, by typing "matlab function", such as "matlab norm" in Google (or any other search engine) and clicking on the first result. If you prefer, you can also type in Matlab command window doc _function_
such as doc norm
and read the doc in Matlab. It's of course a pleasure of us on Stackoverflow to give you the reference by doing the same thing, but it takes a longer time because a human is, in this aspect, always slower than a search engine.
The error reads Undefined function 'norm' for input arguments of type 'uint8'.
. So the input for norm
should not be uint8
, unsigned 8-bit integer. But what should it be?
% why `norm` "does not work"?
% this line runs perfectly well
norm(cross([1,2,3], [4,5,6]))
% so what is working?
class([1,2,3]) % so `norm` works for `double`
One thing we can do now is convert a
and b
to double precision. Let's try it now.
% try fixing 'uint8' error
a2 = double(a);
b2 = double(b);
whos a b % now they are double, which `norm` should work for
try
% this line will raise an error
d = norm(cross(a2,b2));
catch err
disp(err.message)
end
Now the error becomes Input must be 2-D.
. What's wrong with the input?
% what is "must be 2-D" error?
size(a2) % a2 is 3-D
disp(b2) % b2 is also 3-D
This gives output in command window
ans =
1 1 3
(:,:,1) =
255
(:,:,2) =
150
(:,:,3) =
0
In OP's problem, he/she is trying to calculate something about color difference (to the best of my knowledge) which involves the angle between two color vectors in RGB space. So the vectors are needed. With imread
, each pixel of the image is stored as 3 elements in the matrix, first 2 dimension being its physical position, the 3 dimension being RGB channel components. Hence pixel(200,300) with color rgb[255,150,0] is stored by us in variable b
wihch is a 3-D vector.
By understanding what we need and what Matlab can do, we can combine these two points into one. We need the norm of the cross product of a
and b
, while the useful information (the 3 component values) is stored in the 3rd dimension. Matlab can calculate the norm of the cross product of a vector with all its information in the 1st dimension. (Here, "dimension" refers to that of the Matlab variable; a vector with 3 elements in its 1st dimension is physically a 3-D vector).
After thinking twice, we are now able to debug our code - just put all 3 elements into the 1st dimension.
% so we want the 3 elements in the 3rd dimension become in the 1st dim
a3 = squeeze(a2);
b3 = reshape(b2,numel(b2),[]);
try
d = norm(cross(a3,b3));
catch err
disp(err.message)
end
d
Bonus: If by default Matlab treats a 3-D vector as a "1-D array", then most probably the cross
function has not been working correctly. Let's make a check -
>> clear
>> a = [1,2,3]
a =
1 2 3
>> b=[4,5,6]
b =
4 5 6
>> cross(a,b)
ans =
-3 6 -3
>>
The result should be the same as the one we can get by calculating by hand.
Now if we put the components into the 3rd dimension of the variable -
>> clear
>> a(1,1,:)=[1,2,3]
a(:,:,1) =
1
a(:,:,2) =
2
a(:,:,3) =
3
>> b(1,1,:)=[4,5,6]
b(:,:,1) =
4
b(:,:,2) =
5
b(:,:,3) =
6
>> cross(a,b)
ans(:,:,1) =
-3
ans(:,:,2) =
6
ans(:,:,3) =
-3
>>
.... seems OK. cross
also puts the result in the 3rd dimension. In fact, Mathworks' documentation says
If A and B are vectors, then they must have a length of 3.
If A and B are matrices or multidimensional arrays, then they must have the same size. In this case, the cross function treats A and B as collections of three-element vectors. The function calculates the cross product of corresponding vectors along the first array dimension whose size equals 3.
At last, one thing is always correct to anyone who wants to do something with programming - be cautious and prudent when writing your code.

- 21,988
- 13
- 81
- 109

- 2,903
- 1
- 14
- 36
-
+1 - Very nice. I didn't consider the fact that a script called `norm` could be existing too. – rayryeng Aug 15 '14 at 17:00
-
I figured out why the OP is experiencing the problem. `norm` was interpreting the vector as a three dimensional array. He/she was extracting a 3D vector from an image by doing `I(i,j,:)` which produces a `1 x 1 x 3` array. `norm` does not support 3D matrices, which is why they were getting the error. I found out just now because the OP posted the actual code that they were doing in the comments. Why can't they just give us all the info in the beginning? – rayryeng Aug 16 '14 at 05:36
-
@rayryeng Since your answer is good and complete, there is no use I post another duplicate; but after thinking for a while I decided to put something more in this post. Hoping this can bring help to more people. – Yvon Aug 16 '14 at 19:39
-
Very nice answer Yvon. I'd give you more votes, but I've already voted. I'm almost tempted to give you a bounty for such a quality answer! – rayryeng Aug 17 '14 at 05:49