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

2 Ansichten (letzte 30 Tage)
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 Kommentare
Chi Huang
Chi Huang am 8 Jul. 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 am 8 Jul. 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)

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Stephen23
Stephen23 am 8 Jul. 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

Weitere Antworten (2)

Joss Knight
Joss Knight am 9 Jul. 2022
Bearbeitet: Joss Knight am 10 Jul. 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 Kommentare
Bruno Luong
Bruno Luong am 12 Jul. 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 am 12 Jul. 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.

Melden Sie sich an, um zu kommentieren.


Bruno Luong
Bruno Luong am 11 Jul. 2022
Bearbeitet: Bruno Luong am 11 Jul. 2022
B = reshape(reshape(I,[],3)*inv(M.'),size(I));

Kategorien

Mehr zu Operating on Diagonal Matrices finden Sie in Help Center und File Exchange

Produkte


Version

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by