web-dev-qa-db-fra.com

Algorithme d'interpolation de voisin le plus proche à Matlab

J'essaie d'écrire ma propre fonction pour augmenter une image d'entrée en utilisant l'algorithme d'interpolation de voisin le plus proche. La mauvaise partie est que je suis capable de voir comment cela fonctionne mais ne peut pas trouver l'algorithme lui-même. Je serai reconnaissant de toute aide.

Voici ce que j'ai essayé d'avoir échoué l'image d'entrée d'un facteur de 2:

function output = nearest(input)
[x,y]=size(input);
output = repmat(uint8(0),x*2,y*2);
[newwidth,newheight]=size(output);
for i=1:y
    for j=1:x
        xloc = round ((j * (newwidth+1)) / (x+1));
        yloc = round ((i * (newheight+1)) / (y+1));
        output(xloc,yloc) = input(j,i);
    end
end

Voici la sortie après - Mark Suggestion alt text

20
Hellnar

Un moment de retour, j'ai traversé le code du imresize Fonction dans la boîte à outils Tool de traitement de l'image MATLAB Pour créer une version simplifiée pour un voisin le plus proche interpolation d'images. Voici comment cela serait appliqué à votre problème:

%# Initializations:

scale = [2 2];              %# The resolution scale factors: [rows columns]
oldSize = size(inputImage);                   %# Get the size of your image
newSize = max(floor(scale.*oldSize(1:2)),1);  %# Compute the new image size

%# Compute an upsampled set of indices:

rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1));
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2));

%# Index old image to get new image:

outputImage = inputImage(rowIndex,colIndex,:);

Une autre option serait d'utiliser le fichier intégré interp2 Fonction, bien que vous avez mentionné ne voulant pas utiliser de fonctions intégrées dans l'un de vos commentaires.

Modifier: Explication

Au cas où n'importe qui est intéressé, je pensais que j'expliquerais comment la solution ci-dessus fonctionne ...

newSize = max(floor(scale.*oldSize(1:2)),1);

Premièrement, pour obtenir la nouvelle ligne et la nouvelle taille des colonnes Les anciens rangées et les tailles de colonne sont multipliées par le facteur d'échelle. Ce résultat est arrondi à l'entier le plus proche avec floor . Si le facteur d'échelle est inférieur à 1, vous pouvez vous retrouver avec un cas étrange de l'une des valeurs de taille 0, c'est pourquoi l'appel à max est là pour remplacer quelque chose de moins de 1 avec 1.

rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1));
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2));

Ensuite, un nouvel ensemble d'indices est calculé pour les lignes et les colonnes. Premièrement, un ensemble d'indices pour l'image upsamplé est calculé: 1:newSize(...). Chaque pixel d'image est considéré comme ayant une largeur donnée, de sorte que le pixel 1 s'étend de 0 à 1, pixel 2 couvre de 1 à 2, etc. La "coordonnée" du pixel est ainsi traitée comme le centre, c'est pourquoi 0.5 est soustrait des indices. Ces coordonnées sont ensuite divisées par le facteur d'échelle pour donner un ensemble de coordonnées de centre de pixels pour l'image d'origine, qui leur ont ensuite 0,5 ajouté et sont arrondies pour obtenir un ensemble d'indices entier pour l'image d'origine. L'appel à min Assure qu'aucun de ces indices n'est plus grand que la taille d'image d'origine oldSize(...).

outputImage = inputImage(rowIndex,colIndex,:);

Enfin, la nouvelle image upamplée est créée en indexant simplement dans l'image d'origine.

19
gnovice

Cette réponse est plus explicative que d'essayer d'être concise et efficace. Je pense - gnovice La solution est la meilleure à cet égard. Si vous essayez de comprendre comment cela fonctionne, continuez à lire ...

Maintenant, le problème avec votre code est que vous mettez des emplacements de mappage de l'image d'entrée à l'image de sortie, c'est pourquoi vous obtenez le Spotty . Considérons un exemple où l'image d'entrée est tout blanche et sortie initialisée en noir, nous obtenons les éléments suivants:

screenshot

Ce que vous devriez faire est le contraire (de la sortie à l'entrée). Pour illustrer, considérez la notation suivante:

1           c         1                 scaleC*c
+-----------+ 1       +----------------------+ 1
|    |      |         |        |             |
|----o      |   <===  |        |             |
|  (ii,jj)  |         |--------o             |
+-----------+ r       |      (i,j)           |
  inputImage          |                      |
                      |                      |
                      +----------------------+ scaleR*r
                            ouputImage

Note: I am using matrix notation (row/col), so:
  i ranges on [1,scaleR*r] , and j on [1,scaleC*c]
  and ii on [1,r], jj on [1,c]

L'idée est que pour chaque emplacement (i,j) Dans l'image de sortie, nous souhaitons mapper sur l'emplacement "le plus proche" dans les coordonnées d'image d'entrée. Comme il s'agit d'une simple mappage, nous utilisons la formule qui mappe une donnée x à y (compte tenu de tous les autres paramètres):

 x-minX      y-minY
--------- = ---------
maxX-minX   maxY-minY

dans notre cas, x est la coordonnée i/j/y est le ii/jj coordonnée. Par conséquent, la substitution pour chacun nous donne:

jj = (j-1)*(c-1)/(scaleC*c-1) + 1
ii = (i-1)*(r-1)/(scaleR*r-1) + 1

Mettre des morceaux ensemble, nous obtenons le code suivant:

% read a sample image
inputI = imread('coins.png');
[r,c] = size(inputI);
scale = [2 2];        % you could scale each dimension differently

outputI = zeros(scale(1)*r,scale(2)*c, class(inputI));

for i=1:scale(1)*r
    for j=1:scale(2)*c
        % map from output image location to input image location
        ii = round( (i-1)*(r-1)/(scale(1)*r-1)+1 );
        jj = round( (j-1)*(c-1)/(scale(2)*c-1)+1 );

        % assign value
        outputI(i,j) = inputI(ii,jj);
    end
end

figure(1), imshow(inputI)
figure(2), imshow(outputI)
20
Amro

Matlab l'a déjà fait pour vous. UTILISATION IMRESIZE :

output = imresize(input,size(input)*2,'nearest');

ou si vous voulez mettre à l'échelle X & Y de même,

output = imresize(input,2,'nearest');
2
Jacob

Vous avez juste besoin d'une formule plus généralisée pour calculer XLOC et YLOC.

xloc = (j * (newwidth+1)) / (x+1);
yloc = (i * (newheight+1)) / (y+1);

Cela suppose que vos variables ont suffisamment de gamme pour les résultats de la multiplication.

0
Mark Ransom