Right and Bottom Edge Cases Causing Issues in Matrix Transformation: Blur Image Assignment
    8 ビュー (過去 30 日間)
  
       古いコメントを表示
    
Hello,
I'm working on the Blur Image problem where a function needs to accept a matrix and average out pixel values using a submatrix around each. As far as I can tell, my code works perfectly everywhere except in the last row and column and I'm struggling to find what the error is. The full assignment prompt is below.
Write a function called blur that blurs the input image. The function is to be called like this:
output = blur(img,w);
where img, the input image is a two-dimensional matrix of grayscale pixel values between 0 and 255. Blurring is to be carried out by averaging the pixel values in the vicinity of every pixel. Specifically, the output pixel value is the mean of the pixels in a square submatrix of size 2w+1 where the given pixel sits in the center. For example, if w is 1, then we use a 3x3 matrix, that is, we average all the neighboring pixels of the given pixel and itself. Only use valid pixels when portions of the blurring matrix fall outside the image. For example, the blurred value corresponding to w = 1 at index (1,1) would be the mean of of elements (1,1), (1, 2), (2,1) and (2, 2). Both input img and output output are of type uint8.
You can download the test image here
M = % Input Matrix
     1     2     3     4     5
     5     4     3     2     1
    10    10    11    12   199
   200   198   105   101   254
     0   255   100   199    99
function [output] = blur(img, w)
    img = im2double(img);            % Convert uint8 to double
    [rowImg, colImg] = size(img);    
    imgBlur = []; 
    for ii=1:rowImg                                 % Row marker
        for jj=1:colImg                             % Col marker
            if ii+w <= rowImg && jj+w <= colImg       % Loop for Top and Left
                % Left & Top Edge cases
                if ii-w < 1 && jj-w < 1               % Top Left Case
                    empty = img(ii:ii+w, jj:jj+w);
                elseif ii-w < 1                       % Top Edge Case
                    empty = img(ii:ii+w, jj-w:jj+w);
                elseif jj-w < 1                       % Left Edge Case
                    empty = img(ii-w:ii+w, jj:jj+w);
                else                                  % Middle Area Case               
                    empty = img(ii-w:ii+w,jj-w:jj+w); 
                end
            elseif ii+w >= rowImg && jj+w >= colImg   % Loop for Bottom and Right
                if ii+w > rowImg && jj+w > colImg     % Bottom Right Case
                    empty = img(ii-w:ii, jj-w:jj);
                elseif ii+w > rowImg                  % Bottom Edge Case SOMETHING WRONG
                    empty = img(ii-w:ii, jj-w:jj+w);
                else % jj+w > colImg                  % Right Edge Case SOMETHING WRONG
                    empty = img(ii-w:ii+w, jj-w:jj);
                end
            elseif ii-w < rowImg && jj+w > colImg     % Top Right Case
                empty = img(ii:ii+w, jj-w:jj);
            else % ii+w > rowImg && jj-w < colImg     % Bottom Left Case
                empty = img(ii-w:ii, jj:jj+1);               
            end
            newPixelVal = mean(empty, 'all');     % Mean of submatrix(w)
            imgBlur(ii,jj) = newPixelVal;         % Save new pixel value in location (ii,jj). This is the final matrix
        end
    end
    output = uint8(imgBlur);    
end
Below I've provided my output as well as the output of known good code using w = 1:
output = % This is my solution using w=1
  5×5 uint8 matrix
     3     3     3     3     3
     5     5     6    27    54
    71    61    50    76   142
   112    99   110   120   144
   163   165   126   143   163
   testsltn = % Correct Solution using w = 1
  5×5 uint8 matrix
     3     3     3     3     3
     5     5     6    27    37
    71    61    50    76    95
   112    99   110   120   144
   163   143   160   143   163
They're very close but obviously something is wrong in my function. I appreciate any help or advice. Thanks!
0 件のコメント
採用された回答
  Hussein Ammar
      
 2020 年 8 月 29 日
        Hello, why don't you use the following:
function [output] = blur(img, w)
    img = im2double(img);            % Convert uint8 to double
    [rowImg, colImg] = size(img);    
    imgBlur = zeros(rowImg, colImg);  % preallocate for speed 
    for ii=1:rowImg                                 % Row marker
            for jj=1:colImg 						% Col marker
                i_start = max(1, ii-w);
                i_end = min(rowImg, ii+w);
                j_start = max(1, jj-w);
                j_end = min(colImg, jj+w);
                myBlock = img(i_start:i_end, j_start:j_end);
                imgBlur(ii,jj) = mean(myBlock(:)); % reshape and get the mean of the resulted vector
            end
    end
    output = uint8(imgBlur);    
end
Output:
imgBlur =
    3.0000    3.0000    3.0000    3.0000    3.0000
    5.3333    5.4444    5.6667   26.6667   37.1667
   71.1667   60.6667   49.5556   76.4444   94.8333
  112.1667   98.7778  110.1111  120.0000  144.0000
  163.2500  143.0000  159.6667  143.0000  163.2500
output =
  5×5 uint8 matrix
     3     3     3     3     3
     5     5     6    27    37
    71    61    50    76    95
   112    99   110   120   144
   163   143   160   143   163
2 件のコメント
  Hussein Ammar
      
 2020 年 8 月 31 日
				
      編集済み: Hussein Ammar
      
 2020 年 8 月 31 日
  
			In your code, there is a problem in the precedence of the if conditions, also when you change the precedence, you end up with mixed cases. I suggest that you redefine the if condtions from scratch.
その他の回答 (0 件)
参考
カテゴリ
				Help Center および File Exchange で Logical についてさらに検索
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

