The code
is equivalent to
v1=ones(200,200)*10*rand();
because rand is always U(0,1), so abs(rand()) is unnecessary, and bcause the nested loop assigns the same value to every element.
Image v1 will be a white square 90% of the time. In the other 10% of cases, it will be a square that is a uniform shade of gray. This happens because when Matlab renders a floating point array as an image, it assumes the values are gray scale values between 0 and 1. Values <=0 plot as black. Values >=1 plot as white. The value 10*rand() will convert to white, 90% of the time.
Images v2-v5 are comprised of numbers that vary between -1 and 1. All the negative valued pixels will be rendered as black, as described above. The PCA operates on the negative and positive values, but all negative values are black in the images. Therefore there is a strong nonlinearity in the relationship between the numbers in the array and the rendered image. This reduces the effectiveness of PCA in reproducing the images. For these reasons, I recommend generating basis images with values that vary between 0 and 1 only. For example, replace cos(x) with (1+cos x)/2; replace sin(x) with (1+sin x)/2.
Pixel values in vec and vec2 vary from -0.5 to +0.5. Is this intentional? I would choose variation from 0 to 1, to display the full dynamic range from black to pure white. This will also have the benefit that the range for vec and vec2 will match the ranges of the basis images, v1-v5, which vary from black to pure white.
Because negative numbers are rendered as black, I recommend that you not subtract the mean value from all the columns. I have obtained good results with PCA applied to images when I did not subtract the mean value. See here, for example. It is good to view the images you are working with. Therefore I have added code to display some images. Images created by the original code are shown below. The appearance of these images is significantly affected by the size at which they are displayed. Moire patterns appear and disappear as one adjusts the image size.
Here (below) are images generated by the modified code. These images are different from the previous, because (1) the random numbers are different with every run, and (2) v1, which was formerly all white in 90% of cases, is now an intermediate shade of gray, and (3) I have replaced sin x with (1+sin x)/2, etc., for v2-v5, and (4) I have replaced (0.5*sin x) with (0.5 + 0.5*sin x) for vec and vec2. Changes (3) and (4) result in fewer black pixels, and eliminate extensive all-black regions.
At the end of your script, you compute sum1, which is supposed to be a reconstruction of vec, using the principal components. The figure below shows vec and sum1, as generated by your originally posted code.
The figure below shows vec and sum1, as generated by the modified code. vec differs from run to run, due to the random number used to generate it.
One way to compare the similarity of vec and sum1 is to convert each image to a column vector, then compute the Pearson correlation of the column vectors.
>> disp(corr(reshape(sum1,[40000,1]),reshape(vec,[40000,1])))
0.9959
Here are the correlations for five runs of the original code.
0.6986 0.7188 0.7145 0.7014 0.8616
Here are correlations for five runs of the modified code.
0.9941 0.7252 0.9533 0.5947 0.9959
It is a small sample size. It seems like the modified code produces correlations with higher highs and lower lows .