Pergunta

Eu estou tentando escrever a minha própria função para a ampliação de uma imagem de entrada usando o vizinho mais próximo algoritmo de interpolação.A parte ruim é que eu sou capaz de ver como ele funciona, mas não é possível localizar o algoritmo em si.Eu vou ser muito grato por qualquer ajuda.

Aqui está o que eu tentei para aumentar a escala da imagem de entrada por um fator 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

Aqui está a saída, depois de Marca's sugestão alt text

Foi útil?

Solução

Um tempo atrás, passei pelo código do imresize função no Caixa de ferramentas de processamento de imagem MATLAB Para criar uma versão simplificada apenas para a interpolação de imagens mais próxima. Veja como seria aplicado ao seu problema:

%# 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,:);

Outra opção seria usar o embutido interp2 função, embora você tenha mencionado não querer usar funções internas em um de seus comentários.

Editar: Explicação

Caso alguém esteja interessado, pensei em explicar como a solução acima funciona ...

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

Primeiro, para obter os tamanhos da nova linha e coluna, os tamanhos antigos da linha e da coluna são multiplicados pelo fator de escala. Este resultado é arredondado para o número inteiro mais próximo com floor. Se o fator de escala for menor que 1, você pode acabar com um caso estranho de um dos valores de tamanho sendo 0, e é por isso que a chamada para max Existe para substituir algo menos que 1 por 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));

Em seguida, um novo conjunto de índices é calculado para as linhas e colunas. Primeiro, é calculado um conjunto de índices para a imagem upsampled: 1:newSize(...). Cada imagem pixel é considerada como tendo uma dada largura, de modo que o pixel 1 se abre de 0 a 1, pixel 2 de 1 a 2, etc. A "coordenada" do pixel é assim tratada como o centro, e é por isso que 0.5 é subtraído dos índices. Essas coordenadas são então divididas pelo fator de escala para fornecer um conjunto de coordenadas de pixel-centro para a imagem original, que depois adicionou 0,5 a elas e são arredondadas para obter um conjunto de índices inteiros para a imagem original. A chamada para min garante que nenhum desses índices seja maior que o tamanho da imagem original oldSize(...).

outputImage = inputImage(rowIndex,colIndex,:);

Finalmente, a nova imagem upsamplada é criada simplesmente indexando na imagem original.

Outras dicas

Esta resposta é mais explicativa do que tentar ser concisa e eficiente. Eu penso gnoviceA solução é melhor nesse sentido. Caso você esteja tentando entender como funciona, continue lendo ...

Agora, o problema do seu código é que você está mapeando locais da imagem de entrada para a imagem de saída, e é por isso que você está recebendo o Spotty resultado. Considere um exemplo em que a imagem de entrada é toda branca e a saída é inicializada para preto, obtemos o seguinte:

screenshot

O que você deve fazer é o oposto (da saída para a entrada). Para ilustrar, considere a seguinte notação:

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]

A ideia é que para cada local (i,j) Na imagem de saída, queremos mapeá -la para o local "mais próximo" nas coordenadas da imagem de entrada. Como este é um mapeamento simples, usamos a fórmula que mapeia um determinado x para y (dado todos os outros parâmetros):

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

no nosso caso, x é o i/j coordenar e y é o ii/jj coordenada. Portanto, substituir para cada um nos dá:

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

Juntando peças, obtemos o seguinte código:

% 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)

O Matlab já fez isso para você. Usar imresize:

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

ou se você quiser escalar os dois x & y igualmente,

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

Você só precisa de uma mais generalizada fórmula para o cálculo xloc e yloc.

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

Isso pressupõe que as variáveis têm alcance suficiente para a multiplicação dos resultados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top