Dithering — Parte IV — Dithering com Difusão de Erro de Jarvis

Uma forma de obter uma imagem binária é usar a distribuição de erro de Jarvis. Semelhante à abordagem de Floyd-Steinberg, a difusão do erro é produzida através da seguinte máscara:


\(
\begin{array}{| c | c | c | c| c |}
\hline
0 & 0 & 0 & 0 & 0 \\ \hline
0 & 0 & 0 & 0 & 0 \\ \hline
0 & 0 & f(x,y) & 7/48 & 5/48 \\ \hline
3/48 & 5/48 & 7/48 & 5/48 & 3/48 \\ \hline
1/48 & 3/48 & 5/48 & 5/48 & 1/48 \\ \hline
\end{array}
\)

O algoritmo de halftoning que utiliza a difusão de erro de Jarvis, Judice e Ninke é efetuado pela seguinte função:

def jarvis(originalImage):
    ''' Original Jarvis Dithering Algorithm.
 
    dithered = jarvis(originalImage)
 
    Parameters
    ----------
    originalImage: numpy ndarray, original image
 
    Return
    ----------
    dithered: numpy ndarray, dithered image
 
    References
    ----------
    J.Jarvis, C.Judice, and W.Ninke, ``A survey of techniques for the
    display of continuous tone pictures on bilevel displays,''
    em Comp. Graph and Image  Proc., vol.~5, pp.~13--40, 1976.
 
    Written by Pedro Garcia Freitas [sawp@sawp.com.br]
    Copyright 2010 by Pedro Garcia Freitas
 
    see: http://www.sawp.com.br
    '''
    (M, N) = originalImage.shape
    threshold = 127.5
    tmp = originalImage.copy()
    error = 0
 
    super = 127.5 * ones((M, 2))
    infer = 127.5 * ones((2, N + 4))
    tmp = concatenate((super, tmp, super), axis=1)
    tmp = concatenate((tmp, infer))
    dithered = tmp.copy()
 
    for row in xrange(M):
        for col in xrange(2, N + 2):
            dithered[row, col] = 255.0 * int(tmp[row, col] >= threshold)
            error = - dithered[row, col] + tmp[row, col]
 
            tmp[row, col + 2] = 0.10417 * error + tmp[row, col + 2]
            tmp[row, col + 1] = 0.14583 * error + tmp[row, col + 1]
 
            tmp[row + 1, col + 2] = 0.0625 * error + tmp[row + 1, col + 2]
            tmp[row + 1, col + 1] = 0.10417 * error + tmp[row + 1, col + 1]
            tmp[row + 1, col + 0] = 0.14583 * error + tmp[row + 1, col + 0]
            tmp[row + 1, col - 1] = 0.10417 * error + tmp[row + 1, col - 1]
            tmp[row + 1, col - 2] = 0.0625 * error + tmp[row + 1, col - 2]
 
            tmp[row + 2, col + 2] = 0.02083 * error + tmp[row + 2, col + 2]
            tmp[row + 2, col + 1] = 0.0625 * error + tmp[row + 2, col + 1]
            tmp[row + 2, col + 0] = 0.10417 * error + tmp[row + 2, col + 0]
            tmp[row + 2, col - 1] = 0.0625 * error + tmp[row + 2, col - 1]
            tmp[row + 2, col - 2] = 0.02083 * error + tmp[row + 2, col - 2]
    return dithered[0:M, 2:N + 2]

A partir desta implementação, obtemos os seguintes resultados:

Original (entrada)
Halftoned (saída)