Nümerik işlemler ve bilgisayarla görmek için Python

Uzun süredir nümerik hesaplarım için IPython kabuğu ile Python’ın numpy modülünü kullanıyorum ve çok memnunum. Hele Opencv’nin güzel sürümündeki (svn’deki sürümü oluyor) matris yapısını numpy dizisine (ndarray) çevirebilince işlem kolaylığı ve çokluğu arttı, daha da şık oldu.

Bunun ne faydası var konusunda bir fikir vereyim. Opencv, içinde birçok bilgisayarla görme algoritmasını barındıran muhteşem bir açık kaynak kütüphane. Numpy, Matlab’ın Python muadili. Numpy neredeyse standart oldu ve tüm nümerik kütüphaneler onu destekliyor. Benim kullandığım en temel kütüphaneler grafik kütüphaneleri (matplotlib gibi) de Numpy destekli. Numpy’ın en güçlü yanı, dilimleme (“slicing”) operatörü. Matlab kullananlar bunu bilir ve sever. Ayrıca işleri vektörlemek de mümkün. Kullanımı çok esnek. Opencv’de hazır fonksiyonları kullanmak çok kolay ama resimlerden istatistik falan toplayacaksanız işiniz Numpy sözdiziminde olduğu kadar kolay değil. Böyle bir çevirme işlemiyle ikisinin gücü birleşiyor. Bu arada, tüm bahsettiğim kütüphaneler platformdan bağımsız.

Şu anlık yalnızca float32 ve uint8 veri türlerini çevirdim.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def opencv2numpy(matIn):
    """Convert opencv matrix to numpy matrix (supports 1 and 3 channels currently)"""
    if matIn[0].type == cv.CV_8UC1 or matIn[0].type == cv.CV_8UC3:
        dtype = 'uint8'
    elif matIn[0].type == cv.CV_32FC1 or matIn[0].type == cv.CV_32FC3:
        dtype = 'float32'
    else:
        print "No support except float32 and uint8 yet"
        return 0
 
    if matIn[0].type == cv.CV_8UC3 or matIn[0].type == cv.CV_32FC3: 
        matOut = np.fromstring(matIn.tostring(), dtype=dtype).reshape(matIn.height, matIn.width, 3)
    else:
        matOut = np.fromstring(matIn.tostring(), dtype=dtype).reshape(matIn.height, matIn.width)
 
    return matOut
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
def numpy2opencv(matIn):
    if matIn.ndim == 3 and matIn.shape[2] == 3:
        nChannels = 3
    else:
        nChannels = 1
 
    h,w = matIn.shape[0], matIn.shape[1]
    if matIn.dtype == "uint8":
        if nChannels == 1:
            dtype = cv.CV_8UC1
        else:
            dtype = cv.CV_8UC3
    elif matIn.dtype == "float32":
        if nChannels == 1:
            dtype = cv.CV_32FC1
        else:
            dtype = cv.CV_32FC3
    else:
        print "No support except float32 and uint8 yet"
        return 0
 
    matOut = cv.CreateMatHeader(h, w, dtype)
    if nChannels == 1:
        cv.SetData(matOut, matIn.data, w*matIn.itemsize)
    else:
        cv.SetData(matOut, matIn.data, w*4*matIn.itemsize)
 
    return matOut

Güncel işimi görmesi için yazdığımdan hataları olabilir, biraz da verimsiz oldu. Örneğin bir tarafa iyiyken, diğer tarafa verimsiz çeviriyor. Fakat benim için şu an bu öncelik konusu değil. “Exception” fırlatmam lazım ama hariçten gazel okumak zor geldi, işimi görüyor.

Kullanırsanız, genellerseniz veya geliştirirseniz lütfen benimle de paylaşın.

Güncelleme:

Opencv Python arayüzünde zaten hazırmış bu kod. Hem diğer veritipleri için de genellenmiş. Yenisi dönüşümler şöyle:

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
def cv2array(im):
    depth2dtype = {
        cv.IPL_DEPTH_8U: 'uint8',
        cv.IPL_DEPTH_8S: 'int8',
        cv.IPL_DEPTH_16U: 'uint16',
        cv.IPL_DEPTH_16S: 'int16',
        cv.IPL_DEPTH_32S: 'int32',
        cv.IPL_DEPTH_32F: 'float32',
        cv.IPL_DEPTH_64F: 'float64',
    }
 
    arrdtype=im.depth
    a = np.fromstring( im.tostring(), 
                              dtype=depth2dtype[im.depth], 
                              count=im.width*im.height*im.nChannels)
    a.shape = (im.height,im.width,im.nChannels)
    return a
 
def array2cv(a):
    dtype2depth = {
        'uint8':   cv.IPL_DEPTH_8U,
        'int8':    cv.IPL_DEPTH_8S,
        'uint16':  cv.IPL_DEPTH_16U,
        'int16':   cv.IPL_DEPTH_16S,
        'int32':   cv.IPL_DEPTH_32S,
        'float32': cv.IPL_DEPTH_32F,
        'float64': cv.IPL_DEPTH_64F,
    }
    try:
        nChannels = a.shape[2]
    except:
        nChannels = 1
    cv_im = cv.CreateImageHeader((a.shape[1], a.shape[0]), 
                                                dtype2depth[str(a.dtype)], 
                                                nChannels)
    cv.SetData(cv_im, a.tostring(), 
    a.dtype.itemsize*nChannels*a.shape[1])
    return cv_im
Bu yazı Programlama kategorisine gönderilmiş ve , , ile etiketlenmiş. Kalıcı bağlantıyı yer imlerinize ekleyin.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*

Şu HTML etiketlerini ve özelliklerini kullanabilirsiniz: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">