Perform mldivide between 3x3 matrix M and every RGB pixel in a image in GPU

2 vues (au cours des 30 derniers jours)
Chi Huang
Chi Huang le 7 Juil 2022
Commenté : Paul le 12 Juil 2022
I have a rgb image (2048x2048x3), and I wan to perform mldivide on every rgb (3,1) pixels with a M matrix (3x3).
So each pixel will do a M\pixel operation. The easy way to do this is using two for loops to go over each pixels. However, I am wondering if I can use arrayfun or pagefun for this so I can use GPU.
Right now in order to use arrayfun, I have to hard code mldivide so M becomes 9x4194304(2048*2048) array which takes lots of vram. I am wondering if there is a way I can run this without having a big M gpu array as input.
  3 commentaires
Chi Huang
Chi Huang le 8 Juil 2022
Sorry I made a mistake, it it will be a 3x1 matrix, rand(3,1). I forgot matlab has y,x convention.
Stephen23
Stephen23 le 8 Juil 2022
"Sorry I made a mistake, it it will be a 3x1 matrix, rand(3,1). I forgot matlab has y,x convention."
... I guess you mean all of mathematics has that convention: https://en.wikipedia.org/wiki/Matrix_(mathematics)

Connectez-vous pour commenter.

Réponse acceptée

Stephen23
Stephen23 le 8 Juil 2022
format compact
S = 5;
M = rand(3,3);
I = rand(S,S,3);
% reference:
A = nan(S,S,3);
for ii = 1:S
for jj = 1:S
pixel = reshape(I(ii,jj,:),3,1);
A(ii,jj,:) = M\pixel;
end
end
A
A =
A(:,:,1) = 4.2226 15.3976 9.7294 0.6686 -8.5764 15.5251 -0.8818 3.5689 4.1730 2.4676 7.1266 -6.9632 9.8103 10.5705 15.3470 7.5849 0.9940 16.1186 -0.2064 16.8039 -7.8875 -7.1051 0.2250 2.7415 -7.6742 A(:,:,2) = 0.7674 3.0061 1.4504 1.4626 0.3589 2.4699 2.0878 2.4253 1.5477 2.3345 1.0364 0.5316 1.4698 2.3068 2.5930 1.5519 2.5403 3.6515 1.6914 2.3027 0.6423 0.3699 1.7695 2.2491 0.0037 A(:,:,3) = -1.0156 -6.3149 -3.2293 -0.7714 2.6126 -5.7948 -0.6883 -2.1061 -2.1869 -1.4797 -2.2634 1.9633 -3.2872 -4.0813 -5.4468 -2.4617 -1.5182 -6.7929 -0.7229 -5.7964 2.5722 2.1096 -1.0220 -1.5365 2.8622
Remember that RESHAPE is a very fast operation (it does not change your data in memory, only the shape meta-data in its header). In contrast you want to avoid operations that rearrange your data in memory (e.g. TRANSPOSE, PEMUTE). Note that using PAGEFUN would require permutimh your data.
% RESHAPE() and TRANSPOSE() and MLDIVIDE():
B = reshape((M\reshape(I,S*S,3).').',S,S,3)
B =
B(:,:,1) = 4.2226 15.3976 9.7294 0.6686 -8.5764 15.5251 -0.8818 3.5689 4.1730 2.4676 7.1266 -6.9632 9.8103 10.5705 15.3470 7.5849 0.9940 16.1186 -0.2064 16.8039 -7.8875 -7.1051 0.2250 2.7415 -7.6742 B(:,:,2) = 0.7674 3.0061 1.4504 1.4626 0.3589 2.4699 2.0878 2.4253 1.5477 2.3345 1.0364 0.5316 1.4698 2.3068 2.5930 1.5519 2.5403 3.6515 1.6914 2.3027 0.6423 0.3699 1.7695 2.2491 0.0037 B(:,:,3) = -1.0156 -6.3149 -3.2293 -0.7714 2.6126 -5.7948 -0.6883 -2.1061 -2.1869 -1.4797 -2.2634 1.9633 -3.2872 -4.0813 -5.4468 -2.4617 -1.5182 -6.7929 -0.7229 -5.7964 2.5722 2.1096 -1.0220 -1.5365 2.8622
% we can simplify the above into RESHAPE() and MRDIVIDE():
C = reshape((reshape(I,S*S,3)/M.'),S,S,3) % recommended
C =
C(:,:,1) = 4.2226 15.3976 9.7294 0.6686 -8.5764 15.5251 -0.8818 3.5689 4.1730 2.4676 7.1266 -6.9632 9.8103 10.5705 15.3470 7.5849 0.9940 16.1186 -0.2064 16.8039 -7.8875 -7.1051 0.2250 2.7415 -7.6742 C(:,:,2) = 0.7674 3.0061 1.4504 1.4626 0.3589 2.4699 2.0878 2.4253 1.5477 2.3345 1.0364 0.5316 1.4698 2.3068 2.5930 1.5519 2.5403 3.6515 1.6914 2.3027 0.6423 0.3699 1.7695 2.2491 0.0037 C(:,:,3) = -1.0156 -6.3149 -3.2293 -0.7714 2.6126 -5.7948 -0.6883 -2.1061 -2.1869 -1.4797 -2.2634 1.9633 -3.2872 -4.0813 -5.4468 -2.4617 -1.5182 -6.7929 -0.7229 -5.7964 2.5722 2.1096 -1.0220 -1.5365 2.8622
  1 commentaire
Chi Huang
Chi Huang le 8 Juil 2022
wow thx,
Shuld have think about side of the out of the diea of looping the pixels.

Connectez-vous pour commenter.

Plus de réponses (2)

Joss Knight
Joss Knight le 9 Juil 2022
Modifié(e) : Joss Knight le 10 Juil 2022
I feel like I'm missing something - this is just a single backslash with multiple right-hand sides, or to avoid permutation a single mrdivide (edit: you still have to transpose M, but that's very quick):
[h,w] = size(im,[1 2]);
imout = reshape(reshape(im,[],3)/(M.'), h, w, 3);
  23 commentaires
Bruno Luong
Bruno Luong le 12 Juil 2022
For b that is vector,
  • A\b complexity O(n^2),
  • inv(A)*b has O(n^3),
and you find various tic/toc along the discussion above.
For b that is n x m
  • A\b complexity O(n^2)+O(n*m),
  • inv(A)*b has O(n^3)+O(n*m),
with the O(n*m) much favarable to the inv(), possibly 6-10 time faster for small n and large m as for the OP's question here.
Paul
Paul le 12 Juil 2022
No worries. I just deleted my comment that flagged your edit and it looks like Stephen23 deleted his related comment. If you delete your comment and can delete this comment as well, we'll go back to having a nice, clean thread as if it never happened.

Connectez-vous pour commenter.


Bruno Luong
Bruno Luong le 11 Juil 2022
Modifié(e) : Bruno Luong le 11 Juil 2022
B = reshape(reshape(I,[],3)*inv(M.'),size(I));

Catégories

En savoir plus sur Operating on Diagonal Matrices dans Help Center et File Exchange

Produits


Version

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by