24 Nisan 2009 Cuma

Python’da Karakter Dizisi İşlemleri

(http://www.gokmengorgen.net adresinden alıntıdır.)

Geçenlerde bir arkadaşım, Python 3′te gettext modülünün nasıl kullanılacağını sormuştu, ben de henüz 3.* sürümünü denemediğim için bir cevap verememiştim. Hala da verebilecek aşamada değilim; ama bu konu üzerinde biraz araştırma yaparken, ilginç bir internet sayfasıyla[1] karşılaştım. Aşağıda paylaşacağım kodların ve bilgilerin Python 2.* serisinde çalışmaması söz konusu olabilir.

Python’da karakter dizilerini iki biçimde çağırabiliyoruz:

  • Karakter dizileri için % işleyicisi[2].

  • string.Template modülü[3]



% işleyicisiyle kullanım örneği, Python belgelerinde verilmiş:


>>> print('%(language)s has %(#)03d quot types.' % {'language': "Python", "#": 2})
#Python has 002 quot types.


Bu kodda değişkenler bir sözlük içinde eşleştirilmekte ve print çıktısında tanımlanmış değerleriyle ekrana yazılmaktadır. Bunun aynısı şu şekilde de yapabilirdik:


>>> print('%s has %03d quot types.' % ("Python", 2))
#Python has 002 quot types.


Birincisine göre daha basit olsa da, birinci kodda şöyle bir avantaj söz konusudur:

>>> print('The %(first)s variable, and the %(second)s variable.' % {'second': "New", 'first': "Old"})
#The Old variable, and the New variable.


Bu şekilde kullandığımız zaman, ikinci işleyiciyi ilk olarak tanımlayıp, ikinci işleyiciyi ise sonra tanımlayabilme fırsatımız olabiliyor. Nerelerde kullanılabileceği ayrı bir merak konusu. Bu merakı gidermeden önce bir de şu şekilde kullanıma bir bakalım:


>>> print('The {1} variable, and the {0} variable.'.format("New", "Old"))
#The Old variable, and the New variable.


İlginç, değil mi? Aslında bu kadar çeşitlilik olması garibime gidiyor; ama bu son yöntemin yüksek seviye programlama diline daha yakın bir tarz olduğunu düşünmeden edemiyorum. Yanılmıyorsam bu tip kullanım, C# ve Java’da da var. Şimdi son olarak aşağıdaki kodu inceleyelim:


import sys

class Main:
def __init__(self):
print("Python version is, {0}.".format(sys.version[:5])) # print'lerin yazimina dikkat..

digits_list = self.digits()

print("{1} is bigger than {0} as digit.".format(digits_list[0], digits_list[1]))

def digits(self):
try:
first_digit = int(input("Please write a digit: ")) # raw_input yerine input kullaniliyor.
second_digit = int(input("And second digit: "))

except ValueError:
print("\nSorry, you must enter a digit.")
exit()

return self.sort(first_digit, second_digit)

def sort(self, x, y):
return sorted([x,y])

if __name__ == "__main__":
Main()


Kodun yaptığı şey basit: Sizden iki sayı girmeniz isteniyor ve sayıları, büyüklüklerine göre {0} ve {1} ile eşleştirip, “X, Y’den sayıca büyüktür.” gibisinden bir cümle döndürüyor. Kod basit olduğu için bu tip karakter dizisi işleyicilerin faydası pek belli olmuyor; ama mutlaka bir yerde faydası vardır =). Son kodun çıktısı şu şekilde:


[gkmngrgn@gacer ~]$ python3 rank.py
Python version is, 3.0.1.
Please write a digit: 3
And second digit: 1
3 is bigger than 1 as digit.
[gkmngrgn@gacer ~]$


[1]: http://www.python.org/dev/peps/pep-3101/
[2]: http://docs.python.org/library/stdtypes.html#string-formatting-operations
[3]: http://docs.python.org/library/string.html#string.Template

27 Mart 2009 Cuma

Opencv Modülü İle Kamera Görüntüsü Alma

Bu yazımızda python, opencv modülü ve qt ile kamera görüntüsü alıp göstereceğiz, hatta resim de çekeceğiz.


# -*- coding: utf-8 -*-

from PyQt4 import QtGui, QtCore

import Image
import ImageQt
import opencv
from opencv import highgui

# kamera yakalayıcı...
camera = highgui.cvCreateCameraCapture(0)

# kamera işlemimiz sürekli olarak ekrana görüntüyü basıyor...
class camThread(QtCore.QThread):
def run(self):
while True:
# görüntüleri basarken her aralıkda 60ms bekliyoruz, buda 60fps demek...
# eğer sizde görüntü yavaş olursa yani fps yi düşürün...
self.msleep(60)
# görüntüyü alıyoruz...
self.image = highgui.cvQueryFrame(camera)

# resim sinyalini yayıyoruz ve gidecek fonksiyona self.image değişkenini,
# gönderiyoruz...
self.emit(QtCore.SIGNAL("image"), (self.image))

class camoruxWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)

self.resize(650, 450)

self.camThread = camThread()

self.showLabel = QtGui.QLabel(self)
self.showLabel.resize(640, 480)

# camThread den gelen sinyali alıyoruz ve self.showImage ye bağlıyoruz...
self.connect(self.camThread, QtCore.SIGNAL("image"), self.showImage)
self.camThread.start()

self.button = QtGui.QPushButton(self)
self.button.setText(u"Resim çek")
self.connect(self.button, QtCore.SIGNAL("clicked(bool)"), self.cek)

def cek(self):
# flash
self.flash = QtGui.QWidget()
self.flash.setStyleSheet("background-color: rgb(255, 255, 255);")
self.flash.showFullScreen()

# resim çekiliyor...
i = highgui.cvQueryFrame(camera)
opencv.adaptors.Ipl2PIL(i).save("deneme.png")

# flash kapanıyor
self.flash.close()

def showImage(self, image):
# burada: gelen resmi ImageQt ile QLabel in istediği şekile dönüştürüyoruz...
self.image = ImageQt.ImageQt(opencv.adaptors.Ipl2PIL(image).transpose(Image.FLIP_LEFT_RIGHT))
# ve gösteriyoruz...
self.showLabel.setPixmap(QtGui.QPixmap.fromImage(self.image))

app = QtGui.QApplication([])
mw = camoruxWindow()
mw.show()
app.exec_()

Dikkat etmeniz gereken nokta şu:
camThread görüntüyü gösterirken 60ms bekliyor yani 60fps ile görüntü gösteriliyor, sizde eğer görüntü yavaş olursa fps yi düşürmeniz gerekiyor demektir. 30-40 fps arası deneyin…

19 Mart 2009 Perşembe

PyGame İle İlerleme Çubuğu (ProgressBar) Yapalım

Bugün pygame ile basit bir ilerleme çubuğu yapacağız. Uzun zaman alan işlemlerde kullanıcı sıkılmasın diye ekranda sürekli ilerleyen bir çubuk görmeye alışkınsanız bunu neden biz de yapamayalım diyor olabilirsiniz. Öyleyse bu yazı size göre.

İlerleme çubuğu sınıfımız ProgressBar olacak. Bu sınıf görsel hazırlıklarını, miras aldığı ProgressImage'a yaptıracak. Kullanım için biraz ilkel olsa da başlangıç olarak basit bir yöntem seçtim. Ama bu yazının amacı sizlere pygame'i anlatmak. Kullanmanızı ve neden ben de yapmayayım demenizi sağlamak. Bu yüzden kullanılabilirlik konusunda yeterinden öte ayrıntıya girmedim.

Örneğin uzun zaman alan bir döngünüz var:

for i in range(kere):
oturanboga.konus()



Bu döngüde ProgressBar sınıfından bir nesneyi şu şekilde kullanacaksınız:

bariscubugu = ProgressBar(kere, adim, cubukboyutu, ilkrenk, sonrenk)
while not bariscubugu.isEnd():
oturanboga.konus()
bariscubugu.makestep()


Bu kadarı bile sizleri harekete geçirmiştir sanırım. Şimdi yapıma geçelim :)

Önce meşhur modülümüzü import edelim ve bakalım internetten indirmiş misiniz ya da pisi paket yöneticinizden yüklemiş misiniz:


import sys
try:
import pygame
except ImportError:
print '''
This Program Needs Pygame module to be installed.
For windows you can download it from this adress:
http://pygame.org/ftp/pygame-1.8.1release.win32-py2.5.msi
For linux this adress will be helpful:
http://pygame.org/ftp/pygame-1.8.1release.tar.gz
'''
sys.exit(0)


Burada try bloğu içinde yer alan ifade("import pygame") test edilir; hata varsa except bloğunda verilen hataya bakılır. Hatalar uyuşuyorsa except bloğu çalıştırılır; traceback ile başlayan soğuk cümleler yerine bizim programımızda yer alan kullanıcı dostu arkadaş cümleler kullanılabilir ve kullanıcının yüreği ferah tutulmuş olur.

Kök sınıfımız(miras veren sınıf) ProgressImage'ı yazmaya başlayalım:


class ProgressImage:
def __init__(self, size, initcolor, barcolor):
pygame.display.init() #1.
self.screen = pygame.display.set_mode(size) #2.
self.bar = pygame.Surface((size[0]-10,size[1]-10)) #3.
self.bar.fill(initcolor) #4.
pygame.display.update(self.screen.blit(self.bar, (5,5))) #5.

def quit(self):
pygame.display.quit()



  1. Bu sınıfı iyi inceleyelim. Pygame bilenler ne yapıldığını aşağı yukarı anlayacaklardır ama bilmeyen ya da az bilenler için açıklayalım:
    pygame.display.init() satırı display modülünü başlangıçlandırır. Değer döndürmez. Bu metod kullanılmadan önce pygame.display.SDL_VIDEODRIVER ortam değişkeninin -eğer isteniyorsa- değiştirilmesi mümkündür. Böylece kullanılacak video sürücüsü seçilebilir. (Ayrıntı için bakınız)

  2. pygame.display.set_mode() metodu görüntüyü ayarlar ve 3 argüman alır. Bize sadece iki tanesi hatta biri gerekecek. İlk argüman genişlik ve yükseklik değerlerini içeren bir sabit listedir.(tuple) Burada (genislik, yukseklik) şeklinde geçecektir. İkinci argüman flags parametresidir. Bu da görüntü modunu seçmeye yarar. Kodumuzda size parametresiyle yetinilmiştir. Bu metod geriye bir Surface nesnesi döndürür.

    • Surface görüntüleri pixeller halinde saklayan bir nesnedir.
    • Yeni bir nesne oluştururken tual = pygame.Surface((100,100)) şeklinde kullanılabilir. Bu tual isminde bir yüzey nesnesi oluşturacaktır.
    • Örneğimizde self.screen = pygame.display.set_mode(size) kodu screen isminde bir Surface nesnesini display modülünün ilk kez oluşturduğu ana ekrandan almaktadır.
    • screen artık ana ekrana referans etmektedir.


  3. self.bar = pygame.Surface((size[0]-10,size[1]-10))
    satırında da az önce gördüğümüz gibi bir Surface nesnesi yaratılmaktadır. Bu nesneyi screen ana ekranının üzerine çizeceğiz; çünkü bu nesne göstergemizin görüneceği nesne olacak(siz buna katman(layer) da diyebilirsiniz). Göstergenin boyutu screen nesnesinin boyutuna göre 5 piksel içerde görünecek.

  4. self.bar.fill(initcolor) satırında elde ettiğimiz bar isimli yüzey nesnesini initcolor rengiyle dolduruyoruz. Burada color hakkında şunu söylemeliyim: Kırmızı(red), Yeşil(green), Mavi(blue) değerlerini 0-255 değerleri arasında içeren bir üçlü sabit listedir color. (0,0,255) gibi(mavi)

  5. pygame.display.update(self.screen.blit(self.bar, (5,5))) satırında önce pygame.display.update() metoduna verilen parametreye bakalım.

    • self.screen.blit(self.bar, (5,5)) komutu bar nesnesini screen nesnesinin üzerine çizer. Ama bunu ekrana yansıtmaz. Dikkat: nesneleri üstüste bindirir ancak görüntünün oluşması için update() metodu çalışmaldır.
    • Bu metod yani blit() metodu Rect döndürür. Bu bar nesnesinin kapladığı dikdörtgen alanın koordinatlarını içeren başka bir nesnedir ki tahmin edeceğiniz gibi pygame.display.update() metodu Rect alır.
    • Sonuç olarak yaptığımız ana ekran nesnesi olan screen'in üzerine bar nesnesini yanlızca kapladığı alan içinde bindirmektir. Bu bütün ekranı güncellemekten daha hızlı bir metoddur.



Bu kadarı pygame için yeterli sanırım şimdi programı huzurlarınıza sunuyorum. Sizde programı dilediğiniz gibi kopyalayıp kendi başınıza birşeyler deneyebilirsiniz.


import sys
try:
import pygame
except ImportError:
print '''
This Program Needs Pygame module to be installed.
For windows you can download it from this adress:
http://pygame.org/ftp/pygame-1.8.1release.win32-py2.5.msi
For linux this adress will be helpful:
http://pygame.org/ftp/pygame-1.8.1release.tar.gz
'''
sys.exit(0)

class ProgressImage:
def __init__(self, size, initcolor, barcolor):
pygame.display.init()
self.screen = pygame.display.set_mode(size)
self.bar = pygame.Surface((size[0]-10,size[1]-10))
self.bar.fill(initcolor)
pygame.display.update(self.screen.blit(self.bar, (5,5)))

class ProgressBar(ProgressImage):
def __init__(self, whole, step, size, initcolor, barcolor):
ProgressImage.__init__(self, size, initcolor, barcolor)
self.size = size
self.initcolor = initcolor
self.barcolor = barcolor
self.whole = whole
self.step = step
if whole < step:
print "Error: ProgressBar length can't be smaller than step"
sys.exit(1)
self.slice = float(step)/float(whole)
self.percent = 0.0

def showprogress(self):
self.screen.fill(self.initcolor)
barwidth = (self.size[0]-10)*self.percent
barheight = self.size[1]-10
self.bar = pygame.Surface((barwidth,barheight))
self.bar.fill(self.barcolor)
pygame.display.update(self.screen.blit(self.bar, (5,5)))

def reset(self):
self.percent = 0.0
self.showprogress()

def makestep(self):
if self.percent < 1.0:
self.percent += self.slice
self.showprogress()

def quit(self):
pygame.display.quit()

def isEnd(self):
if self.percent<=1.0:
return False
else:
return True

if __name__ == "__main__":
pb = ProgressBar(1000, 10, (100,40), (255,255,255), (0,0,255))
i, j, k = 0, 0, 0
while not pb.isEnd():
temp = "running.."
for j in range(5):
for k in range(5):
print temp
pb.makestep()
pb.quit()


progressbar.png
Hepinize kolay gelsin :)