O código abaixo descreve a implementação comentada de cinco funções. A primeira, "pixels", será usada para facilitar a iteração pelos pixels das imagens.
A função "esteganografar" recebe como argumentos a imagem original, o nome com que ela será salva após receber a informação oculta e uma string contendo os bits de informação que serão embutidos.
A função "recuperar" recebe como argumento uma imagem que contenha alguma informação embutida e retorna uma string com os bits da informação 
extraída.
As funções "gera_bin" e "recupera_str" convertem, respectivamente, uma string de texto em sua respectiva string binária e vice-versa. Elas foram incluídas para facilitar a inserção/recuperação de mensagens de texto nas imagens.
No momento de se recuperar a informação que está embutida na imagem, é preciso saber de antemão quantos bits ela possui. Para isso, a constante PIXELS_RESERVADOS  determina quantos dos primeiros pixels da imagem serão utilizados para armazenar este valor.
A imagem resultante, também chamada de estego-objeto ou estego-imagem, será salva no formato PNG, já que outros formatos como o JPEG utilizam compressão com 
perdas, o que provocaria a alteração de pixels para reduzir o tamanho em disco da imagem, acarretando perda de informações.
# coding: utf-8
import re
import Image
# Define quantos pixels serão utilizados para informar o tamanho da mensagem oculta
PIXELS_RESERVADOS = 10
def pixels(tam):
    
'''Facilita a iteração pelos pixels da imagem'''
    for y in xrange(tam[1]):
        for x in xrange(tam[0]):
            yield (x, y)
def esteganografar(img_orig, img_esteg, str_bin):
    
# Abre a imagem e obtém seus atributos
    img = Image.open(img_orig)
    largura, altura = img.size
    
# Verifica se o formato da imagem é compatível e se ela possui capacidade
    if img.mode[:3] != 'RGB' or largura * altura * 3  < len(str_bin) + PIXELS_RESERVADOS * 3:
        raise IndexError('O tamanho da mensagem excede a capacidade da imagem ou não há suporte para a mesma')
    
# Os primeiros pixels definem o tamanho da informação a ser ocultada
    bits_tam = bin(len(str_bin))[2:].zfill(PIXELS_RESERVADOS * 3) 
    str_bin = bits_tam + str_bin
    
    
# Completa a informação tornando-a múltipla de 3 e iterável;
    str_bin = enumerate(str_bin + '0' * (3 - len(str_bin) % 3))
    
# Carrega os pixels da imagem para a memória;
    pix = img.load()
    
    
# Percorre cada pixel da imagem
    for x, y in pixels(img.size):
        try:
            
# Altera o valor dos bits menos significativos
            rgb = map(lambda cor, bit: cor - (cor % 2) + int(bit), pix[x, y][:3], [str_bin.next()[1] for _ in xrange(3)])
            pix[x, y] = tuple(rgb)
        except StopIteration:
            
# Quando não houver mais bits para se esteganografar, str_bin disparará uma
            # exceção do tipo StopIteration, e a nova imagem estará pronta para ser salva;
            img.save(img_esteg, 'PNG', quality=100)
            return
def recuperar(img_esteg):
    
# Abre a imagem, obtém seus atributos e carrega os pixels para a memória
    img = Image.open(img_esteg)
    tam = img.size
    pix = img.load()
    
# Obtém os primeiros pixels, que definem o tamanho da informação embutida;
    info_tam = ''
    for p in pixels(tam):
        info_tam += ''.join('1' if cor % 2 else '0' for cor in pix[p][:3])
        if len(info_tam) >= PIXELS_RESERVADOS * 3:
            info_tam = int(info_tam, 2)
            break  
    
    
# Extrai a informação binária da imagem
    info_bin = ''
    for p in pixels(tam):
        info_bin += ''.join('1' if cor % 2 else '0' for cor in pix[p][:3])
    
    return info_bin[PIXELS_RESERVADOS * 3:info_tam + PIXELS_RESERVADOS * 3]
 
def gera_bin(msg):
    
'''Para cada caractere, obtém o valor binário de seu código ASCII'''
    return ''.join(bin(ord(caractere))[2:].zfill(8) for caractere in msg)
def recupera_str(str_bin):
    
'''Converte cada grupo de 8 bits no seu respectivo caractere'''
    return ''.join(chr(int(bin, 2)) for bin in re.findall(r'.{8}', str_bin)) 
if __name__ == '__main__':    
    
# Oculta a mensagem "Viva o Linux" na imagem "img.jpg" e
    # salva o resultado como "img_msg.png";
    msg_bin = gera_bin('Viva o Linux')
    esteganografar('img.jpg', 'img_msg.png', msg_bin)
    
    
# Recupera a mensagem
    msg_bin = recuperar('img_msg.png')
    print recupera_str(msg_bin)
 
A Figura 2 mostra a comparação entre uma imagem sem informações ocultas e sua versão após ter os bits menos significativos de todos os seus pixels esteganografados com os valores 0 e 1, alternadamente.
Até mesmo nas partes de cor homogênea como o fundo branco é impossível perceber qualquer diferença que indique a existência de uma mensagem embutida, comprovando a eficácia da técnica.

Figura 2