Você está na página 1de 85

Processamento de Imagens

e

Reconhecimento de Padrões

AULA 5

Prof. Francisco Fambrini UNISAL – Março/2017

PROCESSAMENTO MORFOLÓGICO

A palavra morfologia significa o estudo da forma ou estrutura. Em processamento de imagens usamos morfologia matemática para identificar e extrair descritores de imagens com base em propriedades de formas e contornos das imagens. Importantes áreas de aplicação são segmentação, contagem e inspeção automatizadas. A morfologia possui vários métodos que são estudados em Teoria dos Conjuntos. O principal uso da Morfologia é no Processamento de Imagens Binárias, e os principais operadores morfológicos são os operadores de Dilatação e de Erosão. Os procedimentos morfológicos muito mais sofisticados podem ser reduzidos a uma sequencia de dilatações e erosões.

Operações Lógicas envolvendo imagens binárias

Operações Lógicas envolvendo imagens binárias

Dilatação

Dilatação
Dilatação

Elemento Estruturante

Não existe Operação Morfológica sem elemento estruturante. Primeiro passo é definir o formato do elemento estruturante e qual é sua posição de origem.

elemento estruturante . Primeiro passo é definir o formato do elemento estruturante e qual é sua

Dilatação na prática

Elemento Estruturante 3X3

Elemento Estruturante 5X3
Elemento Estruturante 5X3

Exemplos - Dilatação:

Exemplos - Dilatação:

Para que serve a dilatação ?

Para que serve a dilatação ?

Erosão

Erosão
Erosão

Erosão

Elemento Estruturante 3X3

Elemento Estruturante 5X3
Elemento Estruturante 5X3

Erosão - exemplos

Erosão - exemplos

Outro exemplo de Erosão

Outro exemplo de Erosão

Aplicação da Erosão seguida de Dilatação remoção de componentes

Aplicação da Erosão seguida de Dilatação remoção de componentes

Abertura e Fechamento

Abertura e Fechamento

Propriedades da Abertura e do Fechamento

Propriedades da Abertura e do Fechamento

Operador Morfológico de Abertura (Erosão seguida por uma dilatação)

Operador Morfológico de Abertura (Erosão seguida por uma dilatação)

Operador Morfológico de Fechamento (dilatação seguido por uma erosão)

Operador Morfológico de Fechamento (dilatação seguido por uma erosão)
Erosão e Dilatação feitas usando um elemento estruturante na forma de um pequeno disco circular

Erosão e Dilatação feitas usando um elemento estruturante na forma de um pequeno disco circular

Aplicação do Fechamento

Aplicação do Fechamento

Exemplo 1 – MATLAB (DILATAÇÃO)

No exemplo a seguir, o elemento estruturante é definido como uma matriz 3X3. A sintaxe básica requer a imagem e o elemento estruturante como entradas para a função, e a imagem dilatada é retornada como saída.

bw= imread(‘text.png’)

se = [ 0 1 0;

bw_out= imdilate(bw,se) subplot(1,2,1); imshow(bw); subplot(1,2,2); imshow(bw_out);

1

1

1;

0 1 0 ]

Exemplo 2 – MATLAB (EROSÃO)

bw= imread('text2.png') se = ones(6,1); bw_out= imerode(bw,se) subplot(1,2,1); imshow(bw); subplot(1,2,2); imshow(bw_out);

Função strel (MATLAB)

A função strel do Toolbox de Processamento de Imagens do MATLAB serve para definir elementos estruturantes de diferentes formatos.

bw= imread('text2.png') se1 = strel('square',4); se2 = strel('line',5,45); bw_1=imdilate(bw, se1); bw_2=imdilate(bw, se2);

% elem estrut quadrado % elem estrut reta

subplot(1,2,1); imshow(bw_1); subplot(1,2,2); imshow(bw_2);

Efeitos e usos da erosão e dilatação

A erosão reduz o tamanho de um objeto binário, enquanto a dilatação o aumenta. A erosão tem o efeito de remover todas as pequenas características isoladas, de separar regiões adjuntas e delgadas de uma característica, de reduzir o tamanho de objetos sólidos erodindo-os nas fronteiras. A dilatação tem um efeito aproximadamente reverso ao da erosão: alarga e espessa regiões estreitas, ressalta características em torno das bordas. Dilatação e erosão são o reverso uma da outra, embora não sejam inversas no sentido matemático. Não é possivel restaurar por dilatação um objeto que tenha sido completamente removido por erosão.

Exemplo 3-Uso de dilatação e erosão para identificar características baseadas em forma.

tlevel = 0.2;

A=imread('circuit.tif');subplot(2,3,1), imshow(A) % le a imagem e mostra na tela

%define nivel de treshold para binarização

B = im2bw(A,tlevel); subplot(2,3,2), imshow(~B); %binariza e mostra a imagem

SE =ones(3,18); bw1 =imerode(~B,SE);

%Erode retas verticais

subplot(2,3,3), imshow(bw1); %Exibe resultado bw2 = imerode(bw1,SE');subplot(2,3,4),imshow(bw2)

bw3= imdilate(bw2, SE'); bw4=imdilate(bw3,SE);

subplot(2,3,5),imshow(bw4); %exibe a imagem dilatada boundary= bwperim(bw4); [i,j] =find(boundary); %sobrepõe fronteiras subplot(2,3,6), imshow(A); plot(j,i,'r.');

%erode retas horizontais

%dilata a imagem

Exercício

Use os operadores de Erosão (principalmente) e Dilatação (se necessário) para apagar as unhas da mulher e deixar apenas os lábios na foto, no exercício da aula passada.

Erosão no SimpleCV

from SimpleCV import Image im = Image ( “Jacopo.png” ) Img = im.grayscale() imgBin = img.binarize() imgBin.erode().show()

Dilatação no SimpleCV

from SimpleCV import Image im = Image ( “Jacopo.png” ) img = im.grayscale() imgBin = img.binarize() imgBin.dilate().show()

Combinando Dilatação e Erosão

A função Dilate() ajuda a preencher o interior dos buracos, mas ela também amplifica alguns tipos de ruídos nas imagens. Por outro lado, a função erode() elimina vários ruidos (pontinhos brancos), mas elimina também informações úteis. A solução para este problema é combinar as duas funções.

Estas combinações de dilatação e erosão são tão comuns que existem funções próprias:

morphOpen( )

e

morphClose( )

Abertura e

fechamento, respectivamente.

morphOpen()

ABERTURA:

Erode e depois dilata a imagem. A erosão elimina pequenos objetos e a dilatação restaura mais ou menos o tamanho dos objetos originais que

sobraram após a erosão.

from SimpleCV import Image im = Image ( “Jacopo.png” ) img = im.grayscale() imgBin = img.binarize() imgBin.morphOpen().show

morphClose()

FECHAMENTO:

É a dilatação seguida de erosão. A dilatação primeiro preenche os pequenos buracos entre os objetos. Se aqueles buracos forem pequenos o suficiente, a dilatação vai preenche-los completamente, e a subsequente erosão não irá abrir os buracos. A finalidade é reduzir a quantidade de ruído na imagem.

from SimpleCV import Image im = Image ( “Jacopo.png” ) img = im.grayscale() imgBin = img.binarize() imgBin.morphClose().show

Às vezes, o melhor é fazer múltiplas erosões seguidas por multiplas dilatações na imagem. Para simplificar este processo, as funções dilate() e erode() aceitam um parâmetro que representa o número de vezes em que a função será executada.

Por exemplo, dilate(5) significa fazer 5 dilatações seguidas na imagem:

Vamos ver outro exemplo de dilatações seguidas de erosões:

significa fazer 5 dilatações seguidas na imagem: Vamos ver outro exemplo de dilatações seguidas de erosões:

OUTROS EFEITOS EM VÍDEO

Imagens são matrizes

Já explicamos, desde a primeira aula, que imagens são matrizes. Uma imagem em (RGB) é na verdade uma

matriz de dimensões mXnX3

altura e 3 corresponde à quantidade de R,G e B da imagem. Em muitos casos, é útil transformar esta matriz tridimensional num único vetor (matriz linha). Para transformar uma imagem RGB num vetor, use o NumPy e faça:

onde m é a largura, n é a

m1 = Image( “sua_imagemRGB.png“ mp1 = m1.getNumpy() f1 = mp1.flatten()

)

Fazendo Rotação no vídeo !

Este é um efeito muito legal de processamento de imagens: O script a seguir vai fazer rotação continua na imagem capturada pela câmera e também aumenta progressivamente o ângulo de rotação:

vai fazer rotação continua na imagem capturada pela câmera e também aumenta progressivamente o ângulo de

Medindo objetos

Este segundo exemplo é mais prático: mostra como medir objetos com a câmera. A idéia básica é comparar o objeto que está sendo medido com outro objeto de tamanho conhecido. Por exemplo: Se um objeto está situado em cima do pedaço de uma folha de papel que mede 21,25 x 27,5 cm , podemos usar o tamanho conhecido da folha de papel para determinar o tamanho do objeto. Entretanto, isso é complicado, se o papel não parecer quadrado para a câmera (ou seja, se o papel é visto em perspectiva). O próximo exemplo mostra como consertar isso com a função warp().

X=? 21,25cm
X=?
21,25cm

Medindo objetos

from SimpleCV import Image

img = Image ('skew.png')

corners = [(0,0), (480,0), (336,237),(147,237)]

warped = img.warp(corners)

bgcolor = warped.getPixel(240,115)

dist = warped.colorDistance(bgcolor)

blobs = dist.invert().findBlobs()

paper = blobs[-1].crop()

toyBlobs = paper.invert().findBlobs()

toy = toyBlobs[-1].crop()

paperSize = paper.width

toySize = toy.width

print float(toySize)/float (paperSize)*21.25

Explicando o código

corners = [(0,0), (480,0), (336,237),(147,237)] Estas são as coordenadas para os 4 cantos da folha. Uma boa maneira para identificar os pontos dos cantos é usar o Shell do SimpleCV para carregar a imagem e depois usar a função image.live() para mostrá-la. Então você pode dar um click com o botão esquerdo do mouse para descobrir as coordenadas dos cantos da folha de papel vermelho.

warped = img.warp(corners) Deforma a imagem transformando-a no quadrado das bordas da folha de papel, como mostrado na figura a seguir:

Deforma a imagem transformando-a no quadrado das bordas da folha de papel, como mostrado na figura

Explicando o código

dist = warped.colorDistance(bgcolor) Use o truque do image.live() também para encontrar a cor do papel. Isso tornará mais fácil descobrir qual parte da imagem é o papel e qual parte são os objetos de fundo. A imagem a seguir mostra o resultado. Perceba que o papel é preto enquanto o restante da imagem é representado em vários tons de cinza.

mostra o resultado. Perceba que o papel é preto enquanto o restante da imagem é representado

Explicando o código

blobs = dist.invert().findBlobs()

Fazendo preto o papel, fica mais fácil detectar a peça azul usando a função Blobs()

paper = blobs[-1].crop()

Agora recorta da imagem original o maior Blob (que é o papel) e isso é representado por blobs[-1]. (-1) é o maior blob encontrado na imagem.

Isso cria uma nova imagem que é apenas o papel.

Explicando o código

toy = toyBlobs[-1].crop()

Agora, olhando apenas a área do papel, usa a função findBlobs() novamente para localizar a peça azul. Cria uma imagem da peça azul cortando-a do papel.

print

float(toySize)/float (paperSize)*21.25

Usando a largura do papel e a peça azul, combinado com o fato de que a largura do papel é conhecida e igual a 21,25cm, calcula o tamanho da peça azul, que é de 4,67 cm.

Observe que este exemplo trabalha melhor com objetos planos. Quando ajustamos o “esquadro” da imagem, isso faz a parte de cima do objeto parecer mais larga do que a base, o que pode resultar em erros de medida.

COR

E

SEGMENTAÇÃO

Segmentação

Segmentação é o processo de dividir uma imagem em áreas de conteúdo relacionado. Essas áreas consistem de pixels que compartilham uma característica particular, e uma das características mais frequentemente usadas é a cor.

É fácil usar a cor para segmentar uma imagem.

Essa técnica é muito efetiva quando a cor do objeto desejado é substancialmente diferente da cor do fundo.

Neste caso, você pode usar a cor para segmentar uma imagem e remover o conteúdo do fundo da imagem, deixando apenas o objeto de interesse.

Exemplo de Segmentação de imagem colorida

from SimpleCV import * yellowTool = Image( "yellowtool.png“ ) yellowDist = yellowTool.colorDistance((223, 191, 29)) yellowDistBin = yellowDist.binarize(50).invert() yellowDistBin.show()

Observe que a combinação (R,G,B) = (223, 191, 29) corresponde a cor amarela da pistola de cola quente.

Detectando um carro ilegalmente estacionado

Veja a imagem do estacionamento, sem o carro amarelo estacionado em lugar proibido:

um carro ilegalmente estacionado Veja a imagem do estacionamento, sem o carro amarelo estacionado em lugar

Carro amarelo no lugar proibido

Carro amarelo no lugar proibido

Como fazer ?

Um simples teste procuraria segmentar o amarelo. Entretanto, se o carro amarelo estiver estacionado ao lado da vaga para deficientes, então não estará em local proibido.

Então, esta “visão detectora de amarelo” terá que verificar se o carro aparece dentro de uma área especifica da imagem.

Carregamos as imagens dos carros

from SimpleCV import Image car_in_lot = Image("parking-car.png") car_not_in_lot = Image("parking-no-car.png")

O próximo passo é usar a figura do carro no ponto para determinar a área por inspeção. Uma vez que a imagem original contém espaços legais e ilegais para estacionar, ela precisa ser recortada para cobrir somente o espaço destinado aos deficientes (área ilegal para estacionar). O tamanho total da imagem é 800x600 pixels. A localização do espaço proibido é a caixa em torno do carro, chamada ROI ( Região de Interesse). Neste caso, a ROI começa no ponto(470,200) e tem aproximadamente 200x200 pixels.

from SimpleCV import Image car_in_lot = Image("parking-car.png") car_not_in_lot = Image("parking-no-car.png") car = car_in_lot.crop(470,200,200,200) # Mostra o resultado car.show()

Agora que a imagem está cortada somente para a área de estacionamento ilegal, o próximo passo é encontrar o carro na imagem. A técnica é similar ao exemplo da pistola de cola quente. Primeiro, vamos achar os pixels que estão próximos da área amarela:

From SimpleCV import * car_in_lot = Image( "parking-car.png“ ) car_not_in_lot = Image( "parking-no-car.png“ ) car = car_in_lot.crop(470,200,200,200)

yellow_car = car.colorDistance(Color.YELLOW)

# Mostra os resultados yellow_car.show( )

Subtrai agora a imagem em escala de cinzas da imagem cortada, para obtermos somente a imagem do carro amarelo. Para comparar esta imagem com a imagem que não tem o carro amarelo, deve haver vários tipos de medidas para representar o carro. Uma maneira simples de fazer isso é usando a função meanColor().

Como o próprio nome diz, esta função calcula a “cor média” de uma imagem:

From SimpleCV import * car_in_lot = Image( "parking-car.png“ ) car_not_in_lot = Image( "parking-no-car.png“ ) car = car_in_lot.crop(470,200,200,200) yellow_car = car.colorDistance(Color.YELLOW) only_car = car - yellow_car print only_car.meanColor()

Esta função vai imprimir o valor médio das cores:

( 25.604575,

18.880775,

4.482825)

Isso é uma medida para o espaço quando ocupado pelo carro amarelo. Repita o mesmo processo para o lugar com o espaço vazio (sem o carro estacionado):

from SimpleCV import * car_in_lot = Image( "parking-car.png“ ) car_not_in_lot = Image( "parking-no-car.png“ ) car = car_in_lot.crop(470,200,200,200) yellow_car = car.colorDistance(Color.YELLOW) only_car = car - yellow_car no_car = car_not_in_lot.crop(470,200,200,200) without_yellow_car = no_car.colorDistance(Color.YELLOW) without_yellow_car.show()

Retorne para a imagem em escala de cinza mostrando o quanto longe estão as cores no espaço vazio em relação à imagem com o carro amarelo estacionado. Mais uma vez, subtraia a color_distance e calcule o valor médio da cor:

From SimpleCV

import *

car_in_lot = Image( "parking-car.png“ ) car_not_in_lot = Image( "parking-no-car.png“ ) car = car_in_lot.crop(470,200,200,200)

yellow_car = car.colorDistance(Color.YELLOW) only_car = car - yellow_car no_car = car_not_in_lot.crop(470,200,200,200) without_yellow_car = no_car.colorDistance(Color.YELLOW) -

print only_space.meanColor()

only_space =

no_car

without_yellow_car

O resultado da cor média será:

( 5.031350000000001, 3.6336250000000003, 4.683625)

Esta média é substancialmente diferente da média quando o carro está na imagem, que é de (25.604575, 18.880775, 4.4940750000000005).

A quantidade de azul ( lembre-se (R,G,B) ) é quase igual, mas as quantidades de vermelho e verde são muito diferentes. Isso ocorre porque o amarelo é criado pela combinação do vermelho e do verde.

Sabendo disso, fica relativamente fácil definir os limiares para determinar se o carro amarelo está ou não estacionado na região proibida.

O próximo slide ilustra um exemplo de como ficaria o programa em SimpleCV:

from SimpleCV import * car_in_lot = Image( "parking-car.png“ ) car_not_in_lot = Image( "parking-no-car.png“ ) car = car_in_lot.crop(470,200,200,200) yellow_car = car.colorDistance(Color.YELLOW) only_car = car - yellow_car (r, g, b) = only_car.meanColor() if ((r > 15) and (g > 10):

print “Carro no lugar proibido. Chamar o Guarda.“

(Se os valores de R e de G são suficientemente altos, então o carro amarelo está provavelmente estacionado no espaço para deficientes)

Subtraindo uma imagem da outra

Suponha que você queira saber se alguém está pegando as balas que você deixa num pote na mesa do escritório. Contar as balas todos os dias é um jeito, mas a Visão Computacional pode nos dar uma solução melhor: fotografar o pote de bales e subtrair uma imagem da outra. Se a diferença entre as imagens for maior do que um certo limiar (treshold) então você saberá que a foto mudou e alguém provavelmente pegou balas dali sem sua autorização.

#Carrega as duas fotos, tiradas nos instante de tempo A e B:

timeA = Image( "candyA.png“ ) timeB = Image( "candyB.png“ ) # Compara as 2 imagens, subtraindo uma da outra diff = timeA - timeB

) timeB = Image( "candyB.png“ ) # Compara as 2 imagens, subtraindo uma da outra diff

O ladrão de balas

from SimpleCV

#Carrega a diferença entre as duas imagens

diff = Image( "candydiff.png“

# Extrai os pixels individuais dentro de uma matriz plana matrix = diff.getNumpy() flat = matrix.flatten()

# Calcula quantos pixels mudaram num_change = np.count_nonzero(flat)

percent_change = float(num_change) / float(len(flat)) if percent_change > 0.1:

import *

)

print

“Pare de chupar meus doces!“

No script acima, se a diferença entre os pixels for maior do que 10% ele vai dizer que as balas foram mudadas (aumentaram ou diminuiram) ou seja, que houve mudanças significativas entre a foto 1 e a foto 2.

Comentários sobre o programa anterior

matrix = diff.getNumpy() Lembre-se de que uma imagem é essencialmente uma matriz de valores de pixels. Portanto, para aplicar técnicas matemáticas em uma imagem, às vezes é mais fácil transformar esta imagem em formato de matriz. A função getNumpy () retorna uma matriz NumPy da imagem.

flat = matrix.flatten() A matriz NumPy é, na verdade, uma matriz tridimensional com as dimensões 640x 480 x 3. Isto corresponde às dimensões de imagem de 640 x 480, com uma adicional dimensão para os três valores para vermelho, verde e azul. No entanto, ao invés de trabalhar com uma matriz tridimensional, será mais rápido achatar esta em uma matriz de 1 dimensão: 921.600 x 1.

num_change = np.count_nonzero(flat) Podemos usar Numpy (importado por padrão no SimpleCV como "np") para rapidamente contar o número de pixels diferentes de zero.

percent_change = float(num_change) / float(len(flat))

Calcula a porcentagem de valores que mudou.

Lembre-se que num_change

é a variável que conta o número de pixels que não

são pretos, indicando uma diferença na imagem.

len (flat) calcula o número total de pixels na imagem (ou mais com precisão, na matriz achatada que representa a imagem).

if percent_change > 0.1:

print “pare de pegar as balas do pote!” Finalmente, verifica se o número de pixels que mudou excede o limiar (10%). Se isso ocorreu imprime um aviso. Neste caso, cerca de 22% dos pixels foi alterado, o que imprime a mensagem na Tela: "Pare de roubar minhas balas".

Função meanColor()

A função meanColor () seria uma outra maneira para detectar uma alteração nas imagens. Se as imagens são iguais, a média de cor será preto (ou seja, zero). Caso contrário, as diferenças vão ter cores diferentes,que terá impacto sobre o valor da cor média. Claro que, para menores alterações, as diferenças na cor média serão mínimas. De novo, a fixação de um limiar adequado (treshold) para a diferença em valores médios de cor vai ajudar a gerenciar os alertas falsos positivos ou negativos.

CAMERA DE SEGURANÇA (DETETOR DE MOVIMENTOS)

Aplicação Prática:

Câmera de Segurança

Detectando movimento na frente de uma câmera através da variação da média de cor de uma imagem .

No exemplo do próximo slide, o treshold representa a MÉDIA DAS CORES e não o percentual de pixels que mudou de um frame para outro.

from SimpleCV import * import time threshold = 5.0 # Se a média das cores exceder este valor, faz algo cam = Camera() previous = cam.getImage() disp = Display(previous.size()) while not disp.isDone():

current = cam.getImage() # Obtém outro frame e compara com o anterior diff = current - previous

# Converte para uma Matriz no programa Numpy e calcula a media das cores matrix = diff.getNumpy() mean = matrix.mean()

diff.save(disp)

if mean >= threshold:

# Mostra na tela

# verifica se algo mudou

print "Movimento Detectado ! " #espera 1 segundo

time.sleep(1)

previous = current

Sugestão de Projeto 1

Hoje em dia fala-se muito de IoT (internet das coisas). Baseado no exemplo do estacionamento e do carro amarelo, projete um sistema que monitora o interior de uma geladeira através de uma webcam, olhando sempre o número de latas de cerveja contidas em determinado compartimento. Quando as cervejas acabarem, o sistema deverá enviar um email automaticamente para o Supermercado:

supermercado@gmail.com contendo seu nome, endereço e telefone, pedindo para trazer mais 6 latas de cerveja da sua marca preferida.

Sugestão de Projeto 2

Ainda baseando-se no exemplo do estacionamento de carros, projete um sistema de visão computacional que monitora 5 vagas em um pequeno estacionamento, cada vaga devendo ser ocupada por um automóvel. Seu sistema deverá identificar os carros e contar quantas vagas estão disponiveis em seus estacionamento, para avisar as pessoas antes de entrar. Você pode fazer uma maquete para testar seu sistema usando carrinhos de brinquedo e uma chapa de madeira:

de entrar. Você pode fazer uma maquete para testar seu sistema usando carrinhos de brinquedo e

Sugestão de maquete para o estacionamento

Sugestão de maquete para o estacionamento

Histogramas

Podemos usar o SimpleCV para plotar o histograma de uma imagem, de modo similar ao que fizemos com o MATLAB na primeira aula, porém imprimimos os números na forma de uma matriz:

from SimpleCV import * img = Image( “starry_night.png” ) # Gera o histograma histogram = img.histogram() # Gera a matriz de saida do histograma Print histogram

Histogramas com SimpleCV

Este exemplo de código gera uma lista de 50 valores. Cada valor representa o número de pixels que ocorre em cada nível de brilho. Mas porque foram mostrados 50 valores se existem 256 tons de cinza? A função de histograma () divide o conjunto de dados em intervalos que combinam os valores a partir do eixo x do gráfico. Isto tende a suavizar o gráfico, agrupando níveis juntos. No entanto, o número de intervalos é ajustável por software. O código Python a seguir mostra os 256 níveis de cinza:

from SimpleCV import *

img = Image( 'starry_night.png‘ )

# Generate the histogram with 256 bins, one for each color histogram = img.histogram(256)

# Show how many elements are in the list len(histogram)

Plotando o gráfico do Histograma

Assim como no MATLAB, é possivel no SimpleCV plotar o histograma de uma imagem na forma de um gráfico. Experimente o código a seguir:

from SimpleCV import * img = Image( 'starry_night.png‘ ) # Gera o gráfico mostrando os 256 valores da escala de cinza histogram = img.histogram(256) plot (histogram)

Observação: a Função plot() está na library MATPLOTLIB (http://matplotlib.org/ )que precisa ser carregada à parte (não faz parte do SimpleCV). Para carregar esta library voce pode carregar no terminal de linha de comando, conectado na internet:

$ sudo

pip install

matplotlib

Se você encontrar dificuldades, veja aqui outras maneiras de instalar esta library no Python:

https://www.raspberrypi.org/learning/visualising-sorting-with-python/lesson-1/plan/

Problemas com a instalação de matplotlib

Se você instalou sua biblioteca matplotlib, mas na hora de plotar na tela não aparece nenhum gráfico (e também não aparece nenhum erro) olhe estes links:

http://stackoverflow.com/questions/19721385/matplotlib-

pyplot-does-not-show-output-no-error

http://stackoverflow.com/questions/27798829/importerror-

no-module-named-pyside

Obs: você pode também usar OpenCV (ao invés do SimpleCV) na sua raspberry. Veja aqui:

http://docs.opencv.org/3.1.0/d1/db7/tutorial_py_histogram_

begins.html

Experimente também

from SimpleCV import pylab

cam = Camera() plt.ion() while (1):

img = cam.getImage() img.show() peaks = img.huePeaks() hist = img.hueHistogram() plt.plot(hist)

plt.pause(0.0001)

plt.draw()

import

plt

*

as

Plotando os 3 histogramas R,G e B

Ao invés de olhar o histograma geral, às vezes é mais útil dividir a imagem em seus canais de cor a olhar para o equilíbrio de cor. Isto é demonstrado no seguinte script:

from SimpleCV import * img = Image('starry_night.png')

# Extrai da imagem os 3 canais de cor

(red, green, blue) = img.splitChannels(False)

# Separa os 3 histogramas individuais

red_histogram = red.histogram(255) green_histogram = green.histogram(255) blue_histogram = blue.histogram(255)

# Plota os histogramas – OBS: PRECISA TER A BIBLIOTECA MATPLOTLIB INSTALADA ! plot(red_histogram) plot(green_histogram) plot(blue_histogram)

Comentários sobre o programa

(red, green, blue) = img.splitChannels(False) A função splitChannels () cria três imagens. As três imagens contém componentes vermelho, verde e azul, respectivamente. Por padrão, isso na verdade cria três imagens em tons de cinza, mostrando a intensidade de cada cor individual. Passando o parâmetro False, ele mantém a cor original, que é mais intuitivamente atraente.

red_histogram = red.histogram(255) Uma vez que os canais de cor individuais são separados, gera o histograma, como foi foi feito no exemplo da imagem com tons de cinza. Três canais significa que temos três histogramas.

plot(red_histogram) Traça os histogramas. Observe que cada comando plot espera até que a janela do histograma esteja terminada. Em outras palavras, o código em primeiro lugar mostrar o histograma vermelho. O histograma verde não será exibido até que a janela do histograma vermelha seja finalizada. Então o histograma azul não será exibido até que a janela do verde seja finalizada.

Histogramas R,G e B

Histogramas R,G e B
Histogramas R,G e B

Função Hue Peaks()

HUE SIGNIFICA MATIZ

Depois de olhar para a distribuição de diferentes cores em uma imagem, a próxima questão lógica é de identificar a cor dominante na imagem. Isto é conhecido como encontrar os picos de matiz (Hue Peaks) e é feita utilizando a função huePeaks() para encontrar a(s) cor(es) dominante(s). Apesar de uma imagem poder ser primeiro convertido para o formato de HSV e, em seguida, um histograma pode ser calculado para obter as informações de matiz, o SimpleCV tem um atalho para fazer isso em qualquer formato de imagem. É a função hueHistogram (). Ele funciona exatamente como a função Histogram() mas não mostra os níveis de cinza e sim os níveis de intensidade de cada cor componente. from SimpleCV import * img = Image('monalisa.png')

# calcula o histograma

histogram = img.hueHistogram() plot(histogram)

# calcula os picos do histograma

peaks = img.huePeaks()

# imprime: [(12.927374301675977, 0.11747342828238252)] print peaks

Comentários sobre a função HuePeaks()

[ (12.927374301675977,

0.11747342828238252) ]

A saída da função huePeaks são dois números neste caso.

Se houver um único pico dominante, então haverá apenas um elemento na matriz. O primeiro valor da é o bin que ocorre com mais frequência.

O segundo valor é a porcentagem de pixels que correspondem a essa

cor. Por exemplo, no exemplo acima, o valor 13 é a mais comum, e aparece em 12% do total de pixels da imagem. Este deve parecer aproximadamente correto dado o histograma da imagem Monsa Lisa:

Esta informação pode ser utilizada para subtrair os matizes menos frequentes. Este truque é semelhante aos exemplos anteriores que subtraem valores com base na distância de cor.

Usando a matriz para criar uma máscara

Experimente o script a seguir com a imagem “monalisa”

from SimpleCV import * img = Image('monalisa.png')

# Encontra o valor da matiz dominante (Hue) peaks = img.huePeaks() peak_one = peaks[0][0]

# Calcula a distância da matiz para criar a máscara hue = img.hueDistance(peak_one) mask = hue.binarize().invert()

# Subtrai o valor da matiz dominante lessBackground = img - mask lessBackground.show()

Comentários sobre o programa anterior

A função hueDistance() é parecida com a função colorDistance() já usada nas aulas.Ela vai retornar uma imagem representando a distância de cada pixel do valor de pico da matiz (Hue). Valores pequenos estão próximos do pico dominante de matiz da imagem (Hue peak) e vão aparecer nesta imagem na cor preta. Valores grandes estão mais distantes do pico dominante da matiz e vão aparecer como regiões brancas na imagem binária.

A seguir, a função:

mask = hue.binarize().invert() binariza a matriz distância da imagem,

eliminando os níveis de cinza e gerando uma imagem em preto e branco pura. Criamos assim uma mascara (mask) que é capaz de separar a moça do fundo da imagem.

Subtraimos então a máscara criada da imagem original:

mascara (mask) que é capaz de separar a moça do fundo da imagem. Subtraimos então a

Ruído na imagem resultante

Existe ainda uma boa quantidade de ruído à esquerda na imagem extraída.Os truques usando as funções morfológicas (dilatação, erosão, abertura e fechamento) ajudam a limpar a máscara. Nos exemplos anteriores, mostramos como fazer uma máscara usando a matemática da imagem. O SimpleCV inclui um método de atalho para as operações de máscara. Trata-se uma função máscara binária que permite especificar as cores a serem ocultadas. O seguinte exemplo mostra como extrair o rosto da Mona Lisa.

from SimpleCV

img = Image( "monalisa.png“ ) mask = img.createBinaryMask(color1=(130,125,100),color2=(0,0,0) ) mask = mask.morphClose() result = img - mask.invert()

import *

result.show()

Comentários sobre o programa do slide anterior

mask = img.createBinaryMask(color1=(130,125,100),color2=(0,0,0) ) Cria uma máscara binária, usando os valores comprendidos entre color1 e color2

mask = mask.morphClose() Usa a função morphClose() para limpar o ruído restante na imagem

Motion Blur effect

Um dos truques clássicos em fotografia artística é utilizar uma exposição longa. Ao deixar o obturador da câmera aberto, ele cria um efeito de borrão, conforme os objetos se movem através do campo de Visão. Embora as câmeras web não tenham persianas para replicar diretamente esse efeito, ele pode ser simulado adicionando uma série de imagens, efetivamente criando um borrão de movimento.

from operator import add

from SimpleCV import *

cam = Camera()

frames_to_blur = 4

frames = ImageSet()

while True:

frames.append(cam.getImage())

if len(frames) > frames_to_blur:

frames.pop(0) #remove o frame mais antigo se estivermos no máximo

pic = reduce(add, [i / float(len(frames)) for i in frames])

#add =soma os frames na matriz com peso 1 / numero de frames

pic.show()

Efeito Croma-Key

Agora você vai aprender como se faz um dos efeitos de Processamento de Imagens mais utilizados na TV e no cinema: o Croma-Key.

Uma imagem de uma pessoa é filmada sobre um fundo verde (ou azul). Depois, a imagem da pessoa é recortada e é montada sobre outro fundo, que pode ser uma paisagem ou outro lugar qualquer.

ATENÇÃO: Para este script funcionar é fundamental que as duas imagens que participam da montagem tenham exatamente o mesmo número de pixels !

Chroma Key (Tela Verde)

from SimpleCV import *

sleep_time = 2

#a quantia de tempo para mostrar cada imagem

#carrega e mostra a imagem com fundo verde print "Mostrando imagem com Tela verde" greenscreen = Image("fig1.png") greenscreen.show() time.sleep(sleep_time) # carrega e mostra a imagem de fundo print "Mostrando imagem de fundo" background = Image("fig2.png") background.show() time.sleep(sleep_time) #Cria e aplica a mascara print "Mostrando imagem na mascara" mask = greenscreen.hueDistance(color=Color.GREEN).binarize() mask.show() time.sleep(sleep_time)

#Combina a mascara com a outra imagem para obter o resultado final print "Mostrando imagem final"

result = (greenscreen - mask) + result.show() time.sleep(sleep_time)

( background - mask.invert() )

Detecção de Face usando o OpenCV

Embora o SimpleCV seja mais recomendado para Raspberry PI (por ser mais leve e mais otimizado do que o OpenCV) você também pode utilizar o OpenCV na sua placa. Se você tem uma Rasp modelo I ele ficará bastante lento, mas vai funcionar. O slide a seguir é uma pequena amostra do conteúdo da próxima aula (AULA-6) e ilustra um sistema de reconhecimento de Faces baseado em OpenCV.

Classificadores

Na próxima aula abordaremos o tema “Classificadores”. Para este programa funcionar, você precisa incluir na mesma um arquivo .xml que traz os vetores característicos que permitem o reconhecimento da face. Este arquivo é chamado de haar-cascade classifier. O arquivo é o:

haarcascade_frontalface_default.xml

import cv2 arqCasc = 'haarcascade_frontalface_default.xml' faceCascade = cv2.CascadeClassifier(arqCasc)

webcam = cv2.VideoCapture(0) while True:

s, imagem = webcam.read() imagem = cv2.flip(imagem,180) faces = faceCascade.detectMultiScale( imagem,

#instancia o uso da webcam

#pega efetivamente a imagem da webcam #espelha a imagem

minNeighbors=5,

minSize=(30, 30),

maxSize=(200,200)

)

# Desenha um retângulo nas faces detectadas for (x, y, w, h) in faces:

cv2.rectangle(imagem, (x, y), (x+w, y+h), (0, 255, 0), 2)

cv2.imshow('Video', imagem)

#mostra a imagem captura na janela

#o trecho seguinte é apenas para parar o código e fechar a janela if cv2.waitKey(1) & 0xFF == ord('q'):

break

webcam.release( )

#dispensa o uso da webcam

cv2.destroyAllWindows() #fecha todas a janelas abertas