Monday, March 29, 2010

3d Nokta Ilerletmek (translation)

3d boyutlarda belli kordinattaki bir noktanin degerlerini herhangi bir eksen uzerinde arttirmak / azaltmak istersek, tercume matrisi (translation matrix) kullanmak lazim. Konunun detaylari 3d grafik programlama kitaplarinda bulunabilir; Alttaki ornek 10,10,10 kordinatindaki bir noktayi 10,10,0 noktasina hareket ettiriyor, z kordinatini 10 kadar azaltiyor.
from mpl_toolkits.mplot3d import Axes3D
from pylab import *

fig=plt.figure()
ax = Axes3D(fig)


p = [[10],[10],[10], [1]]
ax.plot(p[0], p[1], p[2], 'o')

T = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, -10],
[0, 0, 0, 1]]

print p
p = dot(T, p)
print p
ax.plot(p[0], p[1], p[2], 'x')

plt.show()

Wednesday, March 24, 2010

Obje Yansitmak

Uc boyutlu kordinat sistemindeki bir objeyi, noktayi alip onu iki boyuta yansitma isi kamera matrisi uzerinden yapiliyor. Bu matris kamera kalibre edilirken uretilen 3x3 boyutunda bir matristir. Test icin alttaki OpenCV Python kodunu paylasalim; bu kod 20x20 boyutlarindaki bir hayali "kup" icin noktalar uretiyoruz ve bu noktalari teker teker kamera matrisi K ile carparak onlari 2 boyutlu piksel konumlarina yansitiyoruz. Carpim sonucu ele gecen sayilar 3x1 boyutunda olacak, fakat bu sayilar homojen kordinatlar, sonuncu (ucuncu) kordinat 1 ya da katlari olmali / olabilir, o zaman 1 sayisina erismek icin 1. ve 2. kordinat degerine sonuncuya boluyoruz, piksel degerlerini aliyoruz.

Test icin xl, yl, zl degerleri ile oynanabilir, ve yesil renkle boyanan kup seklinin resim uzerinde degisik yerlere kondugu gorulebilir. K sayisini herkesi kendi kamerasina gore OpenCV kalibrasyonundan hesaplatmasi gerekiyor. Alttaki K degeri bizim kamera icin.
import cv
from pylab import *

K = array([[653.52398682, 0., 326.47888184],
[0., 653.76440430, 259.63595581],
[0., 0., 1.]])

color = cv.RGB(0, 255, 0)

cv.NamedWindow("win")
im = cv.LoadImage("[HERHANGI BIR JPG RESIM]", cv.CV_LOAD_IMAGE_COLOR)
image_size = cv.GetSize(im)
print image_size[0]
print image_size[1]

xl = -90
yl = -50
zl = 200

for x in arange(xl, xl+20):
for y in arange(yl, yl+20):
for z in arange(zl, zl+20):
X = array([x, y, z])
q = dot(K, X)
real_q = [q[0]/q[2], q[1]/q[2]]
i_real_q = [int(real_q[0]), int(real_q[1])]
if i_real_q[0] < image_size[1] and i_real_q[1] < image_size[0]:
cv.Set2D(im, i_real_q[0], i_real_q[1], color)

cv.ShowImage("win", im);
k = cv.WaitKey()

Sunday, March 21, 2010

Android ve Liste Secimi (Dropdown List)

Telefonde secenekli liste sunmak icin layout
    <Spinner android:id="@+id/spinner1"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:drawSelectorOnTop="true"
/>
Activity icinde gerekli Java kodu
Spinner s1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
s1 = (Spinner) findViewById(R.id.spinner1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this, android.R.layout.simple_spinner_item, mStrings);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s1.setAdapter(adapter);
}

private static final String[] mStrings = {
"deger1", "deger2", "deger3"
};
Secilen bir degerin ne oldugunu okumak icin herhangi bir Listener icinde s1.getSelectedItem() cagrisi degeri gerekli degeri getirecektir.

Thursday, March 18, 2010

GAE Tabanina Veri Yuklemek

Google App Engine ortaminda uygulama icin gereken bazi baslangic verileri olabilir. Bu verileri disaridan GAE'ye dahil etmek icin toptan yukleyici olarak "appcfg.py upload_data" kullanilabilir. Bu komut ile duz dosyayi GAE tabanina toptan (bulk) olarak gondermek mumkun. Fakat bundan once duz dosyadaki her satirin bir objeye nasil tekabul ettigini tanimlamamiz gerekiyor.

GAE veri tabani bir anahtar/deger tabani (key/value store). Bu tur tabanlar hakkinda birkac yazi yazdik; bir nevi Hash dictionary'nin dagitik calisan versiyonu olan bu tabanlar devasa boyutlarda yuk olan Web ortamlarin demirbasi haline geldi. Amazon, Facebook, Friendfeed hep benzer yaklasimlari kullaniyorlar.

GAE ortamindaki Bigtable teknolojisi Google'in kendi urunleri icin de kullandigi taban (Gmail gibi). Bulut kavraminin, ozellikle Google ortaminda oldugu gibi idareli ve tanimli bir ortam icin, onemli bir avantaj sudur. Tabana yazarsiniz, ve isin olceklenmesiyle hic ilgilenmezsiniz. Eger verinin kopyalanmasi gerekiyorsa (mesela cografi lokasyana gore, kullaniciya daha yakin bir makinaya veri yakin olacaksa), taban onu arka planda yapar. Yedeklemeyi yapar. Olceklemeyi yapar. Programci sadece get(), put() komutlariyla ugrasir. Veri yuklemeye gelelim. app.yaml dosyasinda
handlers:
- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin
tanimini eklemeniz lazim. Duz dosyadaki ve veri tabanindaki kayiti, class'i soyle tanimlariz. Mesela bir models.py dosyasi icinde
from google.appengine.ext import db

class Txn(db.Model):
code = db.StringProperty()
date = db.DateProperty()
low = db.FloatProperty()
high = db.FloatProperty()
price = db.FloatProperty()
increase = db.FloatProperty()
volume = db.FloatProperty()
Sonra loader.py adli bir class icinde
import datetime
from google.appengine.ext import db
from google.appengine.tools import bulkloader
from models import *

class TxnLoader(bulkloader.Loader):
def __init__(self):
bulkloader.Loader.__init__(
self, 'Txn',
[('code', str),
('date', lambda x: datetime.datetime.strptime(x, '%Y%m%d').date()),
('low', float),
('high', float),
('price', float),
('increase', float),
('volume', float)
])


loaders = [TxnLoader]
Eger Python yukleme cevre degiskenini degistirmek istemiyorsak, o zaman
import sys
sys.path.append('[GELISTIRME DIZINI]')
ibaresini de kullanmak gerekecek.

Verileri gelistirme ortamina yuklemek icin dev_appserver.py baslatiriz, ve
appcfg.py upload_data --config_file=loader.py --filename=[VERI DOSYASI]
--kind=Txn --url=http://localhost:8080/remote_api [GELISTIRME DIZINI]
komutunu kullaniriz. Sonuc ortamina yuklemek icin once "appcfg.py update" ile kodlari gondeririz, sonra
appcfg.py upload_data --config_file=loader.py --filename=[VERI DOSYASI]
--kind=Txn [GELISTIRME DIZINI]

Wednesday, March 17, 2010

Mysql Veri Ihraci (Export)

select * from [TABLO ISMI] into outfile '[DOSYA ISMI]' FIELDS TERMINATED BY ','

Sunday, March 7, 2010

Google App Engine

Android mobil uygulamamiz icin bazi servis tarafi ekler gerekince, test olarak Google App Engine'i (GAE) denedik. GAE'nin Amazon EC2'den farki belli kendine has API'lar uzerine kurulmus olmasi, Web uygulamalari Google'in sagladigi fonksiyonlarla calismali. GAE Java dilini destekliyor, fakat biz Python kullanmaya karar verdik. Gelistirme daha hizli oldu, Python dilinin esnekligi faydali oldu. Mevcut cozum yelpazemiz, telefon / client uzerinde Java, servis tarafinda Python + GAE yonune dogru evriliyor.

Ozelde GAE + Python ile, genelde "bulut" kavrami ile servis tarafi kodlamasi kolaylasmis. En basit servis Python kodu bir CGI islemcisi (daha cetrefil, taslak HTML bazli Web kodlamasi icin Django altyapisi destekleniyor), request uzerinden alinan bilgi islenip response uzerinden cikti verebilen turden. Boyle bir kod, bir ayar dosyasi, bir tane Python dosyasi uzerinden yapilabiliyor. Script bir main() cagrisi aslinda, CGI mentalitesine gore Web Server (Apache gibi) istegi alir, (eskiden) C ile yazilmis bir main islerkodu (executable) isletir, ve sonuc o script icinde uretilirdi. Yorumlanan dillerde daha esnek olunabiliyor tabii, tum script onbellege tasinabiliyor, bu sayede script seviyesinde (scope) olan her degisken onbellege alinmis oluyor. Bizim kodun hazirlik olarak uzun bir dosyayi isleyip sonucu hash olarak tutmasi gerekiyordu, bunu script seviyesinde bir degisken ile hallettik. Dosya okumasi bir kere yapildi, ardindan tum islemler hash ile calisti.

Gelistirme icin suradan Python SDK indirilebilir

http://code.google.com/appengine/downloads.html

Dosyayi indirip acinca, appcfg.py ve dev_appserver.py gibi dosyalar goruluyor. Gelistirme yapmak icin bir gelistirme dizini acip, orada app.yaml adli bir dosya yaratmak lazim. Bu uygulamanizi tarif eden bir dosya. Icerigi cok basit:
application: [UYGULAMA ISMI]
version: 1
runtime: python
api_version: 1

handlers:
- url: /images
static_dir: images
- url: .*
script: main.py
Ana CGI script main.py, ki bu script'e en ust dizin / uzerinden hemen erisilebilir, images adinda statik dosyalar iceren bir dizinimiz var. Not: Statik dosyalarda 3000 sinirinin uzerine cikilamiyor. Google GAE sisteminin bir dosya paylasma aracina donusmesini istemiyor herhalde. Her durumda, bu rakam herhangi bir uygulama icin yeterli bir rakam.

Gelistirme sureci soyle baslatilir:

python dev_appserver.py [GELISTIRME DIZINI]

Ornek bir kod soyle olabilir:
import cgi
import logging
import wsgiref.handlers
from google.appengine.ext import webapp

class MainPage(webapp.RequestHandler):

def get(self):
astro = self.request.get('param1')
logging.debug("....")
...
self.response.out.write('[HTML BURAYA]')

logging.getLogger().setLevel(logging.DEBUG)

application = webapp.WSGIApplication([
('/', MainPage),
], debug=True)

def main():
wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
main()
Ustteki kod param1 adinda bir parametreyi URL'den okur ve HTML ureterek bunu response olarak gonderir, arada loglama yapar. Gelistirme / test sureci Java ortamindan daha iyi, Python kodunu degistirdiginiz anda degisiklikler hemen kullanima giriyor, servisi tekrar baslatmak gerekmiyor.

GAE sonuc ortaminda kullanim / performans acisindan su nokta onemli: Bir servis sureci "baslatmiyoruz", ihtiyaca gore bulut script'i cagiriyor veya cagirmiyor. Ortam konumsuz (stateless) bir ortam, arda arda iki cagri, ayni kullanicidan gelse bile degisik server makinalara gidebilir, bu yuzden konum bilgisi veri tabani ya da onbellek uzerinde tutulmali. Dert degil.

Surec idaresinin bulutta olmasi, ekonomik ayni zamanda. Eger uygulamayi kullanan yoksa, cagri yapilmaz, ve degerli mikroislemci zamani, bellek yeri heba edilmis olmaz.

Bir diger sinir, bir request / response dongusunun 30 saniye uzerine cikamamasi. Eger bu olursa, izleyici bir program istegi otomatik olarak iptal ediyor. Kontrollu bir ortam olan bulutta bunun yapilmasi da mantikli, hem sistemin isleyisi, hem de istismar amacli kullanabilecek kisiler baglaminda. Servis bir Web ortami, ve 30 saniyeden fazla surecek bir islem ne kullanici, ne de servisci acisindan anlamli bir islemdir.

Gelistirme boyle. Gelistirme bitince, uygulamayi Google'da kayit etmek lazim.

https://appengine.google.com/

adresine gidip kullanici programini kayit eder. Kodu servis tarafina gondermek icin

python appcfg.py update [GELISTIRME DIZINI]

Script appcfg.py program ismini nereden biliyor? app.yaml icinde yazili. Bu update islemi kodlarinizi, dosyalarinizi alip sonuc ortamina gonderiyor. Bir kere Google hesabiniz email ve sifre ile kontrol ediliyor (bir dahaki seferde edilmeyecek) ve kod sonuc ortamina gonderiliyor. Uygulama artik [UYGULAMA ISMI].appspot.com uzerinden cagrilabilir.

Veri tabani icin de durum ayni; kontrollu bir ortam, tabanin dosyalarini nerede tuttugu, nasil dagittigi programciyi ilgilendirmiyor. Google API uzerinden veri depolama, okunma yapildigi takdirde, verinin dagitimi, erisiminin olceklenmesi GAE tarafindan hallediliyor.

Gelistirme sirasinda log mesajlarini dev_appserver.py baslattiginiz ekranda goreceksiniz. Sonuc ortaminda ise log mesajlarina uygulamanizin admin konsolundan erisebilirsiniz.

Fiyatlandirma baglaminda, GAE ayda 5 milyon sayfa altindaki kullanimlar icin bedava. Bu rakam ufak olcekli bir uygulamayi idare eder, bundan daha fazlasi oldugu durumda ya uygulama kar etmeye baslamistir, ya da bir sekilde sponsor edilebilecek durumdadir. Fakat bedava bir baslangic yolunun olmasi iyi, ve Web girisimci mentalitesine uygun. Denemek bedava, cunku Web dunyasinda bazen pek cok deney gerekebiliyor.

Wednesday, March 3, 2010

WebView ve CSS

WebView class'i ile Android telefonlarda, Internet'e cikmaya gerek kalmadan apk dosyasi icine gomulebilecek statik html gosterebildigimizi isledik. WebView aslinda tam tekmilli bir tarayici. Bu yuzden goruntuye CSS uzerinden stil uygulayabilme yetenegine de sahip. CSS kullanimi icin css stil dosyamizi daha once bahsettigimiz HTML dosyalarinin gittigi assets/ altina birakiriz, ve HTML dosyalarimizin basinda hepimizin bildigi "link rel" komutunu uygulayarak css dosyasina referans veririz. CSS dosyasinin dizin olarak yeri neresidir? assets/ altina birakilan dosya, file:///android_asset/ diye baslamali, o zaman style.css kullanimi icin ... link rel= .. href="file:///android_asset/style.css .. diye giden bir kullanimdan bahsediyoruz. Bu kadar.

Tuesday, March 2, 2010

Telefonda HTML

Mobil ortamda HTML apk paketi icinde yeralan HTML icerigi gostermek icin Android API icindeki WebView class'i kullanilir. Duz metni suslemek icin Android icinde API kullanmak yerine, tur islerin tamamini HTML'de yapabiliriz; boylece yeni bir paket ogrenmeye gerek kalmaz. Tanidik bildik etiketler metin suslemek icin kullanilabilir.

APK icinde html dahil etmek icin bu dosyalari en ust seviyede assets/ adli bir dizine koymak yeterli. Bundan sonra bu dosyalara android_asset adindaki bir referanstan kod icinde erisebiliyorsunuz. Ornek.html adindaki bir dosya soyle gosterilebilir:

public class DetailView extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
WebView webview = new WebView(this);
setContentView(webview);
webview.loadUrl("file:///android_asset/ornek.html");
}
}

Monday, March 1, 2010

Bekleme Isareti (ProgressDialog)

Android programimiz baslarken, ya da daha sonraki ekranlarda cok zaman alabilecek bir islem yaparken kullaniciya bir tur bekleme mesaji gostermek iyi olur (yoksa kullanici programin kitlendigini, calismadigini zannedebilir). Eger Activity class'imiz onCreate metotu icinde bir ProgressDialog yarattiysak, bu dialogun is isten gectikten sonra calistigini gorurduk. Sebep, UI thread yapisinda gizli, ozet olarak ekrandaki goruntuler onCreate bitmeden ekranda resmedilmiyor; bizim daha once calismasini bekledigimiz ProgressDialog dahil.

Burada kullanilan numara, su olacak. onCreate sadece ProgressDialog ve (islemini beklemediginiz) turden bazi GUI elementlerini yaratacak, ve hemen arkasindan bir Thread uzerinde cok zaman alacak o isi baslatacak. Thread'in elinde bizim ProgressDialog, UI erisimi olacak, bu islem bitince ProgressDialog'u goruntuden kaldiracak.
public class MyActivity extends Activity implements Runnable {
private ProgressDialog pd;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pd = ProgressDialog.show(this, "Working..", "Preparing Database", true, false);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
// uzun surecek islem burada
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
pd.dismiss();
// diger gui elementleri burada yaratilabilir
}
};
}