Estou tentando implementar vários algoritmos de binarização na imagem mostrada:
Aqui está o código:
clc;
clear;
x=imread('n2.jpg'); %load original image
Agora redimensionamos as imagens para que o trabalho computacional se torne mais fácil posteriormente para nós.
size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');
z=rgb2hsv(x); %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);
% agora encontramos a média e o desvio padrão necessários para os algoritmos niblack e% sauvola
m = mean(v(:))
s=std(v(:))
k=-.4;
value=m+ k*s;
temp=v;
% de implementação do algoritmo de limiar niblack:
for p=1:1:500
for q=1:1:800
pixel=temp(p,q);
if(pixel>value)
temp(p,q)=1;
else
temp(p,q)=0;
end
end
end
figure;
imshow(temp);
title('result by niblack');
k=kittlerMet(g);
figure;
imshow(k);
title('result by kittlerMet');
% de implementação do algoritmo de limiar de sauvola:
val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
pixel=t2(p,q);
if(pixel>value)
t2(p,q)=1;
else
t2(p,q)=0;
end
end
fim
figure;
imshow(t2);
title('result by sauvola');
Os resultados obtidos são os seguintes:
Como você pode ver, as imagens resultantes são degradadas nos pontos mais escuros. Alguém poderia sugerir como otimizar meu resultado?
image-processing
matlab
marca
fonte
fonte
Respostas:
Sua imagem não possui brilho uniforme; portanto, você não deve trabalhar com um limite uniforme. Você precisa de um limite adaptável. Isso pode ser implementado pré-processando a imagem para tornar o brilho mais uniforme em toda a imagem (código escrito no Mathematica, você precisará implementar a versão do Matlab por conta própria):
Uma maneira simples de uniformizar o brilho é remover o texto real da imagem usando um filtro de fechamento:
O tamanho do filtro deve ser escolhido maior que a largura do traço da fonte e menor que o tamanho das manchas que você está tentando remover.
Edição: fui convidado nos comentários para explicar o que uma operação de fechamento faz. É uma dilatação morfológica seguida por uma erosão morfológica . A dilatação move essencialmente o elemento estruturador em todas as posições da imagem e seleciona o pixel mais brilhante sob a máscara, assim:
A operação de erosão faz o oposto (ele seleciona o pixel mais escuro embaixo do elemento estruturador); portanto, se você o aplicar na imagem dilatada:
Portanto, a operação de fechamento remove pequenos objetos escuros com apenas pequenas alterações em objetos escuros maiores e objetos brilhantes.
Aqui está um exemplo com diferentes tamanhos de elementos de estruturação:
À medida que o tamanho do elemento estruturador aumenta, mais e mais caracteres são removidos. No raio = 5, todos os caracteres são removidos. Se o raio aumentar ainda mais, as manchas menores também serão removidas:
Agora você apenas divide a imagem original por esta "imagem em branco" para obter uma imagem de brilho (quase) uniforme:
Agora, esta imagem pode ser binarizada com um limite constante:
fonte
Clip[ImageData[white],{eps,Infinity}]
onde eps é um número pequeno, para estar seguro.A resposta de Nikie parece melhor e também parece estar funcionando e produzindo resultados. Portanto, é um vencedor claro.
No entanto, apenas para a documentação, adicionando mais uma referência, que poderia ser muito rápida.
Esta técnica é chamada de limiar adaptativo, que não requer a aprender o fundo explicitamente.
Essencialmente, em vez de encontrar o limite global mais adequado - podemos particionar a imagem em uma janela local (por exemplo, 7x7 ou apropriada) e encontrar limites que mudam conforme a janela atravessa.
A referência abaixo detalha o método exato. http://homepages.inf.ed.ac.uk/rbf/HIPR2/adpthrsh.htm
Este método seria relativamente mais rápido computacionalmente.
fonte
Outra maneira de usar um filtro passa-banda (no MATLAB). Brincar com a diferença de parâmetros gaussianos pode dar melhores resultados. O processo é basicamente filtrar a imagem da banda para remover os blobs de fundo de baixa frequência, normalizar para [0,1] necessário para o comando 'greythresh', imagem de limite.
Carregar imagem e converter em escala de cinza dupla:
Filtre usando a diferença do kernel Gaussiano e normalize:
Calcule o limite e efetue 010101:
fonte
Este é um bom código Matlab para limiar adaptável: http://www.mathworks.com/matlabcentral/fileexchange/8647-local-adaptive-thresholding
fonte
Vou tentar esta codificação. Mas eu não tenho uma resposta correta ...
fonte