레이블이 ㄱpython인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ㄱpython인 게시물을 표시합니다. 모든 게시물 표시

2016년 5월 20일 금요일

(python) decoration, thread & yield

작성 중...

1. decoration pattern, @ 사용.
호출부에서 read_batches(50) 시,

read_batches = mpgen(read_batches(50))

처럼 원 함수의 기능 확장.


2. python에서는 GIL문제로 thread 대신에 multiprocessing 사용.
mpgen을 통해 주 프로세스와는 별도의 데이터 생성 프로세스가 시작
Queue는 thread에서 데이터 공유에 사용(아래, 최대 3개까지의 item 저장 가능)


3. yield
함수의 형태를 가지는 iterator (generator, 생성기라고 부름)를 만들어 줌.
iterator란?
c = iter(range(5))
c.next(), c.next(),... # 0,1,2,...

함수의 인자를 비휘발성으로 만듬
함수 재호출 시, yield 다음이 수행
return은 결과값 반환, yield는 iterator 반환


4. functools.wraps:
디버깅 시 func.__doc__ 또는 func.__name__ 등의 속성을 요청 시
원 함수 read_batches의 속성이 안나오고 decoration된 mpgen함수의 속성이 나오는 것을 방지.
함수 속성을 인자인 원 함수 f로 되돌리는 역할.
데코레이터에서 closure문제 해결을 위해 사용.



def mpgen(f):
    def main(q, args, kwargs):
        try:
            for item in f(*args, **kwargs):
                q.put(item)
        finally:
            q.close()

    @functools.wraps(f) 
    def wrapped(*args, **kwargs): #*args(리스트 받고), **kwargs(map 받음)
        q = multiprocessing.Queue(3)
        proc = multiprocessing.Process(target=main, args=(q, args, kwargs))
        proc.start()
        try:
            while True:
                item = q.get()
                yield item
        finally:
            proc.terminate()
            proc.join()

    return wrapped
     

@mpgen # mpgen의 인자함수로 read_batches을 사용함을 지정
def read_batches(batch_size):
    def gen_vecs():
        for im, c, p in gen.generate_ims(batch_size):
            yield im, code_to_vec(p, c)

    while True:
        yield unzip(gen_vecs()) # yield는 휘발성이 없는 함수(iterator 만듬)


2016년 5월 16일 월요일

(python) debugger

import ipdb 에서 빠져나올 때는 cntl+z
import pdb
pdb.set_trace()

명령법


(python) video read and write

opencv의 cv와 cv2의 차이
cv2 내에 cv있음. cv2가 최신.
import cv2.cv as cv

python 에서 버전 확인
import cv2
cv2.__version__

video 읽기
installed\opencv\3rdparty\ffmpeg\opencv_ffmpeg_64.dll 필요
이것을 작업 폴더에 복사해서 이름을 opencv_ffmpeg249_64.dll로 바꿈


테스트
import cv2
cap = cv2.VideoCapture('tmp1.mp4')
cap.grab() # true로 나와야 함


(Ref)
1. cv & cv2
2. about video working
3. opencv version 

2016년 4월 30일 토요일

(python) tips

import sys
sys.path
sys.path.append('c:\\python\\pathtest')
sys.path.remove('c:\\python\\pathtest')

set PYTHONPATH=c:\python
>>map(lambda apath: apath.find('pathtest'), sys.path)
[-1, -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]

import numpy as np
dir(), dir(np)

import pdb
pdb.set_trace()
n(step next), s(step in), run
print var

(package 작성 예)
path 연결
import sys
sys.path.append('c:\\python')
(또는 set PYTHONPATH=c:\....)

python 실행 후 path 확인하기 위해
import sys
map(lambda ap: ap.find('pathtest'), sys.path)

사용하기 위해
from pathtest.keras.imgproc import misc as mymisc

가능한 명령확인 위해
dir(mymisc)


[출처]
1. python modules
2. Jump to python - 패키지
3. python debugger- pdb


Keyboard shortcuts

[Mac]

cmd, w                     (현재 윈도 또는 탭 닫기)
cmd, t                      (현재 윈도의 새로운 탭 열기, 또는 아무 것도 없으면 새로운 파일 메니저)
cmd, [ 또는 ]            (브라우저 경로 되돌리기)
cntl, -> or <-           (여러 창을 우회하기)
cmd, cntl, F              (Full Window)
cmd, opt, <- or ->   (탭을 우회하기)

cmd, space              (새 spotlight 오픈, 파일 찾을 때)
alt, space                 (영문 한글 토글)

with iSnap
opt, -> or <- or ...



[Chrome]

cmd, n                     새로운 크롬 시작
cmd, t                      새로운 탭 시작
cmd, w                     탭 종료
cmd, shift, n            시크릿 모드 시작

cmd, L                     주소창 가기
cmd, alt, ->             탭 이동
cmd, alt, i                개발자 도구 열기

cntl, Enter               주소에 .com 추가하여 열기

Alt, <-, ->               이전 페이지로 가기, 다시 오기





[WIndows]

windows + left, right, up, down
windows + Tab

windows + cntl + D, create
windows + cntl + F4, close
windows + cntl + left/right

cntl + c/v/a



[출처]
[1] 크롬단축키,  chrome 단축키
[2] 윈도 단축키

2016년 3월 30일 수요일

(가상환경) Anaconda commands

conda -V
conda info --envs
conda update conda
conda create -n yourenvname python=2.7 anaconda
source activate yourenvname #windows에서는 source 생략
deactivate
conda remove -n yourenvname --all

conda info -e
conda install -n yourenvname [package]

windows에서 새로운 가상환경을 생성 때는 가상환경 생성 후, 그 환경 내에서도 mingw, libpython 설치 필요.

For ubuntu,
source bin/activate ~/anaconda2/
conda info --envs
...
source bin/activate /home/user/anaconda2/envs/keras1.0.1

theano/keras 실행 시는
THEANO_FLAGS=floatX=float32,device=gpu python

bash shell prompt 축약
PS1='\u:\W\$ '


(Ref.)
1. http://uoa-eresearch.github.io/eresearch-cookbook/recipe/2014/11/20/conda/
2. http://antilibrary.org/m/post/766
3. http://askubuntu.com/questions/145618/how-can-i-shorten-my-command-line-bash-prompt

2016년 3월 16일 수요일

(Windows) keras 설치

Backend를 Theano로 사용하므로 아래 설명은 theano설치도 포함한다.

먼저, cuda(v7.5), vs2013, git설치
git은 설치 중 옵션에서 "Run Git from the WIndows command prompt" 선택

TDM GCC x64 설치
Anaconda x64 설치

cmd 창을 관리자 모드로 연다(방법은 아래).
(or open Anaconda prompt)
conda update conda
conda update --all
conda install mingw libpython

Install latest version of Theano
git clone git://github.com/Theano/Theano.git
(or pip install git+git://github.com/Theano/Theano.git)
cd Theano
python setup.py develop

Install keras
git clone https://github.com/fchollet/keras
(pip install keras)
cd keras
python setup.py develop

Test
cd examples
ipython mnist_mlp.py


제어판->시스템->고급시스템설정->환경변수->사용자변수에 가서
PATH 변수에 cuda의 nvcc가 있는 bin폴더 추가
THEANO_FLAGS 변수 만들고 다음 사항 추가
"floatX=float32,device=gpu,nvcc.fastmath=True"


cmd 창을 관리자 모드로 여는법
시작->프로그램 및 파일검색
cmd 입력
리스트에 나타난 cmd를 클릭해서 “관리자모드로 시작”.


설치를 확인하는 법
cmd창에서 
where cl
where gcc
where nvcc
where g++


cuDNN을 같이 설치하면 학습 속도가 더욱 빨라진다. 
nvidia에서 cuDNN 4.0을 다운 받아 압축을 풀면 bin, include, lib의 3개의 폴더가 있다. 
내부의 파일들을   
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5
아래의 해당 위치에 옮겨주면 된다.



출처:
1. Setup a Deep Learning Environment on Windows (Theano & Keras with GPU Enabled)
2. How to install Keras and Theano in Anaconda Python 2.7 in Windows
3. FunMV
4. Installing Keras, Theano and Dependencies on Windows 10












2016년 2월 1일 월요일

(우분투 리눅스에서 파이썬) keras 코드 분석 예

파이썬에서 실행되는 DNN 툴 중에 keras 라는 것이 있습니다. keras 코드를 통해 python 명령 실행과 패키지 설치 폴더 구조와의 관계에 대해 분석해 봅시다.

keras 샘플 코드 중에 cifar10_cnn.py 라는 파일이 있는데 서로 다른 물체 10가지를 convolution net으로 분류해 내는 예제를 보여주는 코드입니다.
이 코드를 보면 헤드부에 아래와 같은 명령이 있습니다.

...
from keras.datasets import cifar10
...
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
...


이 명령을 Ubuntu 리눅스의 경우에 대해 살펴 봅시다.

keras에서 cifar10을 학습하려면 먼저 cifar10의 database 파일을 다운받아야 합니다. 이를 위해 상기한 바와 같이 db 다운에 필요한 lib를 import 합니다.


그런데, 처음 keras를 설치할 때,

keras의 설치 위치는 미리 설정된 어떤 디폴트 설치 위치 아래에서의 keras이고 그 아래에 필요한 lib들이 설치 됩니다. 설정된 이 위치는
/usr/local/lib/python2.7/dist-packages입니다.

여기서 dist-는 배포(distribution) 패키지의 의미로 이 폴더 아래에 들어가 보면
python과 관련하여 그동안 설치한 다양한 패키지(numpy, pandas, Theano, sklearn, ...) 들의 폴더가 있습니다.
따라서 keras의 설치 위치도 여기이며
/usr/local/lib/python2.7/dist-packages/keras 처럼 됩니다.

이 위치를 찾아 keras 폴더에 들어가면 다시 datasets라는 폴더가 있고(즉, 위 코드에서 from keras.datasets 임) 다시 그 밑에 cifar10.py 파일(import cifar10 임)이 있습니다.


다음은 cifar10.py 코드입니다
==========================
from __future__ import absolute_import
from .cifar import load_batch
from .data_utils import get_file
import numpy as np
import os


def load_data():
    dirname = "cifar-10-batches-py"
    origin = "http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz"
    path = get_file(dirname, origin=origin, untar=True)

    nb_train_samples = 50000

    X_train = np.zeros((nb_train_samples, 3, 32, 32), dtype="uint8")
    y_train = np.zeros((nb_train_samples,), dtype="uint8")

    for i in range(1, 6):
        fpath = os.path.join(path, 'data_batch_' + str(i))
        data, labels = load_batch(fpath)
        X_train[(i-1)*10000:i*10000, :, :, :] = data
        y_train[(i-1)*10000:i*10000] = labels

    fpath = os.path.join(path, 'test_batch')
    X_test, y_test = load_batch(fpath)

    y_train = np.reshape(y_train, (len(y_train), 1))
    y_test = np.reshape(y_test, (len(y_test), 1))

    return (X_train, y_train), (X_test, y_test)
============================


위 코드의 앞 부분을 살펴보면 web상의 origin 주소에 있는 db 파일에 접근해서 data file을 다운하는 부분이 있습니다. python을 실행하고 한라인씩 입력하여 수행해 보면

파인썬 명령 쉘에서

>>dirname = "cifar-10-batches-py"
>>origin = "http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz"

를 입력 후, 다음으로 get_file 함수를 실행해야 하는데, 이 파일은 python의 기본 함수가 아닙니다.
함수를 찾아 보면 keras/datasets에 있는 data_utils.py코드 내에 있습니다. 따라서 이 함수를 사용하기 위해

>>from keras.datasets import data_utils

하면 됩니다.  data_utils를 import하였으므로

>>path = data_utils.get_file(dirname, origin=origin, untar=True)

처럼 입력하고, path를 출력해 보면

>>path
'/home/vis/.keras/datasets/cifar-10-batches-py'

입니다. 즉, 내 계정인 vis 아래에 .keras 폴더 아래에 다운받을 db파일이 저장 된다는 것을 알 수 있습니다.
따라서 cifar10_cnn.py파일의 앞 부분의 다운로드 부분을 실행해 본 후에 path가 가리키는 위치에 가보면


vis@vis-VirtualBox:~/.keras/datasets$ ls -la
합계 198956
drwxrwxr-x 3 vis vis      4096  2월  1 11:37 .
drwxrwxr-x 3 vis vis      4096  1월 27 11:43 ..
drwxr-xr-x 2 vis vis      4096  6월  5  2009 cifar-10-batches-py
-rw-rw-r-- 1 vis vis 170498071  2월  1 11:37 cifar-10-batches-py.tar.gz


와 같이 database파일이 다운되어 있는 것을 볼 수 있습니다.









2015년 2월 2일 월요일

Theano 튜토리얼

[출처] http://newsight.tistory.com/161


i파이썬 서버를 mlc서버에 있음
컨트롤 엔터가 실행
쉬프트 엔터가 다른 쉘


심볼릭 변수는, 미지수 변수 x,y등을 할당하는 것

theano.function 은 CUDA C코드를 컴파일해내는 과정이고, 여기서 최적화가 일어난다.
또한 병렬화도 자동으로 처리해준다.

theano.function(inputs, outputs)
inputs는 변수의 리스트를 넣어야한다.
outputs는 인풋들로부터 계산가능한 식이 들어옴.
outputs=f(inputs)


심볼릭 변수들에대한 연산은 그래프로써 표현됨.
심볼릭 algebra들로만 연산을 하다가,
실제로 숫자를 넣어서 계산할 때 theano.function 을 이용해야함.
(함수형 언어의 철학을 따르는 방식)
심파이, 메스메티카 등도 마찬가지의 심볼릭 알제브라를 사용함.



theano.function 은 이 그래프를 CUDA 코드로 컴파일 해주는 것임


CPU/GPU 변환은 theano코드를 실행시키기 전에 해주어야함.
그래야 theano.function 에서 컴파일을 다르게 하겠네.


print(theano.config.floatX) : default 타입 확인
#심볼릭 변수의 타입
T.scalar() : 타입을 지정하지 않는 default 타입인 float32으로 되는 듯
T.iscalar() : int 32 타입을 사용하겠다
T.lscalar() : int 64
T.dscalar() : float64


#심볼릭 변수의 차원
T.scalar() : 0차원 점
T.vector() : 1차원 직선
T.matrix() : 2차원 평면
T.tensor3() : 3차원 큐브
T.tensor4() : 4차원


x=T.matrix()
y=T.matrix()
z=T.dot(x,y)
ftnSum_mat = theano.function([x,y],z)
print(ftnSum_mat(3,4))
----- 3,4는 matrix가 아니라서 에러가 남

x=T.matrix()
y=T.matrix()
z=T.dot(x,y)
ftnSum_mat = theano.function([x,y],z)

a = np.random.random((3,3))
b = np.random.random((3,3))


print(a,b,ftnSum_mat(a,b))


---------
x=T.matrix()
y=T.matrix()
z=T.dot(x,y)
ftnSum_mat = theano.function([x,y],z)

a = np.random.random((3,3))
b = np.random.random((3,3))

print(a,b,ftnSum_mat(a,b))
#이렇게 해도 변수 타입이 넘파이는 float64인데, 씨아노는 float32라서 에러가남
따라서 아래와같이 asarray함수로 float32타입으로 바꿔주어야함.
------
x=T.matrix()
y=T.matrix()
z=T.dot(x,y)
ftnSum_mat = theano.function([x,y],z)

a = np.asarray(np.random.random((3,3)),dtype=theano.config.floatX)
b = np.asarray(np.random.random((3,3)),dtype=theano.config.floatX)

print(a,b,ftnSum_mat(a,b))

-------
결론 -> 항상 float32를 쓰도록 주의할것





python 변수는 실제로 값을 가진 변수임
symbolic 변수는 실제값이 없는 미지수 변수임
shared 변수는 심볼릭 변수인데, 값을 가지고 있는 녀석임.

GPU의 셰어드 메모리에 올라가는 변수로, theano변수가 접근 가능한
값을 가지고 있음.

--
a = np.array([[1,2],[3,4]], dtype = theano.config.floatX)
x = theano.shared(a)
#a 매트릭스가 gpu 메모리에 올라가서, theano 변수가 접근 가능함
----만약 gpu메모리가 모자라면, 여기서 올리다가 에러가 남

print(x.get_value())
x.set_value(x.get_value()+1)
print(x.get_value())


# set 은 cpu -> gpu로 메모리를 올리는 것
# get 은 gpu -> cpu로 메모리를 가져오는 것
따라서 get과 set을 최대한 안써야함.
이건 거의 디버깅 용이라고 할 수 있음.
그리고 안쓰고 어차피 function에서 한방에 계산하기때문에 필요없음
---

a = np.array([[1,2],[3,4]], dtype = theano.config.floatX)
x = theano.shared(a)
y = x**2
ftnShared = theano.function([],y)
print(ftnShared())

#
여기서는 input으로 shared변수를 전달하면 안됨.
input에는 심볼릭 변수만 전달이 가능함.
shared 변수는 함수의 인자가아님.

---


T.nnet.conv.conv2d()
함수 등에 컨벌루션 레이어가 정의되어있음.


-
x = T.scalar()
y = x**2
diff = theano.function([x],T.grad(y,[x]))
print(diff(3))
결과 : [array(6.0, dtype=float32)]
#
array가 붙은 이유는 T.grad의 반환 값이 array라서 그럼.
왜냐하면 x 하나가아니라 여러개의 변수들의 리스트로 편미분을 해서

T.grad(y,[x])
즉, y 함수를 x로 편미분하는 것임,

--
x = T.scalar()
y = x**2
diff = theano.function([x],T.grad(y,[x])[0])
print(diff(3))
결과: 6.0
[0]을 해서, 첫번째 변수로 미분한 값만 array에서 가져옴
--

x = T.scalar()
w = theano.shared(np.array(3,dtype=theano.config.floatX),borrow=True)
obj = (1 - x*w)**2
learn_w = (w, w-0.1*T.grad(obj,w))
learn = theano.function([x],obj,updates=[learn_w])
print(learn(2))

#shared memory는 보통 아주 큰 memory를 GPU에서 사용하기 위함이고, cpu에서 gpu로 shallow copy가 유용하다. borrow=True옵션은 shallow copy이다. False옵션은 deep copy.
#updates는 list of tuples로 준다: [(before, after), (before, after), ...]이고 독립 변수가 여러 개인 경우, target의 독립 변수 당 derivative를 설정할 수 있다.  표기에서 []: list(수정가능), (): tuple(수정불가) 이다.  

updates 는
learn_w = (w, w-0.1*T.grad(obj,w))
이런식으로 정의를 해주어야함.
즉 w를 매 스탭마다 바꾸어갈 식을 정의함

function의 순서가 input 에서 output을 계산하고, 그다음 update 식을 수행함

while(){
learn(2)를 해주어야 이제 계속 업데이트 하는 것임
}
---

x = T.scalar()
w = theano.shared(np.array(3,dtype=theano.config.floatX),borrow=True)
obj = (1 - x*w)**2
learn_w = (w, w-0.1*T.grad(obj,w))
learn = theano.function([x],obj,updates=[learn_w])
print(learn(2),w.get_value())
print(learn(2),w.get_value())
print(learn(2),w.get_value())
print(learn(2),w.get_value())

----
theano는 update가 뉴럴넷을 전제로 깔고 정의됨.
굳이 이걸 안 쓰고, 업데이트를 function 으로 해줘도됨



--

import theano
import theano.tensor as T

class opt_problem:
    def __init__(self):
        # optimization variables
        self.x = theano.shared(numpy.array(100.,dtype=theano.config.floatX), borrow=True)
        self.y = theano.shared(numpy.array(100.,dtype=theano.config.floatX), borrow=True)
        self.pos = [self.x, self.y]
     
        # hyperparameters
        self.lr = theano.shared(np.array(0.05, dtype=theano.config.floatX), borrow=True) # learning rate
     
        # optimization objective
        self.ftn_eqn = (self.x ** 2) + 10*(self.y ** 2)
        self.grad = T.grad(self.ftn_eqn, self.pos)
     
        # evaluating current value
        self.ftn = theano.function([], self.ftn_eqn)
     
    def plot(self, scope=20.):
        # visualizing code
        x = np.arange(-scope, scope, 0.05)
        y = np.arange(-scope, scope, 0.05)
        X, Y = np.meshgrid(x, y)
        X = np.asarray(X, dtype=theano.config.floatX)
        Y = np.asarray(Y, dtype=theano.config.floatX)
        Z = (X ** 2) + 10*(Y ** 2)
        plt.figure()
        C = plt.contour(X,Y,Z)
     
    def build_gd(self):
        self.updates = []      
        for posi, grad in zip(self.pos, self.grad):
            self.updates.append((posi, posi - self.lr*grad))
     
# zip은 pos도 리스트고, grad도 리스트인데 각각을 지퍼로 연결해서 for문을 돌림
        # 독립 변수가 2개 이므로 각 변수에 대한 tuple의 list들 만듬

        # gradient descent function
        self.gd = theano.function([], self.ftn_eqn,
                                  updates=self.updates)
     
problem = opt_problem()
problem.plot()
problem.build_gd()

Xs = []
Ys = []
Xs.append(problem.x.get_value())  # gpu로 내부적으로 shared된 x변수는 값이 계속 바뀜
Ys.append(problem.y.get_value())
for epoch in xrange(20):
    if(epoch%5)==1:
        problem.lr.set_value(problem.lr.get_value()/2)
 
    f_val = problem.gd()
    Xs.append(problem.x.get_value())
    Ys.append(problem.y.get_value())
    plt.plot(Xs, Ys, '-ro')
    print(f_val)


    ----
    numpy에서 아이겐벡터, 아이겐 벨류 계산 가능


    -
 
   matplotlib 는 매틀랩하고 거의 똑같은 인터페이스로 구성되어있음
-
뉴럴넷 짤때, 백프로퍼게이션 구현안하고 짤 수 있음.



--
x = T.scalar()
w = theano.shared(np.array(3,dtype=theano.config.floatX),borrow=True)
obj = (1 - x*w)**2

#learn_w = (w, w-0.1*T.grad(obj,w))

learn = theano.function([x],obj)

w = w-0.1*T.grad(obj,w)
m_update = theano.function([],w)

print(learn(2), m_update())
print(learn(2), m_update())
print(learn(2), m_update())
print(learn(2), m_update())

#
update따로구현해보기

2014년 11월 30일 일요일

Python에서 sqlite를 이용한 BoVW 구현

# Python에서 sqlite를 이용한 BoVW 구현
# funMV, 2014.12
from numpy import *
import pickle
from pysqlite2 import dbapi2 as sqlite
import sift
import imagesearch


f = open("ukbench/first1000/list.txt",'r') # to access sub-directory
lines = f.readlines() # read all lines through line to line style
f.close()
imlist=[ 'ukbench/first1000/'+line[:-1] for line in lines] # to eliminate last character '\n'

nbr_images=len(imlist)
featlist=[ imlist[i][:-3]+'sift' for i in range(nbr_images)] # filename.sift in each line




# load vocabulary
with open('vocabulary.pkl','rb') as f:
    voc = pickle.load(f)


# create db
con = sqlite.connect('test1.db') # 재 실행시, 반드시 test1.db를 지우고 돌려야 함 
                             # 일단, 실행되면 hdd에 test1.db가 저장되기 때문


# create tables
con.execute('create table imlist(filename)')
con.execute('create table imwords(imid,wordid,vocname)')
con.execute('create table imhistograms(imid,histogram,vocname)')      

# 다음 4개 명령은 없어도 실행되지만 좀 느려지는 것 같음 
con.execute('create index im_idx on imlist(filename)')
con.execute('create index wordid_idx on imwords(wordid)')
con.execute('create index imid_idx on imwords(imid)')
con.execute('create index imidhist_idx on imhistograms(imid)')

con.commit()




# test db
locs, descr = sift.read_features_from_file(featlist[0])
# locs=2276x4, descr=2276x128
# For first image, 2277 features are there and they will be prjected to vw


imwords=voc.project(descr)
#voc.shape[0]=498: # of visual words
#imwords.shape=498의 히스토그램(보팅) 정보
#imwords: voting number of features per each word (histogram). some features among 2278 features
# are voted 7 times to first word, and 6 times for second words of vw, so on. 
#array([  7.,   6.,   2.,   1.,   5.,   4.,   4.,   1.,   0.,   4.,   2.,
#         3.,   6.,   1.,   2.,   4.,   2.,   0.,   1.,   9.,   1.,   1.,
#         2.,   3.,   0.,   1.,   7.,   3.,   2.,   7.,   3.,   0.,   5.,
#        17.,   1.,   3.,  16.,   6.,   3.,   8.,  26.,  11.,   1.,  10.,
#         3.,   3.,   4.,   2.,   2.,   1.,   2.,   1.,   2.,   2.,  ...
nbr_words=imwords.shape[0] # 498  



# 위는 test모드이고 여기서부터는 실제 모든 im의 feature들을 db에 삽입 
# go through all images, project features on vocabulary and insert
for i in range(nbr_images)[:100]: # [0,1,2,...,98,99]
    locs, descr = sift.read_features_from_file(featlist[i])
    imname = imlist[i]

    imwords=voc.project(descr)
    nbr_words=imwords.shape[0]

    # (1) 파일 이름을 db에 저장
    cur=con.execute("insert into imlist(filename) values ('%s')" %imname)
    imid = cur.lastrowid

    # (2) 파일 이름 id - 각 word에 대한 voting 횟수 연계 저장
    for j in range(nbr_words):
        word = imwords[j]
        con.execute("insert into imwords(imid,wordid,vocname) values (?,?,?)",
                    (imid,word,voc.name))

    # (3) 파일이름 id와 히스토그램 전체 저장    
    con.execute("insert into imhistograms(imid,histogram,vocname) values (?,?,?)",
                (imid,pickle.dumps(imwords),voc.name))



# 여기서 최종 결과를 저장하고 나가려면 commit를 해 주여야 함.
# con.commit()
# 다시 사용 시
# con=sqlite.connect('test1.db')




# Test for saved db
print con.execute('select count (filename) from imlist').fetchone()
# (100,), 100개의 im name이 저장

print con.execute('select * from imlist').fetchone()
# (u'ukbench/first1000/ukbench00000.jpg',)





##################################################
# 여기서 부터 저장된 db를 이용한 test
##################################################

# test할 query인 첫번째 im의 id, 히스토그램을 가져옴
im_id = con.execute("select rowid from imlist where filename='%s'" % imlist[0]).fetchone()
#im_id=(1,)
s = con.execute("select histogram from imhistograms where rowid='%d'" % im_id).fetchone()
h = pickle.loads(str(s[0])) # len(.)=498, histogram for word voting



#Using the index to get candidates
#locs, descr = sift.read_features_from_file(featlist[0])
#imwords=voc.project(descr)
#words=imwords.nonzero()[0] #voting이 하나라도 있는 words의 index



words=h.nonzero()[0]
#vw에 대한 histogram(bin수는 보팅 횟수가 0인 빈을 배제 후 vw의 갯수 만큼)
# words.shape=(455,)=[0,1,2,3,5,....]


# find candidates
candidates = []
for word in words:
    # table imword에서 word id로 imid를 추출. 즉, 특정 word를 가진 모든 im의 id를 추출
    # 즉, query im의 해당 word를 가지는 db내 모든 im의 id 리스트를 candidates에 저장
    im_ids = con.execute("select distinct imid from imwords where wordid=%d"
                % word).fetchall()
    c = [i[0] for i in im_ids]
    candidates += c


 
# len(candidates) = 1443 




# take all unique words and reverse sort on occurrence 
tmp = [(w,candidates.count(w)) for w in set(candidates)]
# candidates.count(1)=23, candidates.count(10)=15
# set(candidates)=[1,2,3,4,...,99,100]
# tmp=[(1, 23), (2, 23), (3, 19), (4, 26), (5, 11), (6, 13), (7, 14),
#  (8, 11), (9, 28), (10, 15), (11, 14), (12, 30), (13, 10),.....
# (95, 27), (96, 31), (97, 19), (98, 16), (99, 18), (100, 17)]
tmp.sort(cmp=lambda x,y:cmp(x[1],y[1]))
tmp.reverse()
candi=[w[0] for w in tmp] # len(candi)=100
#candi=[43,77,44,42,78,79,...,21,84,83]
#필요한 것은 im의 id이므로 sort후 reverse해줌 



matchscores=[]
for imid in candi:
    s = con.execute("select histogram from imhistograms where rowid='%d'" % imid).fetchone()
    cand_h = pickle.loads(str(s[0])) # histogram for word voting

    cand_dist = sqrt( sum( voc.idf*(h-cand_h)**2 ) )
    matchscores.append( (cand_dist,imid) )


matchscores.sort()
print matchscores[:10]
#[(0.0, 1), (60.812088499474271, 2), (61.547483004618186, 3), (92.620967753952812, 4),
# (100.59065889285603, 34), (107.76370948763174, 28), (108.27892205906744, 25),
# (109.39719124624605, 9), (110.33866766043165, 10), (110.77231202013482, 20)]

    

con.commit()
con.close()









Bag of Visual Words


Bag of Words의 요약:




# BoW를 이해하기 위한 Toy example
# BoW algorithm analysis
# 2013/06/28, 2014/12/03 개선
# by funmv 
#
from PIL import Image
from pylab import *
import os
from numpy import *
from scipy.cluster.vq import *
import sift
import vocabulary


# 물체의 class는 3개이다 (즉, 0~3/4~7/8~11의 4개씩 동일 물체를 다른 자세에서 찍었음. 아래 그림 참조)
imlist = ['ukbench00000.jpg', 'ukbench00001.jpg', 'ukbench00002.jpg', 'ukbench00003.jpg', 'ukbench00004.jpg', 'ukbench00005.jpg', 'ukbench00006.jpg', 'ukbench00007.jpg', 'ukbench00008.jpg', 'ukbench00009.jpg', 'ukbench00010.jpg', 'ukbench00011.jpg']

nbr_images=len(imlist)
featlist=[ imlist[i][:-3]+'sift' for i in range(nbr_images)]

"""for i in range(nbr_images):
    sift.process_image(imlist[i], featlist[i])
"""

descr = []
descr.append(sift.read_features_from_file(featlist[0])[1])
descriptors = descr[0]
# sift.read_features_from_file(featlist[i])[0]:
# list of [pixel coord of each feature point, scale, rotation angle] for i-image
# size: (# of feature point x 4) for i-th image
#
# sift.read_features_from_file(featlist[i])[1]:
# list of [feature values] for i-th image
# size: (# of feature point x 128) for i-th image

for i in arange(1, nbr_images):
    descr.append(sift.read_features_from_file(featlist[i])[1])
    descriptors = vstack((descriptors, descr[i])) # stack of vector

#len(descr[0]): number of feature points -> 2276
#len(descr[0][1]): size of 1st feature vector -> 128
    
voc, distortion = kmeans(descriptors[::10,:],3,1) # select one per 10 rows, 3개의 word를 뽑아냄

len(voc) #3, voc = 3x128
len(voc[0]) #3
len(voc[1]) #128

nbr_words = voc.shape[0] #3

# (# of images, bins of histogram(= # of words))
#    = (12x3)
imwords=zeros((nbr_images, nbr_words)) 
print imwords

words, distance = vq(descr[0],voc) # vector quantization
# len(words)->2276
# words: index vector of the cluster that each feature involves
#        [1, 2, 1, 0, 1, 2, ...]

#voca = vocabulary.Vocabulary('ukbenchtest')

for i in range(nbr_images): # def project
    hist = zeros((nbr_words))
    words, distance = vq(descr[i],voc) 
    # 현재 im에 대해 각 feature가 속하는 word의 index와 이 word까지의 거리가 리턴
    # index를 이용하여 해당 word에 보팅하여 histogram을 만듬 
    for w in words:
        hist[w] += 1
    imwords[i] = hist

print imwords # degree that each im involve to each cluster


"""
     0      1     2    : cluster index (word가 3개이니까 index는 2까지)  
[[  766.   461.  1049.]: 1st image의 histogram의 모양
 [  725.   451.  1020.]: 2nd image의 "
 [  671.   461.  1133.]: ...
 [ 1101.   630.  1403.]
 [  260.   317.   409.]
 [  267.   308.   370.]
 [  283.   394.   476.]
 [  239.   331.   410.]
 [ 1105.   468.  1317.]
 [  116.   191.   390.]
 [  122.   251.   439.]
 [ 1183.   597.  1475.]]:  12번째 im의 histogram모양
  12번째 이미지의 모든 특징 중에서 word 0에 속하는 것은 1183개, 1번 597개, 2번 1475개이다.  3경우 합하면 특징의 개수이다.  따라서 test영상의 특징에 대한 histogram을 그리고 위 12개 중에서 hist모양이 비슷한 것을 찾으면 그것이 해당 영상이다. 
 """








   

 

 

 


다음의 코드에서 voc의 내용을 알 수 있음.





2013년 10월 2일 수요일

Python 작업 위치 변경

""" 명령의 일부만 입력하고 Tab을 누르면 가능한 명령 리스트가 나온다
    방금 입력했던 명령을 다시 보기 위해서는 Alt-p, Alt-n을 사용한다.
    (내 컴퓨터에서는 왼쪽 alt만 먹음)
"""
>>> from PIL import Image
>>> import os
>>> os.getcwd()   # 현재 작업 위치를 보여줌
'D:\\Opencv\\Python27'
>>> from os import chdir  # 작업 위치를 바꾸기 위한 헤드
>>> chdir('d:\\') # 작업 위치 변경
>>> os.getcwd()
'd:\\'
>>>

>>> chdir('D:\\다운로드_2013\\진충_크랙 검출')  # 한글도 입력됨. 2개의 백슬러시'\\'를 사용
>>> os.getcwd()  # 한글이 들어가니 이상한 글자가 나옴
'D:\\\xb4\xd9\xbf\xee\xb7\xce\xb5\xe5_2013\\\xc1\xf8\xc3\xe6_\xc5\xa9\xb7\xa2 \xb0\xcb\xc3\xe2'

>>> pil_im=Image.open('empire.jpg')  # 위치 변경이 잘 되었는지 확인하기 위해 그 위치의 파일하나를 오픈
>>>

>>> from pylab import *  # 영상의 화면 출력을 위해 matplotlit 헤드 입력



""" 작업 위치를 변경하기 위한 명령 """
>>> import os
>>> from os import chdir
>>> chdir('D:\\다운로드_2013\\진충_크랙 검출')
>>> os.listdir('.') # 모든 파일과 폴드명이 나타남...
....
....



(예)

>>> from PIL import Image
>>>
>>> im=Image.open('empire.jpg')
>>> imshow(im)  # pylab헤드를 입력하지 않았기 때문에 에러..

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    imshow(im)
NameError: name 'imshow' is not defined

>>> im1 = array(im) # array명령은 pylab에 있다...

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    im1 = array(im)
NameError: name 'array' is not defined
>>> from pylab import *



>>> im1 = array(im)  # array로 변환 안하면 이미지가 꺼꾸로 화면 출력
>>> imshow(im1)
<matplotlib.image.AxesImage object at 0x03C3C3D0>
>>> show()  # show가 실행된 이후에야 영상이 출력됨...

Python 명령들

직전에 수행했던 명령을 보려면 alt-p, alt-n을 사용한다.

>>> from numpy import *
>>> from scipy import ndimage

>>> a1=ones((1,2))  # 1x2크기의 값이 1인 배열 만들기
>>> a1.shape  # 배열 크기를 출력해 주는 함수
(1,2)
>>> a1.shape[0]
1
>>> a1.shape[1]
2
>>>
>>> a1
array([[ 1.,  1.]])
>>> a2=a1.T  # 배열을 transpose한다.
>>> a2   # 2x1크기의 배열이 얻어 졌다
array([[ 1.],
       [ 1.]])
>>>
>>> ones((1,a2.shape[1]))  # 1x1크기 값이 1인 배열 생성
array([[ 1.]])
>>> vstack((a2,ones((1,a2.shape[1]))))  """vertical stack: 수직 방향으로 데이터 쌓음"""
array([[ 1.],           # a2가 [1; 1]이므로 수직 방향으로 쌓으면 3x1크기 배열
       [ 1.],
       [ 1.]])
>>>


>>>
>>> a2.shape[1]
1
>>> ones((1,1))
array([[ 1.]])
>>> a2
array([[ 1.],
       [ 1.]])
>>> vstack((a2,ones((1,1))))
array([[ 1.],
       [ 1.],
       [ 1.]])



>>> """또 다른 배열 생성과 쌓기"""
>>> a=array((1,2,3))
>>> a
array([1, 2, 3])
>>> b=array((3,4,5))
>>> hstack((a,b))  """ 수평 쌓기 """
array([1, 2, 3, 3, 4, 5])
>>>


>>> a=array(([1],[2],[3]))
>>> a
array([[1],
       [2],
       [3]])
>>> b=array(([3],[4],[5]))
>>> b
array([[3],
       [4],
       [5]])
>>> vstack((a,b)) """ 수직 쌓기 """
array([[1],
       [2],
       [3],
       [3],
       [4],
       [5]])
>>>