2010-04-10 2 views
2

Это еще вопросы, заданные от this one,Как получить фоновый цвет произвольного изображения с помощью MATLAB?

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

Пример:

alt text

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

+0

Вы пытаетесь (1) анализировать матрицу пикселей, чтобы отделить функции переднего плана и фона, чтобы определить доминирующий цвет фона, (2) определить цвет, который использовался для прокладки изображения, (3) извлечь атрибут цветового фона из объекта изображения/оси/фигуры MATLAB или (4) что-то еще полностью? Пример упростит ответ на ваш вопрос. – RTBarnard

+0

Проблема заключается в вашем определении «цвет фона». Возьмите это изображение, например (http://farm4.static.flickr.com/3104/3238518077_1ef13a8e93.jpg). Что следует учитывать как цвет фона? Цвет неба? Цвет воды? Или, может быть, цвет гор? Изображение - это всего лишь набор цветных пикселей, матрица, содержащая набор чисел, которые интерпретируются как цвета для каждой точки. Не установлен «цвет фона». Вы должны сами решить, как его определить (т. Е. Среднее значение всех цветов изображения, наиболее часто встречающийся цвет и т. Д.). – gnovice

+0

@gnovice, я не могу найти хорошее определение цвета фона в изображении, которое вы предоставили, но может для изображения в моем посте, который является белым. Скажем, я не знаю, как определить его в общем дело. – user198729

ответ

5

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

Тем не менее, я думаю, что я понимаю, чего вы пытаетесь выполнить, и я написал пару функций 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 
+0

@ RTBarnard, спасибо за ответ! Можете ли вы взглянуть на этот вопрос, чтобы увидеть, возможно ли преобразовать изображение в квадрат без требования назначить цвет фона явно, но все же сохранить результат будет естественным? http://stackoverflow.com/questions/2605202/how-to-automate-the-padding-for-arbitary-images-using-matlab – user198729

+0

Каким образом приемлемый ответ от @gnovice недостаточен? Мне кажется, что любой (или все) его предлагаемые решения могут работать в тандеме с моей функцией getBackgroundColor: вызовите мою функцию, чтобы получить соответствующий цвет заполнения, а затем вызовите одну из функций заполнения с этим цветом. Может быть, я не понимаю, что тебе нужно. – RTBarnard

+0

Этот вид решения, который зависит от цвета фона, плохо работает с изображениями, которые не имеют очевидного цвета фона, например, этот: http: //farm4.static.flickr.com/3104/3238518077_1ef13a8e93.jpg – user198729