[python-brasil] Separação de cores - PIL

338 views
Skip to first unread message

Daniel

unread,
May 26, 2007, 11:07:00 AM5/26/07
to python...@yahoogrupos.com.br
Estou usando o código abaixo para detectar cores predominantemente
vermelhas em uma imagem, e preencher as demais cores com branco. A
questão é que está um pouco lento. Tenho uma webcam que captura a 15
fps, e o script não consegue processar instantaneamente. Qualquer
sugestão é bem vinda, desde já agradeço.

<code>

VERMELHO = (255,0,0,255)
BRANCO = (255,255,255,255)
import Image
from sys import argv
def __main__():
if len(argv)<2:
print 'Use %s file_name' % argv[0]
else:
proc_img(argv[1])
def proc_img(fname):
img = Image.open(fname)
if img.getbands() <> ('R','G','B','A'):
img = img.convert('RGBA')
for i in range(0,img.size[0]): #img.size[0] <- largura
for j in range(0,img.size[1]): #img.size[1] <- altura
pix = img.getpixel((i,j))
#(pix[0]=Red, pix[1]=Green, pix[2]=Blue, pix[3]=Alpha)
#detecta cores predominantemente vermelhas
if pix[0]>200 and pix[1]<30 and pix[2]<30:
img.putpixel((i,j), VERMELHO)
else:
img.putpixel((i,j), BRANCO)
new_fname = fname.replace('.','_modificada.',1)
nova=img.save(new_fname)

__main__()

</code>

Usei a seguinte figura como teste:
http://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Traffic_lights_3_states.png/200px-Traffic_lights_3_states.png
--
Daniel - NO Java * YES C/Python


,-----------------------------------------------------------.
| Antes de enviar um e-mail para o grupo leia: |
| http://www.pythonbrasil.com.br/moin.cgi/AntesDePerguntar |
| E se você é usuário do BOL lembre-se de cadastrar o |
| e-mail do grupo na lista branca do seu sistema anti-spam. |
`-----------------------------------------------------------´
Links do Yahoo! Grupos

<*> Para visitar o site do seu grupo na web, acesse:
http://br.groups.yahoo.com/group/python-brasil/

<*> Para sair deste grupo, envie um e-mail para:
python-brasi...@yahoogrupos.com.br

<*> O uso que você faz do Yahoo! Grupos está sujeito aos:
http://br.yahoo.com/info/utos.html


Rafael "SDM" Sierra

unread,
May 26, 2007, 11:14:26 AM5/26/07
to python...@yahoogrupos.com.br
On 5/26/07, Daniel <dani...@gmail.com> wrote:
>
> Estou usando o código abaixo para detectar cores predominantemente
> vermelhas em uma imagem, e preencher as demais cores com branco. A
> questão é que está um pouco lento. Tenho uma webcam que captura a 15
> fps, e o script não consegue processar instantaneamente. Qualquer
> sugestão é bem vinda, desde já agradeço.

Usa o profile do python pra ver qual funcao pode ta te atrapalhando....

To vendo que vc usa o disco 2 vezes no script (no comeco pra ler, e no
fim pra escrever), isso pode ser um gargalo dependendo da maquina,
btw, recomendo o profile msm

--
Rafael "SDM" Sierra
http://stiod.com.br/

Daniel

unread,
May 26, 2007, 11:23:41 AM5/26/07
to python...@yahoogrupos.com.br
Realmente, lembro que numa aplicação onde era necessário ler e escrever
algumas .wavs o python (ou a máquina) apanhava um pouco, testei o script
apenas com imagens salvas em disco, vou fazer o teste com a webcam, porque
aí a imagem estará na memória e não necessitará de acesso a disco.
Mesmo assim vou utilizar o profile e ver o que ele me diz, depois envio os
resultados.
Obrigado.

--
Daniel - NO Java * YES C/Python


[As partes desta mensagem que não continham texto foram removidas]

Danilo Cesar

unread,
May 26, 2007, 11:41:59 AM5/26/07
to python...@yahoogrupos.com.br
Tu pode ganhar desempenho usando um pouco de processamento paralelo também.

Enquanto sua aplicação está lendo a próxima imagem do disco, uma outra
thread está processando a imagem anterior. O tempo de espera de leitura
do HD pode ser aproveitado...

Só lembro de sincronizar as threads.


Danilo Cesar

Daniel escreveu:


>
>
> Realmente, lembro que numa aplicação onde era necessário ler e escrever
> algumas .wavs o python (ou a máquina) apanhava um pouco, testei o script
> apenas com imagens salvas em disco, vou fazer o teste com a webcam, porque
> aí a imagem estará na memória e não necessitará de acesso a disco.
> Mesmo assim vou utilizar o profile e ver o que ele me diz, depois envio os
> resultados.
> Obrigado.
>
> --
> Daniel - NO Java * YES C/Python
>
> [As partes desta mensagem que não continham texto foram removidas]
>
>


--
Danilo Cesar Lemes de Paula
Fone: 88336496
UFPR - Ciência da Computação

Eduardo Picado

unread,
May 26, 2007, 12:47:37 PM5/26/07
to python...@yahoogrupos.com.br
tenta usar xrange ao inves de range

On 5/26/07, Daniel <dani...@gmail.com> wrote:
>


--
Eduardo PICADO
MSN eduardo.picado [at] gmail.com
|̲̅<̲̅Θ̲̅>̲̅|


[As partes desta mensagem que não continham texto foram removidas]

,-----------------------------------------------------------.

Pablo Cavalcanti

unread,
May 26, 2007, 12:55:12 PM5/26/07
to python...@yahoogrupos.com.br
Daniel, o metodo getpixel eh estramemente lento.
Use o metofo imagem.getdata()
Ele retorna uma lista de tamanho largura X altura - assim um for apenas
percorre todos os pixels.
Sugereria ir alterando os pixels em uma nova lista.
Veja o codigo abaixo:

import Image
im = Image.open('foto.jpg')
velha = im.getdata()
nova = []


VERMELHO = (255,0,0,255)
BRANCO = (255,255,255,255)

for pix in velha:


if pix[0]>200 and pix[1]<30 and pix[2]<30:

nova.append(VERMELHO)
else:
nova.append(BRANCO)
im2 = Image.new("RGBA",(im.size))
im2.putdata(nova)

Para falar a verdade eu nunca usei estes metodos para imagens "RGBA", apenas
"RGB". Mas acredito que funcione e espero que te ajude.
Abracos...

Pablo


Em 26/05/07, Daniel <dani...@gmail.com> escreveu:

Luciano Ramalho

unread,
May 26, 2007, 1:46:30 PM5/26/07
to python...@yahoogrupos.com.br
On 5/26/07, Pablo Cavalcanti <pgcava...@gmail.com> wrote:
> Daniel, o metodo getpixel eh estramemente lento.
> Use o metofo imagem.getdata()
> Ele retorna uma lista de tamanho largura X altura - assim um for apenas
> percorre todos os pixels.

Evitar ler os pixels um por um é uma grande dica. Outra seria ler os
pixels para um array (veja o módulo array) em vez de uma lista, ou
para um array do NumPy. Por sinal, acho que no manual do PIL eu vi em
algum lugar exemplos que usavam o NumPy para processar os pixels no
atacado.

http://numpy.scipy.org/

Existe a possibilidade de que isto que você está querendo não possa
ser feito em Python com o hardware atual: processamento de imagens em
tempo real não é o tipo de aplicação para a qual eu pensaria em Python
como primeira opção. Se funcionar, ótimo, vou querer saber! E se não
funcionar mas você puder esperar uns dois ou três anos, o hardware
chega lá...


[ ]s
Luciano

Pedro Werneck

unread,
May 26, 2007, 2:16:30 PM5/26/07
to python...@yahoogrupos.com.br
On Sat, 26 May 2007 14:46:30 -0300
"Luciano Ramalho" <ram...@gmail.com> wrote:

> On 5/26/07, Pablo Cavalcanti <pgcava...@gmail.com> wrote:
> > Daniel, o metodo getpixel eh estramemente lento.
> > Use o metofo imagem.getdata()
> > Ele retorna uma lista de tamanho largura X altura - assim um for
> > apenas percorre todos os pixels.
>
> Evitar ler os pixels um por um é uma grande dica. Outra seria ler os
> pixels para um array (veja o módulo array) em vez de uma lista, ou
> para um array do NumPy. Por sinal, acho que no manual do PIL eu vi em
> algum lugar exemplos que usavam o NumPy para processar os pixels no
> atacado.

Sim... dá pra fazer simplesmente:

data = numpy.array(imagem.getdata())

E depois usar numpy.where() para o loop.


> Existe a possibilidade de que isto que você está querendo não possa
> ser feito em Python com o hardware atual: processamento de imagens em
> tempo real não é o tipo de aplicação para a qual eu pensaria em Python
> como primeira opção. Se funcionar, ótimo, vou querer saber! E se não
> funcionar mas você puder esperar uns dois ou três anos, o hardware
> chega lá...

Depende... usando numpy já implementei um hough transform que funcionava
rápido o bastante para não precisar implementar uma versão em outra
linguagem. O código demorava mais na leitura da imagem para o array do
que no processamento.


--
Pedro Werneck

Rodrigo Senra

unread,
May 26, 2007, 2:40:10 PM5/26/07
to python...@yahoogrupos.com.br
[ Daniel <dani...@gmail.com> ]:
-----------------------------------------------

|Estou usando o código abaixo para detectar cores predominantemente
|vermelhas em uma imagem, e preencher as demais cores com branco. A
|questão é que está um pouco lento. Tenho uma webcam que captura a 15
|fps, e o script não consegue processar instantaneamente. Qualquer
|sugestão é bem vinda, desde já agradeço.

Existe uma discussão [1] sobre "setar pixels" que pode ser útil.
No geral, endosso a idéia de converter a imgem inteira para um vetor
e no que tange ao processamento eu faria um módulo em C só com uma
função, para percorrer o vetor e corrigir os pixels. O vetor corrigido
é devolvido e reconvertido para um obj Image do PIL.

Esta estratégia dá para ser implementada rápido e acho que vai
lhe trazer bons resultados em termos de desempenho.

[1] http://www.langarson.com.au/blog/?p=11

Abração
Senra

Daniel

unread,
May 26, 2007, 9:38:56 PM5/26/07
to python...@yahoogrupos.com.br
Primeiramente gostaria de agradecer a todos.

Eu nunca utilizei o profile, mas pelo que entendi o grosso do tempo gasto no
runtime segue abaixo:

ncalls tottime percall cumtime percall filename:lineno(function)
38400 0.215 0.000 0.607 0.000 Image.py:1161(putpixel)
38400 0.211 0.000 0.552 0.000 Image.py:855(getpixel)
76802 0.389 0.000 0.539 0.000 ImageFile.py:115(load)
76802 0.147 0.000 0.147 0.000 Image.py:525(load)


Então acho que agora os passos que vou seguir são:

- as imagens serão RGB, creio que não terei necessidade do canal alpha
- utilizar a função getdata()
- utilizar vetores numpy ao inves de listas
- comparar resultados
- implementar módulo que corrige os pixels em C
- comparar resultados

Abraço pessoal, e mais uma vez valeu pelas dicas.


--
Daniel - NO Java * YES C/Python

[As partes desta mensagem que não continham texto foram removidas]

,-----------------------------------------------------------.

Daniel

unread,
May 26, 2007, 11:39:37 PM5/26/07
to python...@yahoogrupos.com.br
Bem, mudei algumas linhas de código e obtive melhoras significativas do runtime.

usando get_pixel e put_pixel (antiga):
real 0m1.223s
user 0m1.068s
sys 0m0.032s

usando get_data, nova.append:
real 0m0.350s
user 0m0.252s
sys 0m0.028s

Como nunca utilizei a numpy, vou ter que dar uma olhada em alguns
códigos, mas o tempo que a lib leva para carregar fez com que as
comparações ficassem desiguais. Embora depois de uma vez carregada
provavelmente ela possa bater nas demais escolhas. Ainda assim é
necessário fazer testes pra saber qual forma melhor utiliza memória e
processamento. Caso isso já mate o problema, ainda assim é razoável
comparar com o desempenho do módulo em C que ficaria responsável por
corrigir os pixels. As vezes pra uma imagem estática não é
significativo, mas pra uma stream pode ser... não disponho de uma
webcam em casa, então esperar a outra semana e desenvolver algo na
faculdade.

Abraços.


--
Daniel - NO Java * YES C/Python

José Alexandre Nalon

unread,
May 27, 2007, 12:32:27 PM5/27/07
to python...@yahoogrupos.com.br
Olá!

> Estou usando o código abaixo para detectar cores predominantemente
> vermelhas em uma imagem, e preencher as demais cores com branco.

O problema é que você está tentando processar a imagem
pixel-a-pixel, o que nem sempre é uma boa idéia em Python.
Já que você está trabalhando diretamente com o PIL, sugiro
você tentar usar os métodos disponíveis. Por exemplo, não
sei se isso ia solucionar o seu problema, mas dê uma olhada
nos métodos split() e merge() para separar as bandas, e nos
métodos darker() e lighter() para selecionar imagens com ní-
veis altos ou baixos.

--
José Alexandre Nalon
na...@terra.com.br

Daniel

unread,
May 28, 2007, 2:04:38 PM5/28/07
to python...@yahoogrupos.com.br
Esse código tira shots via webcam, processa o shot e exibe na tela. Ainda
não fiz a medição de frames/seg. Mas o código já é funcional, agora é
implementar a parte de processamento dos pixels em C.

<code>
from VideoCapture import Device
import ImageDraw
import Image
import sys
import pygame
VERMELHO = (255,0,0)
BRANCO = (255,255,255)

# init pygame
pygame.init()
# setup screen size
size = width, height = 352,288
# get cam device
cam = Device(devnum=0)
screen = pygame.display.set_mode(size)

def proc_img(img):
if img.getbands() <> ('R','G','B'):
img = img.convert('RGB')
velha = img.getdata()
nova = []
for pix in velha:
#(pix[0]=Red, pix[1]=Green, pix[2]=Blue)
#detecta cores predominantemente vermelhas
if pix[0]>190 and pix[1]<70 and pix[2]<70:
nova.append(VERMELHO)
else:
nova.append(BRANCO)
img2 = Image.new('RGB',img.size)
img2.putdata(nova)
return img2

while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()

camshot = cam.getImage()
camshot2 = proc_img(camshot)
camshot3 = pygame.image.fromstring(camshot2.tostring(), (352,288),
"RGB")
screen.blit(camshot3, (0,0))
pygame.display.flip()
</code>

Abraços.


--
Daniel - NO Java * YES C/Python

[As partes desta mensagem que não continham texto foram removidas]

,-----------------------------------------------------------.

José Alexandre Nalon

unread,
May 28, 2007, 2:54:35 PM5/28/07
to python...@yahoogrupos.com.br
Olá!

> Esse código tira shots via webcam, processa o shot e exibe na tela. Ainda
> não fiz a medição de frames/seg. Mas o código já é funcional, agora é
> implementar a parte de processamento dos pixels em C.

Talvez meu email anterior tenha ficado soterrado sob a
avalanche de respostas que este tópico merecidamente re-
cebeu, então vou repetir minha resposta, que pode ajudar
bastante. Me parece que o processamento que você quer fa-
zer pode ser feito diretamente com rotinas do PIL (e pro-
vavelmente com rotinas do PyGame, que você está usando).
Processamento banda-a-banda é uma capacidade do PIL, in-
cluindo comparação e atribuição de pixels. Há duas vanta-
gens: o processamento é feito na maior velocidade possí-
vel e já está implementado.

Por exemplo, veja se alguma coisa no módulo ImageEnhancer
pode te ajudar, ou talvez o módulo ImageChops (serve para
você trabalhar diretamente com os canais R, G e B, apli-
cando operadores a eles). Se não for o caso, o módulo
ImageMath pode te permitir aplicar todo o seu processamen-
to na forma de um único operador sobre toda a imagem, per-
mitindo, no mínimo, um pouco menos de linhas de programa-
ção.

Claro, se você quer implementar para ter maior controle
sobre o que está acontecendo, ok. Mas, se não for o caso,
vale a pena dar uma olhada nessas possibilidades.

--
José Alexandre Nalon
na...@terra.com.br

Jociel Andrade

unread,
May 28, 2007, 3:22:53 PM5/28/07
to python...@yahoogrupos.com.br
Se a imagem fosse no formato GIF89a seria muito fácil e muito rápida a
transformação...
Há muito tempo atrás (leia-se anos 95 a 97) eu trabalhei com o formato
GIF89a escovando bits (tive que aprender o formato na base de engenharia
reversa, não encontrava documentação)...
Nesse formato há uma tabela de cores que serão usadas para definir a
imagem... Nesse caso então, bastaria alterar os valores dessa tabela para
alterar toda a imagem. Note que o tamanho da tabela de cores (que
corresponde apenas às cores utilizadas na imagem) é muito menor que o número
de pixels que formam a imagem.
Um programinha simples em C resolveria.

[]'s
Jociel

On 5/27/07, José Alexandre Nalon <na...@terra.com.br> wrote:
>
> Olá!
>
> > Estou usando o código abaixo para detectar cores predominantemente
> > vermelhas em uma imagem, e preencher as demais cores com branco.
>
> O problema é que você está tentando processar a imagem
> pixel-a-pixel, o que nem sempre é uma boa idéia em Python.
> Já que você está trabalhando diretamente com o PIL, sugiro
> você tentar usar os métodos disponíveis. Por exemplo, não
> sei se isso ia solucionar o seu problema, mas dê uma olhada
> nos métodos split() e merge() para separar as bandas, e nos
> métodos darker() e lighter() para selecionar imagens com ní-
> veis altos ou baixos.
>
> --
> José Alexandre Nalon

> na...@terra.com.br <nalon%40terra.com.br>
>
>


[As partes desta mensagem que não continham texto foram removidas]

,-----------------------------------------------------------.

Alex

unread,
May 29, 2007, 8:10:30 AM5/29/07
to python...@yahoogrupos.com.br
Eu adquiri um laptop recentemente, mas não consigo configurar a webcam
(usb) nele.
Alguém pode recomendar algo?


--- Em python...@yahoogrupos.com.br, Daniel <danielvaz@...> escreveu

Alex

unread,
May 29, 2007, 8:12:10 AM5/29/07
to python...@yahoogrupos.com.br
Esqueci de mencionar, eu faço questão do Linux e pretendo fazer
rotinas em Python para aquisição e pré-processamento das imagens da
webcam.

--- Em python...@yahoogrupos.com.br, Daniel <danielvaz@...> escreveu
>

Leonardo Santagada

unread,
May 29, 2007, 11:06:31 AM5/29/07
to python...@yahoogrupos.com.br

Em 29/05/2007, às 09:12, Alex escreveu:

> Esqueci de mencionar, eu faço questão do Linux e pretendo fazer
> rotinas em Python para aquisição e pré-processamento das imagens da
> webcam.

Legal, nas rotinas a gente pode te ajudar, na configuração da webcam
não... Tem a lista ubuntu-br e muitas outras que podem te ajudar.

--
Leonardo Santagada
"If it looks like a duck, and quacks like a duck, we have at least to
consider the possibility that we have a small aquatic bird of the
family anatidae on our hands." - Douglas Adams

Alex

unread,
May 30, 2007, 9:00:59 AM5/30/07
to python...@yahoogrupos.com.br
Agradeço a atenção.

A PIL tem suporte para acesso à webcam?

Eu conheço a openCV, mas pretendo usar uns recursos da PIL, caso fosse
possível, prefiro não sobrecarregar o programa.

Att.
Alex.


--- Em python...@yahoogrupos.com.br, Leonardo Santagada
<santagada@...> escreveu

Cleber Willian

unread,
May 30, 2007, 6:56:22 PM5/30/07
to python...@yahoogrupos.com.br
cara da uma olhada nessa url:

http://gumuz.looze.net/wordpress/index.php/archives/2005/06/06/python-webcam-fun-motion-detection/

On 5/30/07, Alex <arch...@yahoo.com.br> wrote:
>
> Agradeço a atenção.
>
> A PIL tem suporte para acesso à webcam?
>
> Eu conheço a openCV, mas pretendo usar uns recursos da PIL, caso fosse
> possível, prefiro não sobrecarregar o programa.
>
> Att.
> Alex.
>

> --- Em python...@yahoogrupos.com.br<python-brasil%40yahoogrupos.com.br>,


> Leonardo Santagada
> <santagada@...> escreveu
> >
> >
> > Em 29/05/2007, às 09:12, Alex escreveu:
> >
> > > Esqueci de mencionar, eu faço questão do Linux e pretendo fazer
> > > rotinas em Python para aquisição e pré-processamento das imagens da
> > > webcam.
> >
> > Legal, nas rotinas a gente pode te ajudar, na configuração da webcam
> > não... Tem a lista ubuntu-br e muitas outras que podem te ajudar.
> >
> > --
> > Leonardo Santagada
> > "If it looks like a duck, and quacks like a duck, we have at least to
> > consider the possibility that we have a small aquatic bird of the
> > family anatidae on our hands." - Douglas Adams
> >
>
>
>

--
,_
>' ) Cleber Willian dos Santos
( ( \ e-mail / gtalk: cleber...@gmail.com
''|\ website: binho.net


[As partes desta mensagem que não continham texto foram removidas]

,-----------------------------------------------------------.

Reply all
Reply to author
Forward
0 new messages