Как получить цвет фона произвольного изображения с помощью MATLAB? - PullRequest
3 голосов
/ 10 апреля 2010

Это еще один вопрос возник из этого

Как программно получить цвет фона изображения?

Пример:

alt text

Для приведенного выше изображения цвет фона белый.

1 Ответ

5 голосов
/ 10 апреля 2010

Как обсуждалось в комментариях к самому вопросу, понятие "цвет фона" довольно субъективно, поэтому на самом деле невозможно написать алгоритм, гарантирующий желаемый результат для всех входных данных.

Тем не менее, я думаю, что я понимаю, что вы пытаетесь выполнить, и я написал пару функций MATLAB, которые довольно успешно определяют вероятный цвет фона для ряда входных изображений, которые я пробовал .

Эвристика, которую я использовал, основана на наблюдении, что, вообще говоря, цвет фона изображения, вероятно, будет областями низкочастотной информации, в то время как передний план, вероятно, будет высокочастотным. (Обратите внимание, что когда это не так, моя функция getBackgroundColor с треском провалится.) Итак, что я делаю, это изолирую высокочастотную информацию в частотной области, преобразую ее обратно в пространственную область, «разложив» выделенные пиксели, чтобы охватить широкие высокочастотные области, а затем просто удалить эти пиксели.

В коде есть множество мест, которые можно сжать и использовать для повышения производительности вашего конкретного приложения, но, похоже, он хорошо работает для широкого спектра тестовых случаев, как есть.

getBackgroundColor.m:

function [img, meanColor, modeColor] = getBackgroundColor (img)
%
% function [img, meanColor, modeColor] = getBackgroundColor (img)
%
%    img   -   Either a string representing the filename of an image to open
%              or an image itself.  If the latter, it must be either a
%              3-dimensional matrix representing an RGB image or a 2-dimensional
%              matrix representing a grayscale image.

if ischar(img)
  img = imread(imageFile);
end
img = double(img);

% Handle RGB and Grayscale separately.
if ndims(img)==3
  % There are probably some spiffy ways to consolidate this sprawl
  % so that the R, G, and B channels are not being processed
  % independently, but for the time being, this does work.
  red   = getBG(img(:, :, 1));
  green = getBG(img(:, :, 2));
  blue  = getBG(img(:, :, 3));

  % For each channel, remove the "foreground" regions identified in
  % each of the other channels.
  red(isnan(green)) = NaN;
  red(isnan(blue)) = NaN;

  green(isnan(red)) = NaN;
  green(isnan(blue)) = NaN;

  blue(isnan(red)) = NaN;
  blue(isnan(green)) = NaN;

  % Compute the mean and mode colors.
  meanColor = [ ...
      mean(mean( red(~isnan(red)) )) ...
      mean(mean( green(~isnan(green)) )) ...
      mean(mean( blue(~isnan(blue)) )) ];
  modeColor = [ ...
      mode(mode( red(~isnan(red)) )) ...
      mode(mode( green(~isnan(green)) )) ...
      mode(mode( blue(~isnan(blue)) )) ];

  % Update each the foreground regions of each channel and set them
  % to their mean colors.  This is only necessary for visualization.
  red(isnan(red)) = meanColor(1);
  green(isnan(green)) = meanColor(2);
  blue(isnan(blue)) = meanColor(3);

  img(:, :, 1) = red;
  img(:, :, 2) = green;
  img(:, :, 3) = blue;
else
  img = getBG(img);
  meanColor = mean(mean( img( ~isnan(img) ) ));
  modeColor = mode(mode( img( ~isnan(img) ) ));
  img(isnan(img)) = meanColor;
end

% Convert the image back to integers (optional)
img = uint8(img);

% Display the results before returning
display(meanColor)
display(modeColor)



  function image = getBG (image)
      mask = getAttenuationMask(size(image), min(size(image)) / 2, 0, 1);

      % Assume that the background is mostly constant, so isolate the high-frequency
      % parts of the image in the frequency domain and then transform it back into the spatial domain
      fftImage = fftshift(fft2(image));
      fftImage = fftImage .* mask;
      invFftImage = abs(ifft2(fftImage));

      % Expand the high-frequency areas of the image and fill in any holes.  This should
      % cover all but the (hopefully) low frequency background areas.
      edgeRegion = imfill(imdilate(invFftImage, strel('disk', 4, 4)), 'holes');

      % Now remove the parts of the image that are covered by edgeRegion
      edgeMean = mean(mean(edgeRegion));
      image(edgeRegion>edgeMean) = NaN;
  end
end

getAttenuationMask.m:

function mask = getAttenuationMask (maskSize, radius, centerValue, edgeValue)
%
% function mask = getAttenuationMask (maskSize, radius, centerValue, edgeValue)
%

if nargin==2
  centerValue = 1;
  edgeValue = 0;
end

width = maskSize(1);
height = maskSize(2);

mx = width / 2;
my = height / 2;

mask=zeros(maskSize);

for i=1:width
  for j=1:height
      d = sqrt( (i-mx)^2 + (j-my)^2 );
      if (d >= radius)
        d = edgeValue;
      else
        d = (centerValue * (1 - (d / radius))) + (edgeValue * (d / radius));
      end

      mask(i, j) = d;
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...