2010-04-10 78 views
2

這是從this one如何使用MATLAB檢索任意圖像的背景顏色?

springed另一個問題如何以編程方式獲取圖像的背景顏色?

實施例:

alt text

對於上述圖像中,背景顏色是白色。

+0

你們是不是要(1)分析像素矩陣分離前臺和後臺功能,以確定一個主導的背景顏色, (2)識別已經用於填充圖像的顏色,(3)從MATLAB圖像/軸/圖形對象中檢索背景顏色屬性,或者(4)完全是其他內容?一個例子會讓你更容易回答你的問題。 – RTBarnard 2010-04-10 04:15:34

+0

問題是你的「背景色」的定義。以此圖像爲例(http://farm4.static.flickr.com/3104/3238518077_1ef13a8e93.jpg)。什麼應該被視爲背景顏色?天空的顏色?水的顏色?或者也許是山的顏色?圖像只是一組彩色像素,一個包含一串數字的矩陣,這些數字被解釋爲每個點的顏色。沒有設置「背景顏色」。您必須自己決定如何定義它(即圖像中所有顏色的均值,最常出現的顏色等)。 – gnovice 2010-04-10 04:16:55

+0

@gnovice,我無法爲您提供的圖像中的背景顏色提供一個好的定義,但可以在我的文章中顯示圖像,這是白色的。我不知道如何在一般案件。 – user198729 2010-04-10 04:26:04

回答

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://gnackoverflow.com/questions/2605202/how-to-automate-the-padding-for-arbitary-images-using-matlab – user198729 2010-04-10 11:55:22

+0

從@gnovice缺陷接受的答案是什麼?在我看來,他提出的解決方案中的任何(或全部)解決方案都可以與我的'getBackgroundColor'函數協同工作:調用我的函數以獲取適當的填充顏色,然後用該顏色調用其中一個填充函數。也許我誤解了你的想法。 – RTBarnard 2010-04-10 12:44:44

+0

這種依賴於背景顏色的解決方案對於沒有明顯背景色的圖像效果不佳,如下所示:http://farm4.static.flickr.com/3104/3238518077_1ef13a8e93.jpg – user198729 2010-04-10 14:08:00