Category Archives: Programming

Switch to Conjugate Gradient

Since I posted about autoencoder neural network on my blog (2 years ago), there are many people visit my Github for that code, Hooray !! Thank you very much everyone. And again I have a new update for that code. I switch to use Conjugate Gradient instead of generative back-propagation. Someone may think is that take 2 years to update it, NO but i’m too lazy.

While I posting autoencoder article, I realize that we need better than normal backpropagation. So I try to explore “What is the easy way to change and what algorithm to swiched to?”. Then I found that in scipy library, it contains optimization algorithm in scipy.optimize module. So you can change the optimization algorithm whatever you want that build within scipy.optimize module. This link is refer to Github page of old autoencoder but the Conjugate Gradient is on conjugate branch.

Why do I switch to Conjugate Gradient? After I study UFLDL lesson within advance optimization part. There is a phrase say that Conjugate Gradient is better than Gradient Descent (Classic Back-propagation). So I started to study about Conjugate Descent and other advance optimization, but I don’t understand them. Finally, I found out the workaround to improve my implementation by using scipy library. If anyone have any suggestion, please comment. Thanks.

Object detection using OpenCV

หลังจากที่ห่างหายไปนานมากเป็นปีเลยทีเดียว วันนี้ก็ได้กลับมาเขียนอีกครั้ง ก็ไม่มีอะไรจะแก้ตัวครับขี้เกียจเป็นหลัก ในวันนี้จะนำเสนอเรื่อง Object detection โดยใช้ HOG และ SVM ผ่านไลบรารี่ OpenCV ซึ่งจริงๆ ใน GitHub ของ OpenCV มีโค้ดส่วนนี้อยู่แล้ว อยู่ใน samples/cpp/train_HOG.cpp ในบทความนี้แค่มาใช้ให้ดูเท่านั้นครับ สำหรับผมใช้ Ubuntu 14.04 และ OpenCV เวอร์ชัน 3 ในการพัฒนาโปรเจคนี้ครับ

ภาพรวมของโปรเจคนี้มีสองขั้นตอนครับ คือเตรียมข้อมูลและ Train model ซึ่งเป็นหน้าที่ของโค้ด train_HOG ของ OpenCV การทำงานของ train_HOG.cpp คือการนำข้อมูลนำเข้าทั้ง Positive และ Negative ไป train โมเดล linear SVM ซึ่งมีการปรับแก้ไขโค้ดเล็กน้อยเพื่อให้เข้ากับโปรเจคที่เราจะทำ นั่นคือการทำ iPhone detection สามารถเข้าไปดูได้ที่ link นี้

ขั้นตอนแรก การเตรียมข้อมูล ข้อมูลประกอบด้วยข้อมูลสองชนิด (Positive, Negative) เริ่มต้นจาก Negative มันคือภาพที่ไม่ใช่วัตถุที่เราจะตรวจจับ ซึ่งเอามาจาก link นี้ ส่วนภาพวัตถุที่จะตรวจจับเราสามารถสร้างเองก็ได้แต่ในที่นี้จะใช้วิธี populate ขึ้นมาจากตัวอย่างที่มีอยู่หนึ่งภาพโดยใช้ opencv_creasamples หลักการคือโปรแกรมจะเอาภาพตัวอย่างไปหมุนและแปะลงบนภาพ Negative เช่นตัวอย่างด้านล่าง

Generated Data

โดยใช้คำสั่งตามข้างล่างนี้

# opencv_createsamples -img images/iphone.jpg -bg negatives/negatives.txt -info positives/positives.txt -num 3000 -bgcolor 255 -bgthresh 8 -w 40 -h 80 -maxxangle 0.5 -maxyangle 0.5

ซึ่งการจะใช้โปรแกรม opencv_createsamples จำเป็นต้องมีไฟล์ negatives.txt ซึ่งคือไฟล์ที่มีรายชื่อของภาพที่จะใช้ ซึ่งเราสามารถสร้างได้โดยใช้คำสั่งข้างล่างนี้

# ls -1 negatives/ > negatives/negatives.txt

และขั้นตอนต่อไปคือการ Train model โดยใช้ train_HOG.cpp ซึ่งสิ่งที่ต้องมีเพื่อใช้กับโปรแกรม train_HOG คือภาพ negative 1 โฟลเดอร์ และภาพ positive 1 โฟลเดอร์ พร้อมด้วยไฟล์ .txt ที่มีรายชื่อของไฟล์ภาพทั้งหมด เพียงเท่านี้เราก็สามารถ train HOG SVM ได้แล้ว แต่สำหรับโค้ดผมจะมีการโหลดภาพทดสอบ เพื่อทดสอบโมเดลที่เรา train มาด้วย โดยคำสั่งที่ใช้ train ตามนี้ครับ

# ./train_HOG --pd=positives/ -p=positives.txt -nd=negatives/ -n=negatives.txt

ภาพผลลัพธ์ทางนี้เลยยังไม่สมบูรณ์มากแต่ก็พอเป็นแนวทางในการริเริ่มทำ object detection ของวัตถุอื่นๆ ได้ครับ ขอบอกว่า ณ ตอนนี้ OpenCV รองรับเพียง linear model ถ้าว่างๆ ผมจะลองพัฒนาโค้ดให้สามารถรับ rbf model ได้ละกัน แล้วก็ใครรู็สึกว่า model ไม่ค่อยดีเท่าไหร่ ลองดู reference ข้างล่างมีวิธีการ train แบบ Haar Cascade อยู่ ซึ่งหลายคนบอกว่าให้ผลดีกว่า HOG SVM แต่ใช้เวลาในการ train นานมาก กอไก่หลายตัว ก็ลองทำตามกันดูครับ ถ้าใครมีผลลัพธ์อย่างไรเอามาแนะนำและแบ่งปันกันก็ได้ครับ (ขอขอบคุณภาพจาก http://kooc.market/)

Using Thai font on FPDF

หายไปนานนะครับ ต้องบอกเลยว่าหาเนื้อหามาลงไม่ได้เลยในช่วงที่ผ่านมา นี่ก็โพสแรกของปีก็ว่าได้เดือนเมษาเลยนะ สำหรับช่วงนี้ผมได้มีโอกาสรับงานเกี่ยวกับการทำ PHP Web Application ซึ่งมีฟีเจอร์ต้องทำรายงาน (Report) ให้กับลูกค้าด้วย ก็หาวิธีมาหลายทางจบด้วยวิธีการที่ว่าให้เซิฟเวอร์สร้างรายงานในรูปแบบ PDF ออกมาเลยดีกว่าลูกค้าถึงไม่ปรินท์ก็สามารถบันทึกส่งเป็นเมล์ได้ ซึ่งไลบารี่ที่ใช้คือ FPDF (Free PDF) ซึ่งเป็นไลบารี่ของภาษา PHP เท่านั้นนะครับ

แต่แล้วก็เกิดปัญหาขึ้นคือจำเป็นต้องทำรายงานออกมาเป็นภาษาไทยครับ แต่ FPDF เนี่ยไม่มี font ภาษาไทยมาให้จำเป็นต้องสร้าง font ภาษาไทยขึ้นมาเองครับ ขั้นตอนการสร้าง font นี่ก็ไม่ยากสามารถไปทำตามได้ที่เว็บไซต์ FPDF > Tutorial > Tutorial ที่ 7 ครับ บอกเลยว่าไม่ยากอย่างที่คิด ซึ่งภาษาไทยใช้ cp874 นะครับ (แต่ถ้าขี้เกียจทำตอนท้ายของบทความมีให้ Download ได้ครับ ซึ่งมี THSarabun กับ Tahoma) เมื่อสร้างแล้วการที่จะนำไปใช้เนี่ยก็ง่ายมากครับ อย่างแรกให้ copy ไฟล์ THSarabunNew.php และ THSarabunNew.z ไว้ในโฟลเดอร์ font ของไลบารี่ fpdf จากนั้นเพียงแค่ AddFont เข้าไปก่อนการเรียกใช้ แล้วก็เรียกใช้ได้เลย ตามตัวอย่างโค้ดข้างล่าง แค่นี้ก็สร้างรายงานแบบ PDF ส่งลูกค้าได้แล้วครับ

<?php 
require('fpdf.php'); 

$pdf = new FPDF(); 
// Add Thai font 
$pdf->AddFont('THSarabunNew','','THSarabunNew.php');
$pdf->AddFont('THSarabunNew','B','THSarabunNew_b.php');
$pdf->AddPage();
$pdf->SetFont('THSarabunNew','',16);
$pdf->Cell(40, 10, iconv('UTF-8', 'cp874', 'สวัสดี'));
$pdf->SetFont('THSarabunNew','B',16);
$pdf->Cell(40, 10, iconv('UTF-8', 'cp874', 'สวัสดี'));
$pdf->Output();
?>

Download

Mashape : api search engine

ก็วันนี้ไม่มีอะไรมาก จะมาแนะนำ เว็บสำหรับคนหา api (mashape) ซึ่งทำออกมาได้ดีมากเลยทีเดียว เป็นเว็บสำหรับให้ผู้ใช้และผู้สร้างได้เชื่อมต่อกันง่ายขึ้น โดยชีวิตปกติของโปรแกรมเมอร์นั้นส่วนมากก็จะไปหาว่า api ไหนเจ๋งและน่าใช้ใน  stackoverflow ถ้ายังงงกับการทำงานก็จะหาต่อใน Github ซึ่งทำให้ไม่รู้การเชื่อมต่อไปยัง api จริงๆว่าต้องทำอย่างไร ทำให้เสียเวลากับการหา api และนำมาเปรียบเทียบค่อนข้างยาก mashape จะช่วยเติมเต็มความต้องการเหล่านี้

สำหรับฝั่งผู้ใช้นั้น เว็บ mashape สามารถทำให้เราได้ทดลองใช้ api ได้เร็วขึ้น ติดตามการเปลี่ยนแปลงได้อย่างรวดเร็ว และมีการรองรับถึง 8 ช่องทาง (Curl, Java, Node, PHP, Python, Ruby, Objective C, และ .NET) น่าจะเรียกได้ว่าเป็น one-stop service จริงๆ นอกจากนั้นยังมีเว็บบอร์ดสำหรับพูดคุยถามปัญหากับผู้สร้างได้ นอกจากนั้นตัว mashape เองยังมีระบบจัดการรองรับการทำงานทั้ง การกำหนดสิทธ์ผู้เข้าถึง การแปลงข้อมูลให้เหมาะกับ application ของผู้ใช้ มีทั้ง pricing ให้เราดูด้วยว่า api ไหนราคาเท่าไหร่ และยังสามารถดูแลตรวจสอบ api ได้จากที่หน้าเว็บเพียงแห่งเดียวไม่ต้องเข้าหลายเว็บ นั่นคือมาที่หน้าเว็บนี้ทีเดียวรู้หมดว่า api ไหนเป็นอย่างไรบ้าง และเค้ายังรับประกันว่า 99.9% up time หลายคนอาจจะสงสัยว่าเค้าทำฟรีแล้วได้อะไร หากเราเสียเงินให้เค้าไปแล้วเนี่ย (25$ ต่อเดือน) เค้าจะอนุญาตให้เราเค้าถึง api ที่ไม่ public ให้เราเข้าไปยัง api ที่เค้าขายกันจริงๆ ไม่ opensource ไม่เลิกพัฒนาเป็นต้น สำหรับคนที่เป็นองค์กร สมัครไว้ก็ดีนะ

และหากเป็นผู้สร้าง api ก็บอกได้เลยว่าเป็นแหล่งค้าขายที่น่าทำตลาดมาก เพราะผู้ใช้อยากได้แหล่งหา api อยู่แล้วที่ไม่ใช่ google และ overflow เพราะ mashape จัดการให้เราหมดทุกอย่างเลย ทำให้เราไม่ต้องไปหา layout การจะพูดคุยกับลูกค้าว่าทำยังไงให้เค้ามาใช้ mashape จะจัดรูปแบบให้ผู้ใช้เข้าใจง่าย ทั้งยังมีระบบจัดทำรายงานให้ได้วิเคราะห์ และเรายังไม่ต้องกังวลเรื่องระบบของผู้ใช้ว่าจะใช้ข้อมูลแบบไหน mashape จะแปลงข้อมูลตามที่ผู้ใช้ต้องการ และยังเป็น auto-generate sdk ทั้ง 8 ช่องทางให้อีกด้วย บอกได้เลยว่าเจ๋ง ส่วนของผู้สร้างอาจจะอธิบายไม่ค่อยเห็นภาพเพราะเป็นแต่ผู้ใช้ไง แต่บอกผู้สร้างได้เลยนะว่าเป็นตลาดที่น่าสนใจทีเดียว dev ทุกคนอยากได้เว็บอย่างนี้อยู่แล้ว

สำหรับวันนี้ไม่รูปนะเพราะทำไม่ทันอ่ะ แล้วมันสิ้นเดือนแล้วด้วยไว้คราวหน้าละกันนะ

Using Email with Google App Engine

สวัสดีครับ วันนี้อยากแนะนำ cloud ของ google (ไม่ได้เงินค่าโฆษณาแต่อย่างใด) สำหรับใครที่มองหา Server ฟรีสำหรับทำโปรเจคส่งอาจารย์ เช่น โปรเจคเกี่ยวกับ IoT (Internet of Things) ถ้าเงินไม่มีแนะนำ Google App Engine ครับฟรีถึงแม้โควต้าจะไม่เยอะเท่าไหร่แต่ก็ทำให้ได้ Server ดีๆ ได้เลยทีเดียว ลองเข้าไปศึกษากันได้ที่ Google Cloud Platform

สำหรับ Google App Engine รองรับหลายภาษาไม่ว่าจะเป็น Python Java PHP และ Go (ซึ่งในที่นี้ผมถนัด Python นะบอกเลย–น่าจะเดาได้จากหลายๆ โพสที่ผ่านมา) สำหรับฐานข้อมูลนั้นไม่ได้มี MySQL หรือ MongoDB ที่หลายคนถนัดต้องใช้ App Engine Datastore ซึ่งมีโควต้านับเป็นจำนวนครั้งในการอ่านเขียน และโควต้าของ GAE นั้นนับเป็นวันครับ ถ้าวันนั้นใช้เกินโควต้าเว็บหรือเซอร์วิสที่เราพัฒนาจะไม่สามารถเข้าใช้งานได้ ก็รอไปจนครบ 24 ชม (ระหว่างนั้นก็ไปช้อปปิ้ง เล่นเกม) แล้วระบบจะรีเซ็ทให้เหลือศูนย์ใหม่ แล้วก็จะเข้าเว็บได้เหมือนเดิม เหมาะสำหรับผู้ริเริ่มอะไรใหม่ๆ

วันนี้จะแนะนำการใช้เซอร์วิส Email ของ GAE นะครับ นอกจากจะโฮสเว็บได้แล้วยังมีระบบรับส่งอีเมล์ให้เราได้ใช้อีกด้วย สำหรับโค้ดสามารถหาได้จาก SimpleEmailGAE ซึ่งผมเขียนไว้เองแหละ ผู้อ่านสามารถเอาไปต่อยอดไปศึกษา (เดา) จากโค้ดกันได้แน่นอน โค้ดไม่ได้ซับซ้อนมาก โดยการทำงานของโค้ดคือเมื่อส่งเมล์เข้าเมล์ของแอพนั้น จะทำการส่งเมล์ตอบกลับมาก็เท่านั้นเอง ที่สำคัญคือในไฟล์ app.yaml ใน section handlers ห้ามสลับลำดับมั่วนะครับ เดี๋ยวมันจะทำงานผิด แล้วก็ต้องไปเปลี่ยน sender ในไฟล์ handle_incoming_email.py ให้ตรงกับชื่อแอพที่ลงทะเบียนไว้ด้วยนะครับ

นอกจากนั้น GAE ยังอำนวยความสะดวกให้เราได้โดยที่เราสามารถรัน server แบบ localhost (page – localhost:8080 และ admin panel – localhost:8000) ใน Admin panel สามารถส่งเมล์ ดูข้อมูลที่เราเก็บไว้ใน Datastore และดู log ที่เกิดขึ้นได้ สำหรับการส่งอีเมล์ต้องตั้งค่า SMTP ก่อนถึงจะส่งจาก localhost ได้แต่บน GAE ไม่ต้องตั้งค่าก็ใช้งานได้เลย เมื่อทดสอบได้แล้วก็ลองนำไป Deploy บน GAE ได้เลย

Graphviz with Python

นี่ก็สิ้นเดือนอีกแล้วนะครับ ยังไม่ได้ไปหาเนื้อหาใหม่มาเขียนเลย แต่เนื่องจากตั้งใจไว้ว่าทุกเดือนต้องเขียนอย่างน้อยหนึ่งบทความ วันนี้เลยจะมาเสนอ Tool สำหรับวาดกราฟบน Python สำหรับคนที่จะนำไปทำเขียนเปเปอร์หรืออยากให้โปรแกรมแสดงผลเป็นกราฟนะครับ

Tool ที่จะมานำเสนอชื่อ Graphviz ครับซึ่งสามารถติดตั้งได้โดยคำสั่งข้างล่างนี้ (สำหรับระบบปฎิบัติการ Debian นะครับ)

$ sudo apt-get install graphviz
$ sudo pip install graphviz

สำหรับการใช้งานนะครับ ก็ทำการ import ในโค้ด Python ของเราได้เลย นี่คือตัวอย่างโค้ด

import graphviz as gv

graph = gv.Digraph(format="jpg")
graph.attr('graph',{'rankdir':'LR','splines':'ortho'})

layer = [7,6,5,3,3]
layer_name = ['input', 'L1 AE', 'L2 AE', 'L3 AE', 'output']

# init node
layers = []
for layer_id in range(len(layer)):
        layers.append([])
        subgraph = gv.Digraph(name="cluster%d" % (layer_id))
        subgraph.attr('graph', {'label':layer_name[layer_id]})
        
        for node_id in range(layer[layer_id]):
                node_name = 'L_%d_%d' % (layer_id, node_id)
                layers[layer_id].append(node_name)
                subgraph.node(node_name, label='')
        graph.subgraph(subgraph)

# init full-connected edges
for layer_id in range(len(layer)-2):
        for node_source in layers[layer_id]:
               for node_sink in layers[layer_id+1]:
                        graph.edge(node_source, node_sink)

# final layer
for node_id in range(3):
        graph.edge('L_3_%d' % (node_id), 'L_4_%d' % (node_id))

filename = graph.render(filename='img/neural_net')
print filename

และนี่คือตัวอย่างของภาพที่ได้จากการรันโค้ดข้างบนครับ

Neural Network Structure

Neural Network Structure

การทำงานของโปรแกรมจะทำงานโดยสร้างไฟล์ชนิด dot ขึ้นมาจากนั้นแปลงไฟล์ dot ให้เป็นไฟล์ภาพ เพราะฉะนั้นถ้าอยากได้กราฟที่สวยหรูกว่านี้ต้องลองดู property ต่างๆ จาก link นี้ได้เลยครับ

Easy Panorama with OpenCV

ห่างหายจากการเขียนบล็อคไปนาน เพราะมีภารกิจที่หลายอย่างที่ต้องทำนะครับ จากตอนแรกคิดว่าจะเขียนเดือนละครั้ง เดือนที่แล้วก้ได้พลาดไปอย่างน่าเสียดาย ตอนนี้ก็ใกล้สิ้นเดือนแล้วจึงมาเขียนโพสสั้นๆ เกี่ยวกับการทำภาพพาโนราม่าด้วย OpenCV ไลบรารี่

เริ่มจากอย่างแรกต้องลง OpenCV Library (2.4.8) ก่อนละครับ ซึ่งในที่นี้จะเป็นการ install สำหรับ Ubuntu โดยใช้คำสั่งตามนี้ครับ

$ sudo apt-get install libopencv-dev build-essential

จากนั้นก้โหลดโค้ด (stitching.cpp) และภาพ dataset จาก link นี้นะครับ โดยต้องโหลด CMakeLists.txt มาด้วยเพื่อช่วยให้การ build โปรแกรมง่ายขึ้น โดยใช้คำสั่งข้างล่างนี้

$ cmake . && make

เพื่อตรวจสอบว่าโปรแกรมที่ build มานั้นทำงานได้หรือไม่ทำได้โดยการพิมพ์ ./stitching จากนั้นตัวโปรแกรมจะฟ้องให้ใส่ input images เข้าไปครับ เราก็สามารถใส่ภาพที่เตรียมไว้ให้เข้าไปได้โดยใช้คำสั่งดังนี้

$ ./stitching 1.jpg 2.jpg 3.jpg

จากนั้นเราก้จะได้ภาพพาโนราม่าสวยๆ ในไฟล์ result.jpg ตามข้างล่างนี้ครับ

Panorama 1

Panorama 1

Panorama 2

Panorama 2

Kasetsart University

Kasetsart University

ขอขอบคุณภาพจาก P. MONGKOLPITTAYATHORN, NOPPON UMNAJWANNAPHAN