คลังเก็บหมวดหมู่: Embedded

ทดลองทำ OCR บน Raspberry Pi 2

วันก่อนได้ทดลองทำงานต้นแบบอ่านตัวเลข  หรือการทำ OCR ด้วย tesseract โดยเริ่มจากขั้นตอนที่ขาดไม่ได้ คือ การปรับปรุงภาพให้สามารถทำการอ่านได้ดีที่สุด โดยการใช้ OpenCV และทำการแสดงผลบนจอ LCD โดยเขียนโปรแกรมบน Qt รันบน Linux และใช้ Raspberry Pi 2

ก็เป็นการหยิบ r-pi 2 มาใช้เป็นครั้งแรกเลย ตอนแรกว่าจะเอามาลอง Windows 10 ซะหน่อย แต่จนแล้วจนรอดก็ยังไม่มีโอกาสเลยครับ เลยเอามาลองกับงานนี้ก่อน ขั้นตอนการทำงานของผม เป็นดังนี้ครับ

1. ทดสอบการเก็บภาพก่อน ว่าต้องใช้แหล่งกำเนิดแสง ช่วยมั้ย ต้องใช้เลนส์ขนาดเท่าไร ระยะติดตั้งควรเป็นเท่าไร เสร็จแล้วก็ลองทำออกมา
2. จากนั้น ก็เริ่มหาขั้นตอนการทำ image processing ตรงนี้โปรแกรมอย่าง gimp ช่วยได้มากเลยครับ ทดลองปรับปรุงภาพด้วย filter แบบต่างๆ จดบันทึกขั้นตอนเอาไว้ แล้วก็ลองเขียนด้วย OpenCV และลองเอาไปทำ OCR ด้วย tesseract เมื่อได้ผลลัพธ์ที่ต้องการแล้วก็ เขียนโปรแกรมด้วย Qt
3. เดี๋ยวนี้ผมไม่ค่อยอยากเขียน UI ด้วย widget ละ ใช้ QML เป็นหลัก ก็เลยใช้ Qt ซึ่งเวลามีน้อย ก็เลยไม่ได้ build Qt เอง ไป download จากคนที่เค้า build มาแล้วเอามาเผยแพร่ แต่ก็เจอปัญหาคือ เค้า build มาแบบ cross platfom ตัว utility ของ Qt เช่น qmake moc ก็จะอยู่บน PC ทางแก้คือ ต้องหัดใช้ cmake เพื่อ build โปรแกรม แทน
4. จากนั้นจึงใส่ sensor และ LED RGB เข้าไปโดยควบคุมผ่าน library ชื่อ WiringPi ซึ่งก็ใช้งานง่ายดีครับ ยกเว้นต้องรัน โปรแกรมด้วย sudo

ก็ประมาณนี้ละครับ ผมไม่ค่อยได้ใส่โค้ดเข้ามาในบล็อก เพราะสามารถหาเอาจากที่อื่นได้อยู่แล้ว ส่วนที่สำคัญคือการเรียนรู้ ไม่ใช่ผลลัพธ์ครับ

เกริ่น QML animations & transitions

Screenshot from 2015-08-06 23:05:48 Screenshot from 2015-08-06 16:59:47

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

ด้วยความตั้งใจแต่เริ่มแรกคือ คำถามที่ค้างคาใจมานานว่า ไม่มีอะไรมาแทน flash และ action script เลยเหรอ สำหรับการทำ cg บน tv เพราะโปรแกรมอย่าง CasparCG นั้นก็ใช้ flash ที่นี้ถ้าเราต้องการทำระบบ live streaming เองละ จะใส่กราฟิกและอนิเมชั่นลงไปได้ยังงัย

คราวก่อนผมลอง cairo overlay ลงบน gstreamer element แค่ใช้เวลาเอา svg ขึ้นเนี่ยก็นานแล้วครับ และถ้าต้องโหลดเยอะๆ ดูเหมือนก็จะมีผลต่อ performance เหมือนกัน

คราวนี้เลยลองใหม่ ใช้วิธีเขียน QML application เลย แล้วค่อยทำ screencast เฉพาะส่วน ผมลองเอาไปถ่ายทอดสดลงบน youtube ก็ได้ดังที่เห็น

อ่าว หมดแรงเล่าซะละ ต่อคราวหน้าครับ

credit : กราฟิกสนาม Designed by Freepik.com

Barcode scanner hooking

กลับมาหัดเขียน win32 API อีกครั้ง หลังจากมาเขียน Qt อยู่นาน (เมื่อ 15-16 ปีก่อน บ้ามากถึงขนาดไปสอบจนได้ cer MCSD Visual C++ มา แล้วหลังจากนั้นไม่นานมันก็ออก .net มา ฮือ ฮือ) เป็นโปรแกรมเล็กๆตัวนึง ทำอะไรไปบ้าง จะมาเล่าให้ฟังครับ อิอิ
requirement คือต้องการโปรแกรมที่เอาไปดักจับข้อมูลจากเครื่องสแกนบาร์โค้ด โดยที่ระบบเค้าก็ทำงานไปปกติ โดยข้อมูลจะเอาไปล็อกไว้ผ่านทาง TCP
จริงๆ SI ก็หาโซลูชั่นได้แล้วใช้แอพสองตัวช่วยกันแต่ติดที่ลิขสิทธิ์เพราะต้องไปลงใน POS หลายเครื่องก็หลายเงินอยู่ ก็เลยต้องหาทางเขียนเอา
ปัญหาที่ต้องหาวิธีแก้คือ ดักจับข้อมูลเฉพาะบาร์โค้ด ไม่ไปยุ่งกับการทำงานเดิม และส่งข้อมูลผ่าน TCP
เรื่องแรกก็ต้องหาทางรู้ก่อนว่าจะดักจับ data จาก HID ตัวไหน(ที่มันเป็น barcode scanner)
เรื่องดักจับข้อมูล ตอนแรกว่าจะใช้ hooking ก็เลยหาวิธีที่สะดวกกว่าได้ เพราะ ใช้ hooking คุ้นๆว่าตัว anti ไวรัส มักจะฟ้อง
เรื่องตัวโปรแกรม ก็ทำให้มันไม่มีหน้าตา(GUI) จะได้ไม่ไปเกะกะหน้าจอเค้า รับแต่ windows message ได้อย่างเดียวพอ จะทำเป็น service ก็ยุ่งยากไป
เรื่องสร้าง tcp server คอยส่ง data ให้ client เนื่องจากอยากให้มันเป็น async เลยใช้แบบ WSAASYNCSELECT ไม่ต้องมี thread ให้ยุ่งยาก รองรับ client ตัวเดียว สบายไป
เรื่องปวดหัวสุดท้ายอยู่ที่ data เนี่ยละ มันเข้ามาเป็นแบบเสมือนเรากด keyboard (virtual key) ลองนึกถึงการกด shift หรือ ctrl ตามด้วย key แล้วต้องแปลงข้อมูลเป็น char array ส่งผ่านเน็ตเวอร์ค อันนี้ก็หาทางแปลงไปมั่วๆ ออกมาได้
ทีนี้โปรแกรมตัวมันเล็กทำงานน้อยๆก็เลยจะไม่ใช้ Qt จะได้สะดวกตอนเอาไป install เลยกลับไปเขียน VC++ เพียวๆ ที่ไม่ได้เขียนนานมากแล้ว
เสร็จละครับ โปรแแกรมเล็กๆตัวนึง

QR code generator and Printing

หลังจากที่ได้เขียนตัวอ่าน QR code ไปแล้ว ก็ถึงคราวต้องทำ ตัว generator ละครับ สร้างขึ้นมาอย่างเดียวไม่พอ ก็ต้องปรินท์ออกมาได้ด้วยถึงจะนำไปใช้ประโยชน์ได้ครับ

ผมใช้ libPrison ในการสร้าง QR ก็สะดวกง่ายดายดีครับ ในส่วนของการปรินท์ Qt ก็ให้ API มาให้ค่อนข้างดีทีเดียว การเรียกใช้ print preview dialog การเพิ่มจำนวนหน้า ทำได้ไม่ยากเลย

เหลือที่จุกจิกกวนใจก็ตรงการกำหนดขนาดและทำการ resize สิ่งที่เราจะวาดให้ตรงกับขนาดของกระดาษที่เราจะพิมพ์นั่นละครับ ผมใช้วิธี resize และ render widget เอาเลย โดยทำ widget ที่มีส่วนประกอบและวาง layout ดังรูป กำหนดขนาดและจำนวนที่จะ render ให้พอดีกับขนาดของกระดาษโดยประมาณเอา

10872676_564210363713443_2086052009_n1

ทำระบบคาราโอเกะ Karaoke with PCDuino3 Nano

เมื่อทำการทดสอบ 2d/3d ไปแล้ว ทีนี้มาลองทดสอบ multimedia กันบ้างครับ โดยข้อมูลจาก linux-sunxi เค้าบอกว่า เราสามารถเล่นไฟล์มัลติมีเดียได้โดยอาศัย vdpau ผ่านทางโปรแกรม mplayer

แต่เมื่อทดลองใช้งานแล้วปรากฎว่า ตัวที่ทางผู้ผลิต install มาให้นั้น น่าจะเป็นเวอร์ชั่นเก่าครับ ต้องลง mplayer2 จาก repository แทนมันถึงจะไปเรียกใช้ vdpau ได้ แต่ก็ดูเหมือนจะมีปัญหาอีก ตรงนี้คงต้องหาข้อมูลต่อ เพราะหลายๆคนแนะนำให้ไปใช้ mpv ซึ่ง fork มาจาก mplayer แทน

พอดีถนัดใช้งาน gstreamer เลยตัดสินใจลง gstreamer 0.10 และทดสอบใช้งานดู ปรากฎว่าเล่นได้ครับ

ผมทดลองเล่นไฟล์ h.264 1080p โดยไม่ใช้ความสามารถของ hardware decoder ช่วย ก็ไม่สามารถเล่นได้อย่างราบรื่นนะครับ แถมกิน cpu ไปหมดทั้งสองคอร์ เมื่อเปลี่ยนมาใช้ vdpau ช่วย ก็สามารถเล่นได้สบายๆครับ

เมื่อผ่านขั้นตอนทดสอบความสามารถก็มาถึงขั้นตอนการพัฒนาอะไรขึ้นมาบ้าง โดยมีโจทย์มาให้ทำระบบเล่นคาราโอเกะ ครับโดยมีความสามารถในการตัดเสียงร้องออกได้ (กรณีที่ไฟล์ต้นฉบับ ใส่เสียงร้องไว้ channel หนึ่งนะครับ) ก็เลยลองทำโดยการใช้วิธี ตัดเสียงจาก channel เดิม ออก แล้วใส่ เสียงจากอีก channel เข้าไปแทน จึงกลายเป็น mono 2 channels ( LR -> LL or RR )  ทำให้เสียงยังคงออกลำโพงทั้งสองข้างได้

20141027142125-s

ก็ทดลองทำให้มันสลับไปมาได้ กว่าจะทำเสร็จก็ร้องเล่นเองไปหลายรอบๆ อิอิ

อันนี้ก็เป็นตัวอย่างหนึ่งในการใช้งานบอร์ดนี้นะครับ ข้อดีอย่างที่บอกไป ลดการใช้พลังงาน ลดต้นทุน ได้หลายๆครับ

QR decoder app on Android

Screenshot_2014-09-23-18-27-55

คราวก่อน เขียนโปรแกรม QR decoder บน pc ไปแล้ว วันนี้เป็นการทดสอบเอาโปรแกรมไปรันบนเครื่องแอนดรอยด์ จุดที่น่าสนใจคือ การคอมไพล์ zbar library ด้วย ndk ส่วนหนึ่งผมทำตามแนะนำจากเว็บนี้ http://www.blackdogfoundry.com/blog/zbar-bar-code-qr-code-reader-android/ เพื่อให้ได้ libzbar.so และ ฟังก์ชั่นการ decode ภาพออกมา

ส่วนต่อมาคือการเอาไปใช้ ผมเขียนด้วย QML ดัดแปลงจาก https://www.ics.com/blog/qt-5-multimedia-qml-elements#.VCFtHdazCfg ซึ่งจริงๆก็คล้ายๆกับ ใน document ของ Qt เองครับ จุดที่น่าสนใจอีกจุดคือการทำให้ QML สามารถเรียกฟังก์ชั่น decode ใน C++ ได้

และส่วนสุดท้ายครับ คือการ deploy หรือการนำโปรแกรมขึ้นไปรันบนอุปกรณ์ที่เป็น Android จริงๆ ซึ่งประเด็นอยู่ที่การนำเอา libzbar.so ใส่เข้าไปด้วย ก็ศึกษาได้จาก http://www.kdab.com/qt-android-episode-3/

การเขียนโปรแกรมครั้งเดียวแล้วสามารถรันได้หลายๆแพลตฟอร์มด้วย Qt เป็นอะไรที่เจ๋งจริงๆเลยครับ อิอิ

Machine Vision

วันก่อนได้มีโอกาสทำชุดเดโม machine vision ด้วย Linux, Qt, OpenCV ครับ เลยมีโอกาสได้เปรียบเทียบการใช้งานระหว่างกล้อง usb webcam ธรรมดา กับ กล้องที่ใช้ในงานอุตสาหกรรม

ผมคิดว่าส่วนที่แตกต่างกันมันก็คือเรื่องของ hardware นั่นละครับ เพื่อให้ได้ภาพที่ดีที่สุดเอาไปประมวลผล ซึ่งก็จะทำให้ลดเวลาในการทำ pre-processing ไปได้เยอะ ซึ่งตรงนี้สำคัญมากครับ เพราะแต่ละขั้นตอนหมายถึงเวลาที่ต้องใช้ cpu ประมวลผล ถ้าใช้ขั้นตอนมากก็เสียเวลามาก อาจชดเชยด้วยการใช้คอมสเป็คสูงๆ แต่ก็ไม่แน่ว่าจะช่วยได้เสมอไป ที่สำคัญงานส่วนใหญ่ต้องการความเร็วในการประมวลซะด้วยสิ ดูได้จากเสป็คของกล้องที่มีการรองรับ fps สูงๆ ระดับ 100 fps ขึ้นไป แต่ถามว่าจะทำยังงัยเพื่อให้ประมวลผลแล้วยังได้เฟรมเรทที่ระดับนี้อยู่ ซึ่งกล้องอุตสาหกรรมก็สามารถตอบโจทย์ตรงนี้ได้(ราคาก็สูงกว่ามาก) แต่ถ้าเพื่อการศึกษาหรือทดลอง OpenCV ผมว่าใช้กล้องธรรมดาก็พอได้ครับ

อีกเรื่องคือการ support Linux ของกล้องยี่ห้อต่างๆ มันไม่ใช่แค่ driver ยังต้องรวมถึง sdk ด้วย อย่างที่ผมได้ทดลองทำเดโม เป็นการใช้งานกล้อง Basler ที่มี interface แบบ GigE ก็จะมี pylon sdk มาให้ซึ่งเป็น c++ framework ก็ต้องนั่งศึกษากันไป หรืออย่างของ Imaging Source ก็ค่อนข้างจะสนับสนุนระบบพื้นฐานของ Linux โดยทั่วไปไม่ต้องลง driver ให้ยุ่งยาก เช่น interface USB ก็ใช้ uvc driver กับ v4l2 เนี่ยแหละ แถมยังมี gstreamer plugin ให้ใช้ด้วย ซึ่งส่วนตัวค่อนข้างประทับใจ

อย่างไรก็ดี หากเราได้ภาพมาแล้วเรื่อง api ของกล้องคงไม่ใช่ประเด็นแล้วครับ อย่างกล้องที่ผมได้มีโอกาสใช้งานทำเดโม ก็คือของ Basler ซึ่งใช้ interface แบบ GigE ก็เสียเวลาศึกษาและเขียนโมดูลเพื่อจะเอาภาพออกมาจากกล้องส่งต่อให้ OpenCV เพิ่มขึ้นนิดหน่อย

อีกส่วนหนึ่งก็คือ GUI ครับ เมื่อตะกี้เราพูดถึงการนำภาพจากกล้องผ่าน api ของมันมาส่งให้ OpenCv แน่นอนก็ต้องมีการ copy memory หรือก็อปปี้เฟรมมา ในระหว่างการทำ image processing เรายังอาจต้องมีการ copy ภาพทั้ง frame อีก รวมถึงเมื่อส่งต่อให้ GUI มาวาดทำการแสดงผล อย่างเช่นที่ผมทำไป อย่างน้อยก็มีการ copy จาก api ของกล้องมาเป็น cv::Mat และในขั้นตอนสุดท้ายอยากเอาไปแสดงผล ก็ต้อง copy เป็น QImage สำหรับ Qt อีกที จากที่ลองทำ ซึ่งใช้ thread และ buffer เพื่อแยกระหว่าง การรับภาพเข้ามา และ การประมวลผล ก็ยังดูว่าใช้ cpu มากพอควร

สิ่งที่อยากทำต่อไปคือ ทดลองเอา gpu เข้ามาช่วยทั้งในเรื่องของการแสดงผลและการทำ image processing เช่น OpenGL, cuda หรือ OpenCL ซึ่ง OpenCV ก็ดูจะ support ตรงนี้ด้วย คงต้องไปศึกษาเพิ่มเติมก่อนครับ

ก็ประมาณนี้ จากการที่ได้กลับมาทำ image processing อยู่สามสี่วัน หลังจากไม่ได้ทำมานานหลายปี

Streaming Server : beta version

ตัว beta เสร็จละครับ ลองดูการทำงานของมันจากวิดิโอดูนะครับ แผนงานต่อไป คือ ทำ โปรแกรม signage ฝั่ง client ให้เนียนๆ ใช้งานง่าย

Linux DVR demo program

ความเดิมจากตอนที่ แนะนำ ฮาร์ดแวร์ซึ่งก็คือ DVR card จาก Adlink และ Yuan  ไปแล้ว วันนี้จะมาเดโมให้ดูกับโปรแกรมที่เพิ่งเขียนขึ้นมาใหม่ครับ ( เขียนตอนหยุดปีใหม่นี่เอง เสร็จตอนเวลาข้ามเที่ยงคืนวันสิ้นปีมาหน่อยเดียว อิอิ ) โดยโปรแกรมนี้รันบน Kubuntu ด้วยเครื่อง VIA VB8001 จับคู่กับ Yuan ตัวเก่านั่นแล

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

ระบบนี้ประกอบด้วยสองโปรแกรม ตัวแรกรันเป็น backend รับสัญญาณภาพจาก DVR มาทั้ง 4 แชนแนล โปรแกรมตัวที่สอง คือตัวแสดงผลภาพที่ส่งมาจากโปรแกรม backend และรอรับอินพุตจากคีย์บอร์ด ที่สามารถกดคีย์เพื่อเลือกดูทีละแชนแนลก็ได้ หรือ ดูรวม 4 แชนแนลก็ได้ โดยผมใช้ DBUS ตรงนี้แหละ เมื่อมีการกดคีย์บอร์ดในโปรแกรมแสดงผล ก็จะเป็นการเรียกเมธอดแบบข้ามโปรเซสไปที่โปรแกรม backend เพื่อเป็นการเลือกแชนแนลของสัญญาณภาพจะที่ส่งออกมา ผมใช้วิธีนี้เพราะเดี๋ยวจะเอาไปไว้ควบคุมโปรแกรมที่ใช้บันทึกวิดิโอด้วย

ก็ดูผลลัพธ์ของตัวโปรแกรมทั้งสองเอาละกันครับ จริงๆ ผมทดลองเอา module GPS + บอร์ด Arduino ใช้ส่งตำแหน่ง ความเร็ว ออกมาได้แล้ว ( อันนี้ไม่ได้เขียนโปรแกรมเองเลย เอาโค้ดเค้ามาใช้ทั้งหมด แค่ออกแรงบัดกรีนิดหน่อย ) ว่าจะเอามาเขียน overlay ทับลงบนภาพวิดิโอ แต่ขอยกไว้ตอนต่อๆไปละกัน เพราะโมดูล GPS ที่ว่ามันของถูกๆจากบ้านหม้อ พอเข้าบ้านแล้วมั่วเลย (แต่ลองบนรถตอนขากลับมาจากต่างจังหวัด ก็ถูกต้องรวดเร็วดีนะ)

หมายเหตุ : ผมขอแก้หน่อย ชอบบอกว่า DBUS คล้าย DCOM อยู่เรื่อย จริงๆแล้วยังไม่ใช่นะครับ ยังไม่ถึงขนาดนั้น ถ้าให้เจาะจงจริงๆ มันเหมือน COM แบบ out of process มากกว่าครับ