# مباحث متفرقه برنامه نویسی > برنامه نویسی Matlab >  حذف پیش زمینه از تصویر

## mahsava

تصویری از پشت دست فردی داریم و با استفاده از یکی از الگوریتم های لبه یابی کانتور آن را به دست آورده ایم. حال می خواهیم با استفاده از این کانتور (و یا روش بهتری) شیء را از تصویر جدا کرده و پیش زمینه را حذف کنیم. چه کدی باید نوشته شود؟
(سعی کردم تصاویر را اضافه کنم ولی نشد!)

----------


## rahnema1

توی تاپیک زیر این مباحث گفته شده
https://barnamenevis.org/showthread.php?458959

----------


## mahsava

ممنون. تاپیک مفیدی بود. اما مشکل من همون ابتدای کاره. تو اون تاپیک چون شکل هندوانه کاملا محدب هست راحت میشه با استفاده از کانتور از پیش زمینه جداش کرد. اما شکلی که من دارم تصویر یک دسته.

1.jpg

که کانتورش رو به دست آوردم

2.jpg

حالا میخوام از روی کانتور یه ماسک درست کنم که با کانوالو کردنش در تصویر اصلی بتونم کل دست رو از پیش زمینه جدا کنم. کدش رو نوشتم اما خطا داره. مشکل قسمت هایی از کانتوره که لبه ی افقی داریم (که ممکنه طولش دو پیکسل یا بیشتر باشه).

----------


## mahsava

کد رو باید بین چه تگی قرار بدم که تروتمیز دیده بشه؟

----------


## mahsava

function [ maskIm ] = contour2mask( contourIm )
% this function get a contour (binary image), fill inside of it with 1 and
% return a binary mask
rowsNo = size(contourIm,1);
colsNo = size(contourIm,2);
maskIm = zeros(rowsNo,colsNo);
for i=1:rowsNo
    sw = 1;
    startPoint = 0;
    endPoint = 0;
    count = 0;
    j = 1;
    while j < colsNo
        if i == 181 
            a = 0;
        end
        while j < colsNo && ~contourIm(i,j) % find first 1
            j = j + 1;
        end
        if j < colsNo 
            startPoint = j;
            count = 1;
            else break; % no 1s
        end
        while j < colsNo && contourIm(i,j) % find next 0
            count = count + 1;
            j = j + 1;
        end
        if count > 3
            sw = 0;
            endPoint = startPoint + count - 1;
        else while j < colsNo && ~contourIm(i,j) % find next 1
                count = count + 1;
                j = j + 1;
             end
             if j < colsNo && contourIm(i,j)
                count = count + 1;
                j = j + 1;
             end
             if j <= colsNo && contourIm(i,j)
                count = count + 1;
                j = j + 1;
             end
                endPoint = startPoint + count - 1;
                
        end
    for k=startPoint:endPoint
        maskIm(i,k) = 1;
    end    
    j = j + 1;
    end
end

----------


## rahnema1

مهم اینه که یک محدوده کاملا بسته داشته باشیم تا بتونید اون را پر کنیم
اون لبه دست که شما گذاشته بودید بعضی جا ها منافذی داشت که با عملیات مورفولوژیکی پر شد پایین دست هم باید بسته می شد
در شمن به جای اون حلقه میشه از دستور imfill استفاده کرد که داخل محدوده را پر کنه
غیر از این روش یک روش دیگه را می تونید استفاده کنید که لبه دست را با استفاده از گزینه Lindeberg از دستور edge به دست بیارید و تعداد زیادی خط ایجاد می شه که بلند ترین اونها لبه دست مورد نظره که با استفاده از bwconncomp و لیبل گذاری هر سگمنت میشه اون را استخراج و داخل اون را پر کرد

contourIm=imread('2.bmp')>100;
maskIm=contourIm;
kernel=[-1, -size(maskIm,1), 1, size(maskIm,1)];
maskIm=(bwmorph(bwmorph(maskIm,'bridge'),'spur'));
maskIm=(bwmorph(maskIm & bwmorph(maskIm==0,'majority'),'bridge'));
maskIm=(bwmorph(maskIm,'shrink'));
idx=find(maskIm-bwmorph(maskIm,'shrink'));
[p1r p1c]= ind2sub(size(maskIm),idx(1));
[p2r p2c]= ind2sub(size(maskIm),idx(2));
Length=max([abs(p2c-p1c) abs(p2r-p1r)])+2;
lr= round(linspace(p1r,p2r,Length));
lc= round(linspace(p1c,p2c,Length));
idx2=sub2ind(size(maskIm),lr,lc);
maskIm(idx2)=1;
list1=[sub2ind(size(maskIm),round(size(maskIm,1)/2),round(size(maskIm,2)/2))];
while numel(list1)>0
	list2=[];
	for L=1:numel(list1)
		idxkernel=list1(L)+kernel;
		idxfill=idxkernel(find(maskIm(idxkernel)==0));
		maskIm(idxfill)=1;
		list2=[list2 idxfill];
	end
	list1=list2;
end
imshow(maskIm);

----------


## mahsava

بسیار عالی. خیلی ممنون از راهنماییتون.
متوجه نشدم تصویری که تو خط اول می خونیدش کدومه؟ خودتون ساختینش؟ چرا مقادیر بزرگتر از 100؟ متوجه نشدم دقیقا چیکار کردین.

----------


## rahnema1

> بسیار عالی. خیلی ممنون از راهنماییتون.
> متوجه نشدم تصویری که تو خط اول می خونیدش کدومه؟ خودتون ساختینش؟ چرا مقادیر بزرگتر از 100؟ متوجه نشدم دقیقا چیکار کردین.


همون تصویر 2 که گذاشتید توسط browser هم به فرمت jpg و هم bmp ذخیره کرده و یه مشکل داشت که تصویر شامل 0و 255 نبود بلکه مقادیر دیگه هم داشت که یک آستانه گذاشتم مثل مقدار 100 که پایین تر ازاون سیاه و بالاتر از اون سفید بشه با دستور unique می تونید متوجه بشید که محتوای اون تصویر فقط دو تا عدد نیست

----------


## mahsava

من همین کد رو اجرا کردم ولی خطای خارج از آرایه داد. روند کار رو نگاه کردم داشت درست پیش می رفت ولی از یه جایی به بعد شروع کرد به پر کردن بیرون از دست. شما مشخصه Matlab رو خیلی تخصصی بلدین. خط های اول مشخص بود که عملیات موفولوژیکی انجام میده ولی من متوجه نشدم خط های بعدی چطور عمل می کنن. باید بیشتر اجراش کنم شاید بفهمم مشکلش چیه

----------


## rahnema1

> من همین کد رو اجرا کردم ولی خطای خارج از آرایه داد. روند کار رو نگاه کردم داشت درست پیش می رفت ولی از یه جایی به بعد شروع کرد به پر کردن بیرون از دست. شما مشخصه Matlab رو خیلی تخصصی بلدین. خط های اول مشخص بود که عملیات موفولوژیکی انجام میده ولی من متوجه نشدم خط های بعدی چطور عمل می کنن. باید بیشتر اجراش کنم شاید بفهمم مشکلش چیه


من برنامه را در متلب تست نکردم در نرم افزار octave که شبیه متلب هست اجرا کردم. شاید بعضی نتایج مورفولوژی نتایجش کمی متفاوت باشه در نتیجه محدوده دست کاملا بسته نشده یه کم با توابع مورفولوژی ور برید تا محدوده کاملا بسته بشه

----------


## mahsava

بازم ممنون. کمک خیلی بزرگی کردین. من یه مدت کلی وقت گذاشتم رو این قسمت از کد ولی به هیچ نتیجه ای نرسیدم!
باید بهش بیشتر ور برم.

----------


## rahnema1

اینجور شد
http://www.sharefile.ir/uploads/1411674740.png

----------


## mahsava

تصویر کلا 13 بایته؟!

----------


## rahnema1

تصویر که دو تا مقدار بیشتر نداره : 0 و 1 علاوه بر این تصویر فشرده هم میشه که حجمش اینقدر میشه

----------


## mahsava

آخه نه ویندوز بازش می کنه و نه متلب

----------


## rahnema1

با دو فرمت png و gif  http://www.sharefile.ir/uploads/1411629391.zip

----------


## mahsava

این درسته. مرسی

----------


## tiger1978

سلام 
من یک مقاله دارم که باید مورفولوژی را روی که تصویر اعمال کنه ان تصویر باید نویز و پس زمینه ان جدا بشه بعد روی تصویر اصلی کار اصلی مقاله انجام بشه قسمت اول را کدش را پیدا کردم اما نمی دونم چطور باید در برنامه اجراش کنم
30 lines (206 sloc)  6.71 KB
function ML = perform_mca(M, components, options)


% perform_mca - perform MCA decomposition
%
%   ML = perform_mca(M, components, options);
%   
%   ML(:,:,i) is the layer optained by sparse decomposition in 
%       dictionary Di described by components{i}.
%
%   components is a cell array of structure.
%   cpt = components{i) discribe the ith transform used. 
%
%   It must contains: 
%       cpt.callback: a function of the type 
%           y = function(x,dir,options);
%       for instance you can set cpt.callback=@callback_atrou
%
%   It can contains:
%       cpt.options: the options given to the callback
%       cpt.threshold_factor: an amplification factor for the thresholding.
%       cpt.tv_correction and cpt.tv_weight: the MCA will perform an
%           additional TV minimization (usefull for the cartoon layer).
%
%   options contains options for the MCA process such as:
%       options.niter: number of iterations.
%       options.saverep: directory to save iterations
%       options.Tmax and options.Tmin: maximum and minimum threshold
%           values. Set Tmin=0 if there is no noise in the problem
%           (decomposition will be exact i.e. M=sum(ML,3)
%           Set Tmax to approximately the maximum value of the
%           coefficients of all the transforms of M.
%
%   The references for the Morphological Components Analysis are
%   
%       J. Bobin, Y. Moudden, J.-L. Starck and M. Elad,  
%       "Morphological Diversity and Source Separation",  
%       IEEE Transaction on Signal Processing , Vol 13, 7, pp 409--412, 2006.
%
%       M. Elad, J.-L Starck, D. Donoho and P. Querre, 
%       "Simultaneous Cartoon and Texture Image Inpainting using Morphological Component Analysis (MCA)", 
%       Journal on Applied and Computational Harmonic Analysis ACHA , Vol. 19, pp. 340-358, November 2005.
%
%   	J.-L. Starck, M. Elad, and D.L. Donoho, 
%       "Image Decomposition Via the Combination of Sparse Representation and a Variational Approach", 
%       IEEE Transaction on Image Processing , 14, 10, 2005.
%
%       J.-L. Starck, M. Elad, and D.L. Donoho, 
%       "Redundant Multiscale Transforms and their Application for Morphological Component Analysis", 
%       Advances in Imaging and Electron Physics , 132, 2004. 
%
%   See also: perform_iterative_thresholding.
%
%   Copyright (c) 2007 Gabriel Peyre

----------


## tiger1978

options.null = 0;
if isfield(options, 'niter')
    niter = options.niter;
else
    niter = 20;
end
if isfield(options, 'Tmax')
    Tmax = options.Tmax;
else
    Tmax = 0.2*max(abs(M(:)));
end
if isfield(options, 'Tmin')
    Tmin = options.Tmin;
else
    Tmin = 0;
end
if isfield(options, 'threshold')
    threshold = options.threshold;
else
    threshold = 'hard';
end
if isfield(options, 'saverep')
    saverep = options.saverep;
else
    saverep = [];
end
if isfield(options, 'InpaintingMask')
    InpaintingMask = options.InpaintingMask;
else
    InpaintingMask = [];
end


s = length(components);




% init the residual
n = size(M,1);
ML = zeros(n,n,s);
if not(isempty(InpaintingMask))
    q = sum(InpaintingMask(:)==Inf);
    for k=1:s
        Mk = ML(:,:,k);
        Mk(InpaintingMask==Inf) = rand( q,1 ) * max( M(InpaintingMask~=Inf) );
        ML(:,:,k) = Mk;
    end
end




MLsave = [];
for i=1:niter
    progressbar(i,niter);
    % current threshold
    T0 = Tmax + (i-1)/(niter-1)*(Tmin-Tmax);
    for k=1:s

        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        % current component
        cpt = components{k};
        % callback function
        callback = cpt.callback;
        % options
        clear opt; opt.null = 0;
        if isfield(cpt, 'options')
            opt = cpt.options;
        end
        % threshold factor amplification
        threshold_factor = 1;
        if isfield(cpt, 'threshold_factor')
            threshold_factor = cpt.threshold_factor;
        end


        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        % compute residual
        T = T0 * threshold_factor;
        opt.T = T;
        % compute residual
        sel = 1:s; sel(k) = [];
        R = M - sum( ML(:,:,sel), 3);
        if not(isempty(InpaintingMask))
            % enforce known values only outside
            Mk = ML(:,:,k);
            R(InpaintingMask==Inf) = Mk(InpaintingMask==Inf);
        end


        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        % perform forward transform
        RW = feval(callback, R,+1,opt);
        % perform thresholding
        if strcmp(cpt.name, 'wav')
            % do not threshold the low frequency
        	RW1 = perform_thresholding({RW{1:end-1}},T, threshold);
            RW = {RW1{:}, RW{end}};
        else
        	RW = perform_thresholding(RW,T, threshold);
        end
        % perform backward transform
        ML(:,:,k) = feval(callback, RW,-1,opt);

        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        % TV additional sparsening
        if isfield(cpt, 'tv_correction') && cpt.tv_correction==1
            if isfield(options, 'tv_weight')
                tv_weight = options.tv_weight;
            else
                tv_weight = 2.5*max(abs(M(:)))/256;
            end
            ML(:,:,k) = perform_tv_correction(ML(:,:,k),tv_weight);
            end

        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        % save result
        if not(isempty(saverep))
            MLsave(:,:,:,i) = ML;
        end
    end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% save all the data
if not(isempty(saverep))
    % normalize the evolution
    vmax = max(max(max(MLsave,[],1),[],2),[],4); 
    vmax = repmat(vmax, [n n 1 niter]);
    vmin = min(min(min(MLsave,[],1),[],2),[],4); 
    vmin = repmat(vmin, [n n 1 niter]);
    MLsave = (MLsave-vmin) ./ (vmax-vmin);

    for k=1:s
        cpt = components{k};
        for i=1:niter
            if isfield(cpt, 'name')
                str = cpt.name;
            else
                str = ['layer' num2str(k)];
            end
            str = [str '-iter' num2string_fixeddigit(i,2)];
            warning off;
            imwrite( MLsave(:,:,k,i), [saverep str '.png'], 'png' );
            warning on;
        end
    end
end








%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%
function y = perform_hard_tresholding(x,t)


if iscell(x)
    for i=1:length(x)
        y{i} = perform_hard_tresholding(x{i},t);
    end
    return;
end


y = x .* (abs(x) > t);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%%%%%%%%%%%
function y = perform_soft_tresholding(x,t)


if iscell(x)
    for i=1:length(x)
        y{i} = perform_soft_tresholding(x{i},t);
    end
    return;
end


s = abs(x) - t;
s = (s + abs(s))/2;
y = sign(x).*s;

----------

