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
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.
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:
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)
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');
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.