title: Matlab mode filter for dependent RGB channels
body: <p>I've been performing a 2D mode filter on an RGB image by running medfilt2 independently on the R,G and B channels. However, splitting the RGB channels like this gives artifacts in the colouring. Is there a way to perform the 2D median filter while keeping RGB values 'together'?</p>
  
  <p>Or, I could explain this more abstractly: Imagine I had a 2D matrix, where each value contained a pair of index coordinates (i.e. a cell matrix of 2X1 vectors). How would I go about performing a median filter on this?</p>
  
  <p>Here's how I can do an independent mode filter (giving the artifacts):</p>
  
  <pre><code>r = colfilt(r0,[5 5],'sliding',@mode);
  g = colfilt(g0,[5 5],'sliding',@mode);
  b = colfilt(b0,[5 5],'sliding',@mode);
  </code></pre>
  
  <p>However colfilt won't work on a cell matrix. </p>
  
  <p>Another approach could be to somehow combine my RGB channels into a single number and thus create a standard 2D matrix. Not sure how to implement this, though...</p>
  
  <p>Any ideas?</p>
  
  <p>Thanks for your help.</p>
  
  <p>Cheers,
  Hugh</p>
  
  <p>EDIT:
  OK, so problem solved. Here's how I did it.</p>
  
  <p>I adapted my question so that I'm no longer dealing with (RGB) vectors, but (UV) vectors. Still essentially the same problem, except that my vectors are 2D not 3D.</p>
  
  <p>So firstly I load the individual U and V channels, arrange them each into a 1D list, then combine them, so I essentially have a list of vectors. Then I reduce it to just those which are unique. Then, I assign each pixel in my matrix the value of the index of that unique vector. After this I can do the mode filter. Then I basically do the reverse, in that I go through the filtered image pixelwise, and read the value at each pixel (i.e. an index in my list), and find the unique vector associated with that index and insert it at that pixel.</p>
  
  <pre><code>%   Create index list
  img_u = img_iuv(:,:,2);
  img_v = img_iuv(:,:,3);
  coordlist = unique(cat(2,img_u(:),img_v(:)),'rows');
  %   Create a 2D matrix of indices
  img_idx = zeros(size(img_iuv,1),size(img_iuv,2),2);
  for y = 1:length(Y)
      for x = 1:length(X)
          coords = squeeze(img_iuv(x,y,2:3))';
          [~,idx] = ismember(coords,coordlist,'rows');
          img_idx(x,y) = idx;       
      end
  end
  %   Apply the mode filter
  img_idx = colfilt(img_idx,[n,n],'sliding',@mode);
  %   Re-construct the original image using the filtered data
  for y = 1:length(Y)
      for x = 1:length(X)
          idx = img_idx(x,y);
          try
              coords = coordlist(idx,:);
          end
          img_iuv(x,y,2:3) = coords(:);    
      end
  end
  </code></pre>
  
  <p>Not pretty but it gets the job done. I suppose this approach would also work for RGB images, or other similar situations. </p>
  
  <p>Cheers,
  Hugh</p>