Dataset
နမူနာ အနေနဲ့ Graz dataset ထဲက စက်ဘီးပုံတွေ နဲ့ လူပုံတွေကို သုံးပါမယ်။ အဲဒီ ဝဘ်ဆိုက် က ပုံတွေကို download လုပ်ပြီးတဲ့ အခါ စက်ဘီးပုံ ၂၀၀ နဲ့ လူပုံ ၂၀၀ကို training လုပ်ဖို့ training ဆိုတဲ့ folder ထဲမှာ သိမ်းပြီး၊ ကျန်တာကို test လုပ်ဖို့ test ဆိုတဲ့ folder ထဲမှာသိမ်းလိုက်ပါမယ်။ အဲဒီက ပုံတွေက bmp ဖိုင်တွေ ဖြစ်နေတဲ့ အတွက် ပုံတွေ အားလုံးကို ကျွန်တော်တို့ လိုချင်တဲ့ png ဖိုင် format ဖြစ်အောင် ပြောင်းဖို့လိုပါတယ်။ အဲလို ပုံအားလုံးကို တခါတည်း ပြောင်းဖို့ အတွက် အောက်မှာပြထားတဲ့ အတိုင်း MatLab program လေးတပုဒ်ကို ရေးပြီး training folder အတွက်တခါ၊ test folder အတွက်တစ်ခါ လွယ်လွယ်ကူကူ မြန်မြန်ဆန်ဆန် ပြောင်းလိုက်ပါတယ်။%File name: bmp2png.m %------------------------------------------------------------------------- sDir=[pwd,'/test/']; %source folder sFile=[sDir, '*.bmp']; %source files dFile=[pwd,'/test_png/test_']; %destination %------------------------------------------------------------------------- sList=dir(sFile); %Get file list nFiles=size(sList,1) %number of files %------------------------------------------------------------------------- for i=1:nFiles Img=imread([sDir,sList(i).name]); imwrite(Img,[dFile,sprintf('%03d',i),'.png']); i %output progress end
ကျွန်တော့် စက်ထဲမှာ MatLab မရှိတဲ့ အတွက် အဲဒီအစား အလကားရတဲ့ free software တစ်ခုဖြစ်တဲ့ Octave ကို သုံးပါမယ်။ Ubuntu 14.04 LTS Linux စက် အဟောင်းလေးတစ်လုံးကို သံုးခဲ့ ပါတယ်။ Octave မှာ image processing package မရှိသေးရင်အောက်က ပြထားတဲ့ အတိုင်း terminal မှာ ရိုက်ပြီး ထည့်လို့ရပါတယ်။ ကျွန်တော်က တော့ statistics package ကိုပါ ထည့်လိုက်ပါတယ်။
sudo apt-get install octave-image sudo apt-get install octave-statistics
ပြီးရင် Octave ကို ဖွင့်လိုက်ပါမယ်။ နောက် Octave ရဲ့ terminal ထဲမှာ အောက်က command တွေကို ရိုက်ထည့်ပြီး package တွေကို တင်ဖို့လိုပါတယ်။
pkg load image pkg load statistics
နောက်တခါ ပြောင်းလို့ ရတဲ့ ပုံတွေကို သိမ်းဖို့ အတွက် training_png နဲ့ test_png ဆိုပြီး folder အသစ်တွေ ဖွဲ့လိုက်ပါမယ်။ Octave ရဲ့ terminal ထဲမှာပဲ chdir ဆိုတဲ့ command နဲ့ လက်ရှိ directory ကို ပြောင်း၊ ခုနက MatLab progarm ကို run ဖို့ သူ့ရဲ့ ဖိုင်နာမည် bmp2png; ဆိုပြီးရိုက်လိုက်မယ် ဆိုရင် ပုံတွေကို png ပြောင်းပြီး သတ်မှတ်တဲ့ folder ထဲမှာ သိမ်းသွားပါမယ်။
Feature Extraction
SIFT features တွေကို ရှာဖို့ ဒီ ဝဘ်ဆိုက် ကနေ Harris & Hessian ဆိုတဲ့ feature extractor ကိုသုံးပါမယ်။ အဲဒီ feature extractor ကို မသုံးချင်ရင် တခြားရှိတဲ့ ဟာတွေထဲက ကြိုက်တာကို ယူသုံးလို့ရပါတယ်။ အဲဒီ extract_features.tar.gz ဆိုတဲ့ ဖိုင်ကို ဒေါင်းလုပ် လုပ်၊ extract လုပ်ပြီးရင်၊ feature တွေ ထုတ်ချင်တဲ့ folder တွေထဲမှာ extract_features.ln နဲ့ harhessift.basis ဆိုတဲ့ ဖိုင်တွေကို ထားလိုက်ပါမယ်။ ပြီးရင် ဖိုင်အားလုံးကို တခုချင်းစီ extract လုပ်ဖို့ အောက်မှာ ပြထားတဲ့ အတိုင်း xall.sh ဆိုပြီး script ဖိုင်လေး ရေးပြီး feature တွေကို ထုတ်လိုက်ပါမယ်။#!/bin/bash FILES=./*.png for f in $FILES do echo "Processing - $f ..." ./extract_features.ln -harhes -i "$f" -sift -pca harhessift.basis done
Scrpit ဖိုင်ရေးပြီးထဲအခါ terminal မှာ သူ့ကို run လို့ရအောင် အောက်ကအတိုင်း ပြင်ဖို့လိုပါတယ်။ ပြီးရင် ./xall.sh ရိုက်လိုက်ရင် ပုံတွေ တစ်ပုံ ခြင်းစီ အတွက် feature file တွေရလာပါလိမ့်မယ်။
chmod 755 xall.sh
ထုတ်ထားတဲ့ feature တွေကို ပုံနဲ့ တွဲကြည့်ချင်ရင် ခုနက ဝက်ဘ်ဆိုဒ် ကပဲ display_features.m ဆိုတဲ့ MatLab code ကို ယူနိုင်ပါတယ်။ နောက် Octave terminal မှာ နမူနာ အနေနဲ့ ဒုတိယမြောက် စက်ဘီးပုံနဲ့ သူ့ရဲ့ features တွေကို အောက်က အတိုင်း command ရိုက်ထည့်ပြီး ကြည့်လို့ ရပါတယ်။
display_features('bike_002.png.harhes.sift','bike_002.png',0,0);
Feature file တွေရဲ့ extension က .sift ဖြစ်ပြီး ပထမဆုံး အကြောင်းက feature vector တခုခြင်းစီရဲ့ အရွယ်အစား ကို ဖော်ပြထားတာ ဖြစ်ပြီး ၁၂၈ လို့ တွေ့နိုင်ပါတယ်။ ဒုတိယ အကြောင်းက feature အရေအတွက်ကို ဖော်ပြထားတာ ဖြစ်ပါတယ်။ တပုံ တပုံ စီမှာ feature အရေအတွက် ထောင်ချီပါတာကို တွေ့ရပါတယ်။ တတိယ အကြောင်းက စပြီး တတန်းစီမှာ ဂဏန်း ၁၃၃ လုံးပါပြီး ၆ ခုမြောက်ကစပြီး နောက်ဆုံး ၁၃၃ လုံး အထိက dimension 128 ခုရှိတဲ့ feature vector တွေဖြစ်ပါတယ်။
Classification
ပထမ အဆင့် အနေနဲ့ ရထားတဲ့ features တွေကို အမျိုးအစားခွဲပြီး အုပ်စု နှစ်ရာလောက် ခွဲထားလိုက်ပါမယ်။ အဲဒီလို တူရာတူရာ အုပ်စု ဖွဲဖို့ အတွက် k-means clustering algorithm ကို သုံးပါမယ်။ Feature vectors တွေ တစ်ခု နဲ့ တစ်ခု ဘယ်လောက်နီးစပ်လည်း ဆိုတာ တိုင်းဖို့ ကြိုက်တဲ့ distance အမျိုးအစားကို သုံးနိုင်ပါတယ်။ ကျွန်တော်တို့က နောက်ပိုင်းမှာ histogram တွေကို ပါ ဘယ်လောက်နီးစပ်လည်း တိုင်းမှာမို့ သူတို့အတွက် သင့်တော်တဲ့ χ2 distance ကို တလက်စတည်း သုံးလိုက်ပါမယ်။ Vector နှစ်ခုကြားက χ2 distance ရှာတဲ့ MatLab ဖန်ရှင်တစ်ခုကို အောက်မှာ ပြထားပါတယ်။function d=ChiDist(v1,v2) %Find Chi Square distance between two vectors %Input: 2 vectors %Output: a scalar distance %File name: ChiDist.m dv=(v1-v2).^2; sv=abs(v1)+abs(v2); sv(sv==0)=1e-9; %eliminate zero denominator d=sum(dv./sv)./2; end
MatLab မှာ kmeans ဆိုတဲ့ ဖန်ရှင်ပါပေမယ့် အဲဒီမှာ χ2 distance ကို သုံးလို့မရတဲ့ အတွက် k-means ရှာတဲ့ ကုဒ်ကို ကိုယ့်ဟာကို ရေး ပြီးသုံးခဲ့ ပါတယ်။ အမှန်တော့ features တွေကို အုပ်စုဖွဲ့တာ ရိုးရိုး kmeans ကို သုံးလိုက်လည်း ရပါတယ်။ ဒါပေမယ့် kmeans အတွက် statistics package လိုပါတယ်။
function [Idx,C]=KMeansCustom(X,k) %KMeansCustom partitions the points in the n-by-d data matrix X into k clusters. %[Idx,C]= KMeansCustom(X,k) returns %n-by-1 vector IDX containing the cluster indices of each point and %k-by-d matrix C containing the k cluster centroid locations. %For n sample points with d dimensions in each point, X has n rows and d columns. %File name: KMeansCustom.m %Author: Yan Naing Aye %Website: http://cool-emerald.blogspot.com/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Define maximum number of iterations MaxIter=100; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% [n,d]=size(X); k=round(k); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %step1 :arbitrarily choose k samples as the initial cluster centers p=randperm(n); Mu=X(p(1:k),:); D=zeros(k,n); for t=1:MaxIter %step2:distribute the samples X to the clusters for j=1:k for i=1:n D(j,i)=ChiDist(X(i,:),Mu(j,:));%Use custom distance end end [ValMin,IndexMin]=min(D); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %step 3: update the cluster centers OldMu=Mu; for i=1:k Mu(i,:)=mean(X(IndexMin==i,:),1); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %step4 :check convergence if sum(sum(abs(OldMu-Mu))) == 0 break end t %output progress end Idx=IndexMin'; C=Mu;
တပုံစီမှာ feature vector တွေ ထောင်ချီပါတာမို့ ကျွန်တော်တို့ train လုပ်မယ့် ပုံ ၄၀၀ အတွက် ဆိုရင် တွက်ချက်မှု တွေ အများကြီး လုပ်ရမှာမို့။ တပုံချင်းစီ ကနေ feature အားလုံးကို မယူတော့ပဲ ပုံအားလုံးကနေ ကြုံရာကျဘမ်း feature အခု ၁၀၀ စီယူလိုက်ပါမယ်။ ပြီးမှ ရလာတဲ့ ကျဘမ်း features တွေကို k-means သုံးပြီး အုပ်စု ၂၀၀ ဖွဲ့လိုက်ပါမယ်။ အဲဒီလို အုပ်စုဖွဲ့ပေးပြီး အုပ်စုတွေရဲ့ အလယ် (centers) တွေကို ရှာပေးတဲ့ MatLab ပရိုဂရမ်ကို အောက်မှာ ပြထားပါတယ်။ ထောင်ချီရှိတဲ့ feature တွေ အကုန်မယူပဲ တစ်ရာစီပဲ ယူတွက်တာတောင်မှ နာရီ နဲ့ ချီပြီးကြာတာမို့ ပစ်ထားလိုက်ပြီး နောက်နေ့ကျမှ ကွန်ပြူတာဖွင့်ကြည့်လိုက်တဲ့ အခါ visual token vocabulary လို့ခေါ်တဲ့ feature centers တွေကို FeatureCtrs.dat ဆိုတဲ့ ဖိုင်ထဲမှာ သိမ်းထားတာကို ရပါတယ်။
%File name: IF1_Find_VisualTokens.m %Author: Yan Naing Aye %Website: http://cool-emerald.blogspot.com/ %------------------------------------------------------------------------- %parameter settings NRF=100; %number of random features taken from each training image NVT=200; %number of visual tokens to find FV_Size=128; %feature vector size %------------------------------------------------------------------------- sDir=[pwd,'/training_png/']; %source directory sFile=[sDir,'*.sift']; %source files fList=dir(sFile); %get file list nFiles=size(fList,1); %number of files %------------------------------------------------------------------------- allFeatures=zeros(NRF*nFiles,FV_Size); %allocate and initialize for all features %(e.g. 100 random features each from 400 files and each feature has 128 dimensions) selFeatures=zeros(NRF,FV_Size); %allocate and initialize for random features si=1; ei=100; %starting index and ending index for each file for i=1:nFiles i %output progress sFile=[sDir,fList(i).name] %read all features from each file readFeatures=textread(sFile,'','headerlines',2); %each row has 133 elements and first 5 elements are u,v,a,b,c; feature vectors starts from 6th column readFeatures=readFeatures(:,6:end); %select random features nFeatures=size(readFeatures,1); p=randperm(nFeatures,NRF); selFeatures=readFeatures(p,:); %put the selected features to all features pool ei=i*NRF; si=ei-NRF+1; allFeatures(si:ei,:)=selFeatures; end %find feature centers by k-means clustering [idx,FeatureCtrs] = KMeansCustom(allFeatures,NVT); %save the feature centers to a file save -ascii -double -tabs FeatureCtrs.dat FeatureCtrs;
အဲဒီ ပရိုဂရမ်ကို Octave terminal မှာ IF1_Find_VisualTokens; လို့ရိုက်ထည့်ပြီး run နိုင်ပါတယ်။
Histogram of Visual Tokens
ဒုတိယ အဆင့် အနေနဲ့ training ပုံတပုံ စီက features အားလုံးကို ဖတ်ပြီး ဘယ် visual token တွေဘယ်နှစ်ခု ပါတယ် ဆိုတဲ့ histogram တခုစီ ဆောက်ပါမယ်။ token frequency feature လို့လည်း ခေါ်ပါတယ်။function h=GetHistOfVT(sFile) %Get histogram of visual tokens %Input: feature file path %Output: a row (1D array) of histogram %File name: GetHistOfVT.m %Author: Yan Naing Aye %Website: http://cool-emerald.blogspot.com/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %read all features from each file readFeatures=textread(sFile,'','headerlines',2); %each row has 133 elements and first 5 elements are u,v,a,b,c; feature vectors starts from 6th column readFeatures=readFeatures(:,6:end); %load feature centers (visual tokens) load('FeatureCtrs.dat'); nf=size(readFeatures,1); nc=size(FeatureCtrs,1); %---------------------------------------------------------------- %initialize histogram h=zeros(1,nc); for i=1:nf minD=ChiDist(readFeatures(i,:),FeatureCtrs(1,:)); minC=1; for j=2:nc d=ChiDist(readFeatures(i,:),FeatureCtrs(j,:)); if (d<minD) minD=d; minC=j; end end h(minC)=h(minC)+1; end end
အဲဒီလို histogram တွေရှာပြီး ပုံအားလုံးရဲ့ histogram တွေ အားလုံးကို AllHistVT.dat ဆိုတဲ့ ဖိုင်တဖိုင် ဖန်တီးပြီး သိမ်းပေးတဲ့ ပရိုဂရမ်ကို အောက်မှာ ပြထားပါတယ်။ Octave terminal မှာ IF2_Build_Histogram_of_VisualTokens; လို့ ရိုက်ထည့်ပြီး run နိုင်ပါတယ်။ သူလည်း နာရီနဲ့ ချီပြီးကြာပါတယ်။
%File name: IF2_Build_Histogram_of_VisualTokens.m %Author: Yan Naing Aye %Website: http://cool-emerald.blogspot.com/ %------------------------------------------------------------------------- NVT=200; %number of visual tokens sDir=[pwd,'/training_png/']; %source directory sFile=[sDir, '*.sift']; %source files sList=dir(sFile); %source file list nFiles=size(sList,1); %number of files AllHistVT=zeros(nFiles,NVT); %histograms of visual tokens of all files %------------------------------------------------------------------------- for i=1:nFiles AllHistVT(i,:)=GetHistOfVT([sDir,sList(i).name]); i%output progress end save -ascii -double -tabs AllHistVT.dat AllHistVT;
Image Retrieval
နောက်ဆုံးအဆင့်ကတော့ query image လို့ ခေါ်တဲ့ test image တပုံကို ရွေးပေးလိုက်ရင် သူနဲ့ အတူဆုံး ပုံ ၉ ပုံကို training image တွေထဲက ရွေးထုတ်ဖို့ပါ။ အဲလို လုပ်ပေးမယ့် ပရိုဂရမ်ကို အောက်မှာ ပြထားပြီး Octave terminal မှာ IF3_Retrieve; လို့ ရိုက်ထည့်ပြီး run နိုင်ပါတယ်။%File name: IF3_Retrieve.m %Author: Yan Naing Aye %Website: http://cool-emerald.blogspot.com/ %------------------------------------------------------------------------- %Get test file featureDir=[pwd,'/test_png/']; [uFileName,uPathName] = uigetfile('*.png','Select a test file',featureDir); [pathstr, fileNameWithoutExt, ext, versn] = fileparts(uFileName); featurefile=[featureDir, fileNameWithoutExt,'.png.harhes.sift']; %------------------------------------------------------------------------- %show test image figure; imshow([pwd,'/test_png/', fileNameWithoutExt,'.png']); title('Test image'); %------------------------------------------------------------------------- %Get histogram for test image figure; h=GetHistOfVT(featurefile); bar(h); title('Test image histogram'); %------------------------------------------------------------------------- %Load trained data load('AllHistVT.dat'); n=size(AllHistVT,1); cDist=zeros(n,1); for i=1:n; cDist(i)=ChiDist(h,AllHistVT(i,:)); end [B, IX] = sort(cDist); %------------------------------------------------------------------------- %Get folder path and wildcard imgDir=[pwd,'/training_png/']; imgFile=[imgDir, '*.png']; %Get file list and number of files fileList=dir(imgFile); %------------------------------------------------------------------------- %Show results nr=9;%number of results to show %settings cs=3; rs=ceil(nr./cs); figure; for i=1:nr imgFileName=fileList(IX(i)).name; subplot(rs,cs,i); imshow([imgDir,imgFileName]); title(['Rank ',num2str(i)]); end %-------------------------------------------------------------------------
သပ်သပ်ဖယ်ထားတဲ့ test_png ထဲက နမူနာ စက်ဘီးပုံ test image တစ်ခု ပေးလိုက်တဲ့ အခါ training_png ထဲက စက်ဘီးပုံ တွေကို စက္ကန့် အနည်းငယ် အတွင်း မှန်ကန်စွာ ထုတ်ပေးနိုင်တာ တွေ့ရပြီး၊ လူပုံ ပေးကြည့်တဲ့ အခါမှာ လည်း ခပ်ဆင်ဆင် လူပုံတွေကို ထုတ်ပေးနိုင်တာကို တွေ့ရပါတယ်။
ရေးထားတဲ့ ကုဒ်ဖိုင်တွေကို ဒီမှာ download လုပ်နိုင်ပါတယ်။
No comments:
Post a Comment