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

2 ビュー (過去 30 日間)
Chi Huang
Chi Huang 2022 年 7 月 7 日
コメント済み: Paul 2022 年 7 月 12 日
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 件のコメント
Chi Huang
Chi Huang 2022 年 7 月 8 日
Sorry I made a mistake, it it will be a 3x1 matrix, rand(3,1). I forgot matlab has y,x convention.
Stephen23
Stephen23 2022 年 7 月 8 日
"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)

サインインしてコメントする。

採用された回答

Stephen23
Stephen23 2022 年 7 月 8 日
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 件のコメント
Chi Huang
Chi Huang 2022 年 7 月 8 日
wow thx,
Shuld have think about side of the out of the diea of looping the pixels.

サインインしてコメントする。

その他の回答 (2 件)

Joss Knight
Joss Knight 2022 年 7 月 9 日
編集済み: Joss Knight 2022 年 7 月 10 日
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 件のコメント
Bruno Luong
Bruno Luong 2022 年 7 月 12 日
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 2022 年 7 月 12 日
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.

サインインしてコメントする。


Bruno Luong
Bruno Luong 2022 年 7 月 11 日
編集済み: Bruno Luong 2022 年 7 月 11 日
B = reshape(reshape(I,[],3)*inv(M.'),size(I));

カテゴリ

Help Center および File ExchangeOperating on Diagonal Matrices についてさらに検索

製品


リリース

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by