How to calculate the Data-Term for Patch Based Inpainting
이전 댓글 표시
Hello everyone;
I've been working on inpainting algorithms (without AI or DNN) for a few months now. The aim is to later modify these inpainting algorithms and test them against each other. But with patch-based inpainting I now have the technical problem that I simply don't understand how to determine the data term.
I understand that the data term (Dp) contains the structure values and is therefore of crucial importance for inpainting, as the structures that run into the inpainting region are treated with priority. For this purpose, gradient values or isophote values should be determined directly at the edge pixel and a priority should be determined from these.
I fully understood the purpose of the Dp and how it should be used afterwards. Unfortunately, I don't understand how I can actually calculate the Dp and this is what I'm hoping for concrete help with.
This is my code so far. It may works if the Data Term is not very important fpr the inpainting task as the data term is just constant zero so far to test if the surrounding function is working. The paper is used for creating this is found in the first line. As I comment my code in German only I added translations in '()' behind them.
%Basisquelle: https://www.degruyter.com/document/doi/10.1515/jisys-2013-0031/html?lang=de
%To Parameters:
%pic the original (uint8 coloured-RGB) Picture where the inpainting Region can be found.
% The Inpainting Region has only full black RGB-Pixels. I am testing with small Picture
% of size 100x100 Pixels now, but I want to test with 1k and 2k Pictures later.
%mask Logical 2d Array with same size as pic. 1 is part of Inpainting region
%patchsize Opt. Param - Odd Int that says how big a patch is
%searchdist Opt. Param - Used in Step 3 for search areal for possible best patch
%alpha The alpha used in the Paper for P-Calculating
%beta The beta used in the Paper for P-Calculating
%gamma The [small] omega used in the Paper for RC-Calculating
%[klein] omega wurde zu gamma umgeschrieben damit es weniger
%Verwechslungsgefahr mit [groß]Omega gibt.
%(the small omega was changed to gamma to make it easier to read and differ from big Omega in this code)
function [out] = patchBasedInpainting(pic,mask,patchsize,searchdist,alpha,beta,gamma)
if ~exist("alpha","var")
alpha = 0.2;
end
if ~exist("beta","var")
beta = 0.8;
end
if ~exist("gamma","var")
gamma = 0.7;
end
if gamma > 1 || 0 > gamma
error("Gamma must be between zero and one!");
end
if (alpha+beta) > 1 || 0 > (alpha+beta)
error("Sum of alpha and beta must be between zero and one!");
end
if ~exist("patchsize","var")
patchsize = 9;
else
if isEven(patchsize) || (patchsize < 3)
error("The Patchsize is not allowed to be odd!");
end
end
ps = floor(patchsize/2);
if ~exist("searchdist","var")
searchdist = 33;
end
searchdist = searchdist + ps;
%Searchdist beschreibt im welchem Umfeld um den höchst priorisierten
%Pixel herum nach dem besten Patch gesucht werden soll. Dabei gibt
%search dist bei der eingabe einen Wert vor, der dann noch anschließend
%um ps erweitert wird.
%(Searchdist tells in what area around a highst priority Pixel should
%searched for the best patch. searchdist is give by caller function and
%extended by ps)
[y,x,N] = size(pic);
%Phi fertiges Bildgebiet
%(Phi is finished Picture Area)
%Omega unfertiges Bildgebiet
%(Omega is unfinished Picture Area - aka Inpainting Region)
%deltaOmega Grenze zwischen Phi und Omega in Omega
%(deltaOmega is the border between Phi and Omega and is part of Omega)
Phi = pic .* uint8(~mask); %1 in Maske heißt Teil der Inpainting region (A One in the mask meas be part of inpaintign region)
Omega = mask;
Cmap = double(~Omega); % Map für das Vertrauen eiens Pixels (1 ist max) (Map for confidence for each Pixel - One is max)
iterationcounter = 0;
barmax = sum(Omega,"all");
bartext = "Patchbased Inpainting in Iteration: ";
bar = waitbar(0,append(bartext,string(0)));
while 1 %Abbruch im Schritt 1 enthalten (Abort in Step 1)
%Schritt 1: Bestimme deltaOmega (Step 1 - find deltaOmega)
deltaOmega = zeros(sum(uint64(Omega),'all')*2,2);
at = 1;
if(isempty(deltaOmega)) %Falls die Restmaske leer ist, muss man auch nicht mehr zählen.
break; %(Break id there are no Pixel in Omega left)
end
for i = 1 + ps : y - ps
for j = 1 + ps : x - ps
if Omega(i,j) == 1
if sum(Omega(i-1:i+1,j-1:j+1),"all") < 9 %Überprüfe ob in der 9 Nachbarschaft des Pixels die Summe <9 ist
deltaOmega(at,:) = [i,j]; %(Check if in 9 Neigborhood sum is less to 9)
at = at + 1;
end
end
end
end
deltaOmega = deltaOmega(1:at-1,:);
to = size(deltaOmega,1);
%Schritt 2: Bestimmte die höchste Priorität
%(Step 2: Find highest Priority Pixel)
maxP = -inf;
pixel_x = 0;
pixel_y = 0;
for at = 1 : to
%Bestimme C bzw. RC
%(Calculate C)
p = deltaOmega(at,:);
py = p(1,1);
px = p(1,2);
%[py,px] = deltaOmega(at,:);
%patch = ~Omega(py-ps:py+ps,px-ps:px+ps);
patch = Cmap(py-ps:py+ps,px-ps:px+ps);
Cp = sum(patch,"all") / patchsize^2;
RCp = (1-gamma) * Cp + gamma;
%Bestimme D
%(Calculate D)
%(This is where I need to add Code. Somehow I need to extract a
%Value between 0 and 1 by using gradients.
Dp = 0;
%Bestimme P
%(Calculate P)
Pp = alpha * RCp + beta * Dp;
if Pp > maxP
maxP = Pp;
cForMaxP = Cp;
pixel_y = py;
pixel_x = px;
end
end
if N == 3
Phi_p = Phi(pixel_y-ps:pixel_y+ps,pixel_x-ps:pixel_x+ps,:);
else
Phi_p = Phi(pixel_y-ps:pixel_y+ps,pixel_x-ps:pixel_x+ps);
end
Omega_p = Omega(pixel_y-ps:pixel_y+ps,pixel_x-ps:pixel_x+ps);
%Schritt 3: Bestimme den besten Patch aus Phi zum Problem
%(Step 3: Find the best Patch inside Phi for the Pixel)
best_value = inf;
best_y = 0;
best_x = 0;
for i = pixel_y - searchdist : pixel_y + searchdist
for j = pixel_x - searchdist : pixel_x + searchdist
if (j+ps > x || i-ps < 1 ||j-ps < 1 || i+ps > y)
continue;%Die Maske darf din Bild Rand nicht überschreiten!
%(Mask is not allowed to exit Image Border!)
end
Q_mask = Omega(i-ps:i+ps,j-ps:j+ps); % Patch muss vollständig in Phi liegen!
if mean2(Q_mask) == 0 % (Patch must be 100% inside Phi!)
if N == 3
Phi_q = Phi(i-ps:i+ps,j-ps:j+ps,:);
else
Phi_q = Phi(i-ps:i+ps,i-ps:i+ps);
end
%err=SSE(Phi_p,Phi_q,Omega_p); %Der Einfluss von Omega ist viel zu groß, als das man hier die std. Funktion nutzen könnte.
%(Influence of Omega is to big to use the st. MATLAB Function)
err = immse(Phi_q,Phi_p);
if err < best_value
best_y = i;
best_x = j;
best_value = err;
bestPhiQ = Phi_q; % Nur für Debugzwecke
%(Just for Debugging)
end
end
end
end
%Schritt 4 Fülle Omega mit den Pixeln Phi_q
%(Step 4: Fill Omega with Pixels taken from Phi_q)
for i = 0 : ps*2
for j = 0 : ps*2
if Omega(pixel_y-ps+i,pixel_x-ps+j) == 1 %Aktualisiere nur Pixel in Omega
%(Only update Pixel
%inside Omega)
Omega(pixel_y-ps+i,pixel_x-ps+j) = 0; %Nun Teil von Phi
%(Now a part of
%Phi)
if N == 3
Phi(pixel_y-ps+i,pixel_x-ps+j,:) = Phi(best_y-ps+i,best_x-ps+j,:);
else
Phi(pixel_y-ps+i,pixel_x-ps+j) = Phi(best_y-ps+i,best_x-ps+j);
end
Cmap(pixel_y-ps+i,pixel_x-ps+j) = cForMaxP; %Setzte Vertrauenswerte
%(update confidence)
end
end
end
%Schleifenende
%Backpart of Looping
iterationcounter = iterationcounter + 1;
remainingPixels = sum(Omega,"all");
%disp(string(remainingPixels));
waitbar((barmax-remainingPixels)/barmax,bar,append(bartext,string(iterationcounter)));
end
close(bar);
out = Phi;
end
%Optimierungs Ideen:
%Mittelwertsfilter Faltung auf der Maske um C zu bestimmen
%Um Omega zu finden sich den Rahmen merken - dies sollte realtiv viele
%Nullvergleiche vermeiden.
%(Idea for efficieny improfing:
%Mean Convolution for calculating C Values
%Save a Inner bounding area for Omega - so upper parts are not checked anymore)
%Finding ways to avoid zero checkings
채택된 답변
추가 답변 (0개)
카테고리
도움말 센터 및 File Exchange에서 Blocked Images에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!