Rafael Lopes'

almost a blog

Montage With Opencv and Numpy

Permalink

With numpy and opencv one can easily concatenate images:

montage.py download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
import sys
import cv2
from numpy import r_, concatenate




def main():
    imgs  = []
    for fname in sys.argv[1:]:
        imgs.append(cv2.imread(fname))

    montage = concatenate(imgs, 0)
    cv2.imwrite('montage_vertical.png', montage)


    montage = concatenate(imgs, 1)
    cv2.imwrite('montage_horizontal.png', montage)

if __name__ == '__main__':
    main()

Using slices, it is possible to show each channel of color as a separate image:

channels_montage.py download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python
import sys
import cv2
from numpy import r_, concatenate

def main():
    img = cv2.imread(sys.argv[1])

    b = img.copy()
    b[:,:,1] = 0
    b[:,:,2] = 0


    g = img.copy()
    g[:,:,0] = 0
    g[:,:,2] = 0

    r = img.copy()
    r[:,:,0] = 0
    r[:,:,1] = 0

    montage = concatenate((b,g,r), 1)
    cv2.imwrite('montage_channels.png', montage)

if __name__ == '__main__':
    main()

Dilma Discurso Generator

Permalink

No post anterior fiz um robô para capturar mais de 260 discursos da presidente Dilma. Usando o excelente nltk criei um modelo para gerar discursos artificiais:

O sistema tem falhas. Se alguém pede asilo em uma condição muito melhor as múltiplas vozes da democracia , quero dar um salto e um parceiro de tantas jornadas conjuntas , elas terão um convívio com o incentivo , o dever de afirmar para todos e de intercâmbio que traduzam a meta corajosa e criativa para dar um exemplo de transporte urbano seja de fato , um país nessa imensa força construtiva que é organizada pelo partido.

resultado do Dilma Discurso Generator
discurso_generator.py download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
import nltk
import numpy
import codecs
import sys

def main():
    raw = codecs.open(sys.argv[1]).read()
    tokens = nltk.word_tokenize(raw)
    text = nltk.Text(tokens)
    estimator = lambda fdist, bins: nltk.probability.LidstoneProbDist(fdist, 0.2)
    model = nltk.NgramModel(3, text, estimator=estimator)
    first_words =  model.generate(42)[-2:]
    print ' '.join(model.generate(50, first_words))


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print "USO: %s arquivo_texto" % sys.argv[0]
    else:
        main()

Neste modelo, a i-ésima palavra do texto gerado depende somente das últimas duas palavras. Usei uma distribuição chamada Lidstone para sortear cada possível próxima tripla. Interessantemente essa distribuição “finge” ter amostrado umas triplas que não estavam na amostra dando alguma chance de uma tripla não existente no texto original aparecer no gerado.

Arquivo de discursos: discursos.txt.

Coletando 260 Discursos Da Presidente Dilma

Permalink

Brincando com o BeautifulSoup fiz um robozinho para coletar todos os discursos da presidente Dilma Rousssef. Ao todo, do discurso inaugural aos últimos no Rio+20, são 260 discursos.

Fica como exemplo de web scraping.

webscraping_discursos_dilma.py download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/usr/bin/env python
from BeautifulSoup import BeautifulSoup
import urllib2,sys
import codecs

ADDRESS = 'http://www2.planalto.gov.br/imprensa/discursos?b_start:int=0'

def prox_pagina(soup):
    '''
    Itera pelas paginas do site do planalto usando o link no paginador.
    '''
    try:
        span_next = soup.find('span', {'class':'next'})
        href = span_next.first()['href']
        print href
        html = urllib2.urlopen(href).read()
        return BeautifulSoup(html)
    except Exception:
        return None



def parse_discurso_texto(href):
    '''
    Procura pelo texto do discurso. Separa os paragrafos por um new line.
    '''
    print href
    html = urllib2.urlopen(href).read()
    soup =  BeautifulSoup(html)
    #os paragrafos ficam dentro de um div com id parent-fieldname-text
    text = [p.text for p in soup.find(id='parent-fieldname-text').findAll('p')]
    text = '\n'.join(text)
    return text + '\n'



def main():
    #abre a pagina da internet
    html = urllib2.urlopen(ADDRESS).read()
    #inicializa o parser do html lido
    soup = BeautifulSoup(html)
    #abre arquivo onde salvar os discursos
    f = codecs.open('discursos.txt', 'w', "utf-8")
    while(soup):
        #os links dos discursos ficam nas tags a com classe summary url
        discursos = soup.findAll('a', {'class':'summary url'})
        discursos = [d['href'] for d in discursos]
        for d in discursos:
            t = parse_discurso_texto(d)
            f.write(t)
        soup = prox_pagina(soup)
    f.close()


if __name__ == '__main__':
    main()

A Simple Bottom-up Saliency Model in Python Opencv

Permalink

In my research, I’m trying several models of saliency. The saliency of a point of a given image can be defined as a measure of attention it (the point) demands from a human looking at the image performing a given task. Like the girl in red from Schindlers List.

The Achanta, Hemani, Estrada and Susstrunk method is simple to implement and perform very well.

In simple words, our method find the Euclidean distance between the Lab pixel vector in a Gaussian filtered image with the average Lab vector for the input image.

frequency_saliency.py download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env python
import cv2
import numpy
import sys

if __name__ == '__main__':
    if len(sys.argv) > 1:
        img  = cv2.imread(sys.argv[1])
    else:
        cam = cv2.VideoCapture(0)
        status, img = cam.read()

    img = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
    #mean of each channel
    m = numpy.asarray([img[:,:,0].mean(), img[:,:,1].mean(), img[:,:,2].mean()])
    img = cv2.medianBlur(img, 9)
    dist = (img - m)**2
    print("mean color is %s"% m)
    salmap = numpy.zeros((dist.shape[0], dist.shape[1]))
    for l in range(dist.shape[0]):
        for c in range(dist.shape[1]):
            salmap[l][c] = numpy.sqrt(dist[l][c].sum())
    #minmax normalization
    salmap = (salmap -salmap.min())
    salmap = salmap/salmap.max()
    salmap = 255*salmap
    salmap = salmap.astype(numpy.uint8)
    cv2.imwrite('saliency.png', salmap)
    cv2.waitKey()

One thing from this code that can be useful in other contexts is the numpy idiom to get a single channel of the image. To get the first channel:

 img[:,:,0]

To see more about take a look at numpy indexing docs.

Snippet: Comparing Histograms of Images With C++ Opecv

Permalink

This code shows how to compare the hue and saturation histograms of two images in OpenCV c++.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
Compares the HSV histograms of two images, a and b.
Return the norm  between 
*/
double compare_histograms(Mat a, Mat  b) {
    MatND  hista, histb;
    Mat a_hsv, b_hsv;

    //args to calculate the histogram
    int channels[] = {0, 1};
    //180 bins for hue and 256 bins to saturation
    int histsize[] = {180, 256};
    //distribution uniform by the bins
    float hrange[] = {0, 180};
    float srange[] = {0, 256};
    const float * ranges[] = {hrange,srange};

    //Convert images to HSV from BGR
    cvtColor(a, a_hsv, CV_BGR2HSV);
    cvtColor(b, b_hsv, CV_BGR2HSV);

    //Calculates the histogram of the two images
    calcHist(&a, 1, channels, Mat(), hista, 2, histsize, ranges);
    calcHist(&b, 1, channels, Mat(), histb, 2, histsize, ranges);

    //Return the norm
    return norm(hista, histb);
}

Simulating Colorblindness With Python Opencv

Permalink

Like the sepia filter from the last post, one can simulate color vision deficiency using linear transformations over the RGB color space.

The left is the original picutre (Palmeiras vs Internacional soccer teams). The right image is a protanomalous simulation.

With a similar code and the method of Machado et al. with pre-calculated matrix the following code simulate protanomalous color vision.

protan.py download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
import cv2
import numpy
import sys

if __name__ == '__main__':
    if len(sys.argv) > 1:
        img  = cv2.imread(sys.argv[1])
    else:
        cam = cv2.VideoCapture(0)
        status, img = cam.read()

    m_protan = numpy.asarray( [[0.259411, 0.923008,  -0.182420],
                               [0.110296, 0.804340,  0.085364 ],
                               [-0.006276, -0.034346,  1.040622 ]])

    img = cv2.cvtColor(img, cv2.cv.CV_BGR2RGB)
    protan = cv2.transform(img, m_protan)
    protan = cv2.cvtColor(protan, cv2.cv.CV_RGB2BGR)
    cv2.imshow('protan', protan)
    cv2.imwrite('protan.png', protan)
    cv2.waitKey()

Making Sepia Images With Python Opencv

Permalink

A Sepia filter can be described by a linear transformation over the color space of an image:

where is a matrix 3x3 and is a RGB color vector of the i-th pixel of the image. The values of are (as taken from here).

The OpenCV offers a function to apply a matrix over each pixel of an image. I make use of it in the following code.

sepia.py download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python
import cv2
import numpy
import sys

if __name__ == '__main__':
    if len(sys.argv) > 1:
        img  = cv2.imread(sys.argv[1])
    else:
        cam = cv2.VideoCapture(0)
        status, img = cam.read()

    m_sepia = numpy.asarray([[0.393, 0.769, 0.189],
                             [0.349, 0.686, 0.168],
                             [0.272, 0.534, 0.131]])
    sepia = cv2.transform(img, m_sepia)
    sepia = cv2.cvtColor(sepia, cv2.cv.CV_RGB2BGR)
    cv2.imshow('sepia', sepia)
    cv2.imwrite('sepia.png', sepia)
    cv2.waitKey()