Dithering — Parte I — Halftone via Pontilhado Ordenado
Halftone (meio-tom) é uma técnica de processamento de imagens que emprega padrões de pontos pretos ou brancos para reduzir o número de níveis de cinza de uma representação. Devido ao fato do sistema visual humano atenuar a distinção entre os pontos com tons diferentes, os padrões de pontos pretos e brancos produzem um efeito visual como se a imagem fosse composta por mais tons de cinza.
Esta técnica é muito utilizada em aplicações de impressão em jornais e faxes, onde apenas os níveis brancos e pretos são necessários. Há diferentes abordagens para produção de tais padrões, tais como o pontilhado ordenado (ordered dithering) e pontilhado com difusão de erro (dithered with error difusion).
Neste exemplo, implementamos um algoritmo de halftoning típico para impressão, baseado em padrões de pontos com pontilhado ordenado. A figura abaixo mostra os padrões que podem ser utilizados para aproximar dez níveis de cinza:
Cada conjunto de níveis de cinza é representado por um padrão de pontos brancos ou pretos. Uma área de pixels cheia de pontos pretos é uma aproximação de um nível de cinza preto (ou 0). De forma análoga, uma área de pontos totalmente brancos será uma aproximação do branco em uma escala de nível de cinza (ou 9). Os demais padrões intermediários entre serão re-escalados para o intervalo , conforme ilustrado na imagem abaixo.
É possível notar que utilizamos nove limiares (threshold) para a sub-codificação: o intervalo é truncado para , é truncado para , para , e assim por diante. Assim, cada pixel na imagem de entrada irá corresponder a um padrão de pixels na imagem gerada. Desta forma, a resolução espacial será reduzida a da resolução espacial original. Isto é, antes da substituição de cada pixel pela máscara devemos reduzir em as dimensões da imagem para que o resultado tenha o mesmo tamanho da original.
Todo o processo descrito é implementado na seguinte função;
def halftone(im, predown = True, histeq = False):
"""
Convert a image from grayscale image to binary image using halftone
Parameters
----------
* im: numpy matrix (image)
* predown: boolean (default True)
divide original image by 3 before halftoning
* histeq: boolean (default False)
perform a histogram equalization before halftone
Written by Pedro Garcia Freitas [sawp@sawp.com.br]
Copyright 2010 by Pedro Garcia Freitas
see: http://www.sawp.com.br
"""
def halft(im):
# provides the threshold levels for binarization
level9 = array([[1,1,1],[1,1,1],[1,1,1]])
level8 = array([[1,0,1],[1,1,1],[1,1,1]])
level7 = array([[1,0,1],[1,1,1],[1,1,0]])
level6 = array([[0,0,1],[1,1,1],[1,1,0]])
level5 = array([[0,0,1],[1,1,1],[1,0,1]])
level4 = array([[0,0,0],[1,1,1],[0,1,0]])
level3 = array([[0,0,0],[1,1,0],[0,1,0]])
level2 = array([[0,0,0],[1,1,0],[0,0,0]])
level1 = array([[0,0,0],[0,1,0],[0,0,0]])
level0 = array([[0,0,0],[0,0,0],[0,0,0]])
# create and rescale new image to fit levels
(h,l) = im.shape
masked = (10.0 / 255.0) * im
masked = ceil(masked)
rIm = zeros((3 * h, 3 * l))
# generate the halftoned image_path
k = 0
r = 0
for i in xrange(h):
for j in xrange(l):
mask = masked[i, j]
if mask == 1:
selected = level0
elif mask == 2:
selected = level1
elif mask == 3:
selected = level2
elif mask == 4:
selected = level3
elif mask == 5:
selected = level4
elif mask == 6:
selected = level5
elif mask == 7:
selected = level6
elif mask == 8:
selected = level7
elif mask == 9:
selected = level8
else:
selected = level9
xs = i + k
xf = i + k + 3
ys = j + r
yf = j + r + 3
rIm[xs:xf, ys:yf] = selected[:,:]
r = r + 2
r = 0
k = k + 2
return rIm
# try generate halftoned image with original size
if predown == True:
im = imresize(im, 1.0 / 3.0)
if histeq == False:
retIm = halft(im)
else:
equalized = normalize(im)
equalized = halft(equalized)
retIm = equalized
retIm = halft(im)
retIm = ceil((equalized + retIm) * 0.5)
return retIm
Os resultados do retorno desta função podem ser vistos abaixo:
Original (parâmetro) |
Halftoned (retorno) |
|
|
|
|
|
|
</center>