31 กรกฎาคม 2553

การติดตั้งกล้องและโปรเจคเตอร์บน Pan/Tilt Camera Head

การติดตั้งกล้องและโปรเจคเตอร์บน Pan/Tilt Camera Head

Biclops Camera Head รุ่นนี้ออกแบบมาให้ติดตั้งกล้องที่แกนจุดหมุนของการ Tilt
เพื่อให้ใช้แรงน้อยที่สุดในการเอาชนะแรงโน้มถ่วงของโลก โดยให้เกิดโมเมนต์น้อยที่สุด

ฐานเชื่อมต่อของกล้องกับ Camera Head ไม่ได้ออกแบบมาติดตั้งโปรเจคเตอร์
จึงออกแบบการยึดใหม่ออกมาได้ดังภาพ

ติดตั้งกล้องทางด้านซ้ายและโปรเจคเตอร์ทางทางขวา กลับหัวแบบบนลงล่างทั้งคู่
เมื่อทดสอบการฉาย


แต่เฟรมภาพที่ได้จากกล้องไม่สามารถเห็นภาพการฉายโปรเจคเตอร์ได้ทั้งหมด ประกอบกับแสงของโปรเจคเตอร์ยังมีความเข้มไม่เพียงพอ
ทำให้เห็นภาพจากการฉายเป็นภาพลางๆ ซึ่งอาจทำให้มีผลในการทำ registration เพราะไม่สามารถทราบได้ว่า
แสงที่ฉายไปตรงกับวัตถุหรือไม่ จึงต้องพิจารณา กล้องที่มีประสิทธิภาพดีกว่านี้


ปัญหาอื่นๆ
1. สายสัญญาณติดพื้น ขณะที่ Camera Head ทำ Homing
2. จุดที่ยึดติด โปรเจคเตอร์เป็นแบบ น็อตไขเข้าไป จึงไม่เหมาะกับฐานที่หมุนได้
   เมื่อฐานหมุนหลายๆครั้งน็อตจะคลายตัวเนื่องจากโมเมนต์ไม่เท่ากัน
3. ไม่สามารถร้อยสายสัญญาณโปรเจคเตอร์และกล้อง ที่จุดกลางของ Camera Head
   ได้เนื่องจากหัวเชื่อมต่อใหญ่กว่าช่องว่างที่มีให้

งานที่ต้องทำต่อเพื่อแก้ไขข้อบกพร่อง
1. ตั้งกล้องและโปรเจคเตอร์ให้ใกล้กันกว่านี้
2. ออกแบบฐานการวางโปรเจคเตอร์และกล้องใหม่
3. หาซื้อสายสัญญาณที่หัวเล็กกว่านี้ และ มีความอ่อนตัวกว่านี้


28 กรกฎาคม 2553

โปรเจ็คภาเป็น 3 มิติใช้หลักการฉาย code ภาพเหมือนกัน

ใช้อากาศเป็นฉากโปรเจ็คเตอร์

ที่มา http://www.io2technology.com/specifications

การแสดงผล โปรเจ็คเตอร์ไปยัง ระนาบใดๆ

จอนห์นี ลี ได้โชว์การฉายโปรเจ็คเตอร์ไปยัง ระนาบภาพใดๆ โดยหาตำแหน่งกรอบของภาพจาก แสงที่ฉายออกไปเป็น code ในด้านแนวตั้งและแนวนอน
โดยแบ่งครึ่งภาพไปเรื่อยๆ คล้ายหลักการของเลขฐาน 2
ตัวเซ็นเซอร์ไฟเบอร์ออฟติกที่อยู่ที่มุมของกรอบสีเหลี่ยม
จะเกิด Pulse code ตามแสงที่ได้รับ ทำให้สามารถบอกได้ว่า
มุมนี้อยู่ที่ตำแหน่งใดของและใช้วิธีการ Warp

ARmirai




ที่มา http://pseudospace.blogspot.com/2008/12/figma-mirai-meets-augmented-reality.html

13 กรกฎาคม 2553

สร้างโมเดลการโปรเจคภาพโดยไม่ต้องคำนวณระยะทางระหว่างวัตถุและโปรเจค

สร้างโมเดลการโปรเจคภาพโดยไม่ต้องคำนวณระยะทางระหว่างวัตถุและโปรเจคเตอร์
แนวคิดของหลักการนี้ มาจากสมมติฐานว่า
เมื่อกล้องรับภาพจะเกิดการโปรเจคภาพแบบ Perspective ด้วยเลนส์ของกล้องให้เป็นพิกัด (X,Y)
หากเราสามารถสร้างแสงฉายกลับไปยังพิกัด (X,Y) นั้นจะเกิดภาพกลับไปที่วัตถุ
จึงสร้างออกมาเป็นแบบจำลองทางเลขาคณิตได้ดังนี้

แบบจำลองนี้กล้องและโปรเจคเตอร์อยู่ที่จุดเดียวกัน มองไปที่ตำแหน่งของวัตถุเดียวกัน
ถ้าภาพปรากฏที่ (X,Y) แล้ว เราสามารถสร้างภาพที่ตำแหน่ง (X,Y) เพื่อฉายกลับไปที่วัตถุได้
แต่โมเดลนี้ไม่สามารถเกิดขึ้นจริงได้เนื่องจาก กล้องและโปรเจคเตอร์ไม่สามารถอยู๋ในตำแหน่งเดียวกันได้
มุม Fovy ของกล้องและโปรเจคเตอร์ไม่เท่ากัน กล้องและโปรเจคเตอร์มี Distroion

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

เมื่อวัตถุทั้งชิ้นอยู่ในลักษณะขนานกับแกน Z หรือบิดเบือนไม่มาก จะเกิด Error ไม่เกิน 1%
แต่หากมีความแปรปรวนในแกน Z มากจะมี Error สูงขึ้น

จากภาพจะเกิด Error สูงถึง 7% ซึ่งในความเป็นจริงแล้วการวางวัตถุในลักษณะดังกล่าวเอง
เป็นลักษณะที่ไม่เหมาะสมกับฉายด้วยโปรเจคเตอร์อยู่แล้ว
เพราะจุดบนโปรเจคเตอร์ที่สามารถฉายไปบนวัตถุมีจำนวนน้อย



HCI Trip @นครปฐม

HCI Trip @นครปฐม

เวลา รายการ ระยะ ทางรายละเอียด
6.00 ออกจากฟีโบ้ 46.1 กม. 59 นาที
7.00-13.00 พิพิธภัณฆ์หุ่นขึ้ผึ้ง ไทย
*
http://www.moohin.com/trips/nakhonpathom/model/
ล่องเรือเที่ยวนครปฐม
คลองมหาสวัสดิ์  เลือกซื้อขนม อาหารอร่อยๆ จิบกาแฟโบราณจากร้านกาแฟเก่าแก่
แผนที่ล่องเรือเที่ยว
http://www.moohin.com/018/botemap.shtml
14.00 ลานแสดงช้างและฟาร์ม จระเข้สามพราน17.5 กม ใช้เวลา 23 นาที *
http://www.elephantshow.com/home.htm
19.00 วัดพระปฐมเจดีย์ 25.1 กม. ใช้เวลา 24 นาทีรับประทานอาหารค่ำ ที่ตลาดโต้รุ่ง
ไอติมลอยฟ้า
http://www.moohin.com/trips/nakhonpathom/flyingicecream/
ของกินอร่อย
http://talk.edtguide.com /ตลาดโต้รุ่ง-พระปฐมเจดีย.html

13 มิถุนายน 2553

SURF Speeded Up Robust Features

SURF Speeded Up Robust Features
เป็น feature  ที่ได้รับแรงบันดาลใจมากจา SIFT โดยการใช้ Haar Wavelet มาใช้
ถูกนำเสนอในปี 2006 เป็นเป็น ฟังก์ชันใหม่ที่มีมาใน OpenCV 2.0 และ IVT
อ่าน Paper เพิ่มเติม
อ่าน wiki

Integration Vision Toolkit ทูลคิดสำหร...

Integration Vision Toolkit ทูลคิดสำหรับวิชั่นที่มีพื้นฐานมาจาก OpencV

เป็นไรบารีสำหรับ Computer Vision อีกตัวที่หน้าสนใจ
มาจากทางฝั่งเยอรมัน ที่สำคัญมันมีหนังสือให้อ่าน 1 เล่น อย่างนี้พอสูสีกับ OpenCV หน่อย
เพราะถ้ามีมาให้แต่ library ก็ใช้ไม่เป็นอยู่ดี
http://ivt.sourceforge.net/book.html

สำหรับตัวอย่าง ถึงแม้จะมีน้อยกว่าของ OpenCV
แต่ก็เป็นตัวอย่างที่ดี มี Plattern การเขียนที่น่านำมาเป็นตัวอย่าง
เช่นการทำ fillter การใช้ SURF เพิ่งรู้จักครั้งแรกจากการอ่าน ข้อมูลใน Sample นี่แหละ
http://ivt.sourceforge.net/examples.html


จุดเด่นอีกอย่างก็คือ มีการจัดไลบารี เป็น class แบบ C++ คล้ายกับใน OpenCV 2.0
แต่จากที่ลองมีการจัดเรียงที่ดีกว่ามาก เพราะเริ่มเขียนแบบนี้ตั้งแต่แรกเริ่ม

นอกจากนี้เค้ายังอ้างว่า เร็วกว่า OpenCV ในหลายๆด้าน
  • Undistortion (faster by a factor of 4 compared to cvCalibFilter from the OpenCV)
  • Combined Rectification/Undistortion (faster by a factor of 8 compared to cvCalibFilter from the OpenCV)
  • Harris Corner Detector (faster by a factor of 1.4 compared to the OpenCV implementation)
  • SIFT Features and kd-tree feature matching
  • Calibration: fully integrated single and stereo camera model (compatible with OpenCV calibration)
  • Many filters, resize, Bayer2RGB, RGB2HSV, SVD, PCA, Linear Least Squares, drawing, ...
  • POSIT (pose estimation on the basis of 2D-3D point correspondences)
  • Core function of the ICP (pose estimation on the basis of 3D-3D point correspondences

ใครสนใจเข้าไปโหลดมาลองเล่นได้ที่
http://ivt.sourceforge.net/index.html

ปล. ตัวอย่าง Fast Harris-SIFT features / kd-tree matching / RANSAC ผมรันไม่ผ่าน ใครรันได้ช่วยบอกวิธีด้วยนะครับ

11 มิถุนายน 2553

สรุปหุ่นยนต์เล่นลูกบิด

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

หัวข้อโครงงาน เดอะเทอร์มิเนเตอร์: หุ่นยนต์แก้ปัญหาลูกบิด
                          (The Terminator: Robotic Rubik Solver)

ผู้วิจัย : นายเนมินทร์ สุขเสน นายสรุจ พันธุ์จันทร์ นายนวคุณ ศรีบาง นายทินกร ภูสีดิน และนายศุภชัย ไชยสงคราม

อาจารย์ที่ปรึกษา : รศ.ดร.สยาม เจริญเสียง และดร.อาบทิพย์ ธีรวงศ์กิจ

 


บทนำ

ลูกบิดเป็นเกมการละเล่นที่สนุกสนานมีส่วนช่วยในการพัฒนาสมองของผู้เล่น ซึ่งการพัฒนาหุ่นยนต์ให้สามารถเล่นลูกบิดเช่นเดียวกับมนุษย์ได้นั้นมีส่วนประกอบดังต่อไปนี้ ระบบวิชันทำหน้าที่เสมือนดวงตา ระบบคอมพิวเตอร์ทำหน้าที่เสมือนสมอง ระบบแขนกลทำหน้าที่เสมือนแขนและนิ้วมือ จากการทดลอง หุ่นยนต์สามารถทำงานได้ถูกต้อง และเล่นลูกบิดได้เสร็จภายในเวลา 14 นาที

ปัญหา

ลูกบิดขนาด 3x3x3 รูปทรงสี่เหลี่ยมจะมีทั้งหมด 6 หน้าด้วยกัน แต่ละหน้าหมุนได้ 3 แบบรวม 18 แบบทำให้ลูกบิดสามารถสลับสับเปลี่ยนหน้าได้ถึง 8!x38x12!x210 แบบหรือประมาณ 43 ล้านล้านล้านแบบ

แนวทางการวิจัย

ทีมงานได้ออกแบบแขนกลที่มีองศาอิสระ 4 องศาเคลื่อนที่อยู่บนระนาบ 2 มิติ ที่ปลายแขนกลติดตั้งกริปเปอร์ซึ่งสามารถหมุน และจับลูกบิดได้ จากรูปร่างที่ออกแบบนี้เองทำให้ตัวแขนกลสามารถเข้าถึงลูกบิดได้ 2 หน้า กระบวนการที่หุ่นยนต์ใช้แก้ปัญหาลูกบิดประกอบด้วนขั้นตอน 3 ขั้นตอนดังนี้

1.        อ่านสีทั้ง 6 หน้าของลูกบิดด้วยระบบวิชัน

2.        ประมวลผลรูปแบบการบิด ด้วยระบบคอมพิวเตอร์ ซึ่งจะได้ท่าทางในการบิดประมาณ 100 ครั้ง

3.        เมื่อได้ท่าทางในการบิดและหน้าที่บิดต้องทำการหมุนหน้านั้นให้มาอยู่หน้าที่แขนกลสามารถเข้าถึงได

4.        ทำซ้ำข้อ 3 จนกระทั่งการบิดเสร็จสิ้น

                 


ผลที่คาดหมาย

หุ่นยนต์สามารถแก้ปัญหาลูกบิดได้โดยอัตโนมัติ อย่างถูกต้อง

เอกสารอ้างอิง

 [1] Craig, J.J., Introduction to robotics: mechanics and control. 2004: Prentice Hall.

[2] Corke, P.I., A Robotics Toolbox for MATLAB. IEEE Robotics and Automation Magazine, 1996. 3: p. 24-32


ดาวน์โหลด PDF ได้ที่นี่


 


ทดลองฉายภาพจากโปรเจ็คเตอร์ลงบนภาพ 3 มิติ

ทดลองฉายภาพจากโปรเจ็คเตอร์ลงบนภาพ 3 มิติ

จัดองค์ประกอบการทดลองดังนี้
ระยะระหว่างกล่องถึงprojector 110 ซม.
พารามิเตอร์ของ projector คือ
    fovy =33.5
    อัตราส่วน 4/3
    อยู่ห่างจากวัตถุ 190 ซม.
   

ได้ sourc code ดังนี้
#include <GL/glut.h>
void init(void)
{
    //glEnable (GL_DEPTH_TEST); //enable the depth testing
 //   glEnable (GL_LIGHTING); //enable the lighting
 //   glEnable (GL_LIGHT0); //enable LIGHT0, our Diffuse Light
 //   glShadeModel (GL_SMOOTH); //set the shader to smooth shader
    
    glClearColor (0.0, 0.0, 0.0, 0.0);

    glShadeModel (GL_FLAT);
    


    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective(33.5, 4.0/3.0, 140.0, 190);

}
void cube (void) {
    float i;
    for (
i=0;i<50;i++)
    {
    glTranslated(1, 0, 1);
    glPushMatrix();
    glutSolidCube(2); //draw the cube
    glPopMatrix();
    }
}
void display(void)
{
        glMatrixMode(GL_MODELVIEW);
    glLoadIdentity ();
    gluLookAt
    (
        0.0, 0.0, 190.0,/* camera */
        0.0, 0.0, 0.0,    /* lens towards */
        0.0, 1.0, 0.0   /* up-vector */
    );
    glClear (GL_COLOR_BUFFER_BIT);

    glPolygonMode(GL_FRONT,GL_FILL);
    glPolygonMode(GL_BACK, GL_LINE);
 
    glColor3f (1.0, 0., 0.);
    glutWireSphere(1, 32, 32);
   
    glColor3f (1.0, 1.0, 1.0);
    glRotatef(45.0, 0.0, 1.0, 0.0);
    glutWireCube (50);

    //glTranslatef(0., 0., 10.);
    glutWireSphere(10, 32, 32);
               /* drawing Cube */
    //cube();
    //glutSwapBuffers(); //swap the buffers

    glFlush ();
}

void reshape (int w, int h)
{
    glViewport (0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode (GL_MODELVIEW);
}

void keyboard (unsigned char key, int x, int y) {
    /*
    * Press ESC Key
    */
    if (key==27)
    {
    glutLeaveGameMode(); //set the resolution how it was
    exit(0); //quit the program
    }
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    //glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
    //glutInitDisplayMode  (GLUT_DOUBLE  | GLUT_DEPTH);
    /*
    * the settings for fullscreen mode
    */
    //glutGameModeString( "1024x768:32@75" );
    /*
    * set glut to fullscreen using the settings in the line above
    */
    //glutEnterGameMode();
    /*
    * Seting Screen Position
    */
    glutInitWindowPosition (0, 0);
    glutInitWindowSize (800, 600);
    glutCreateWindow (argv[0]);
    glutFullScreen();

    init ();

    glutDisplayFunc (display); //use the display function to draw everything
    /*
    * update any variables in display,
    * display can be changed to anyhing, as long as you move the
    * variables to be updated, in this case, angle++;
    * glutIdleFunc (display);
    */
    glutIdleFunc (display);
    glutReshapeFunc (reshape);
    glutKeyboardFunc (keyboard);
    glutMainLoop();

    return 0;
}

ติดตั้งอุปกรณ์การทดลองดังภาพ


ภาพที่ฉายลงบนวัตถุจริง ซึ่งมีการเหลี่อมเพียงเล็กน้อยเท่านั้น

30 พฤษภาคม 2553

เตรียมการสอนถ่ายภาพ วิดีโอและการจัดกา...

เตรียมการสอนถ่ายภาพ วิดีโอและการจัดการภาพถ่ายเบี้องต้น
ก่อนอื่นต้องกล่าวยินดีต้อนรับ FRA รุ่นที่ 8
ที่จะมาเรียน ป.โททางด้านวิทยาการหุ่นยนต์และระบบอัตโนมัติ ที่ ฟีโบ้นะครับ
คิดอีกทีก็เศร้านี่เราแก่ไปอีกแล้วเหรอเนี่ย ปี2 แล้ว

Download ไฟล์ MindMap ได้ที่นี่ http://www.upload-thai.com/download.php?id=5192bb7de80c541244a10b41a8cc0805

OpenGL สร้างสีเหลี่ยมที่ไม่ใช่ลูกบาศก์

OpenGL สร้างสีเหลี่ยมที่ไม่ใช่ลูกบาศก์ จากสีีเหลี่มลูกบาศก์
โดยปกติ glut จะมีฟังก์ชัน glutWireCube สำหรับสร้างลูกบาศก์ได้อย่างง่ายดายในคำสั่งเดียว
แต่หากเราต้องการสร้างรูปที่ไม่เป็นลูกบาศก์โดยวิธีดังเดิม
โดยการกำหนดจุด มุมแต่ละจุดของแล้วสร้างเป็น polygon มาต่อกัน
ดูได้จาก GL Manager ของ อ.สยาม
void CGLMgrDlg::Box(GLdouble x0, GLdouble x1, GLdouble y0, GLdouble y1,
        GLdouble z0, GLdouble z1, GLenum type)
{
    static GLdouble n[6][3] = {
        {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
        {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
    };
    static GLint faces[6][4] = {
        { 0, 1, 2, 3 }, { 3, 2, 6, 7 }, { 7, 6, 5, 4 },
        { 4, 5, 1, 0 }, { 5, 6, 2, 1 }, { 7, 4, 0, 3 }
    };
    GLdouble v[8][3], tmp;
    GLint i;

    if (x0 > x1) {
        tmp = x0; x0 = x1; x1 = tmp;
    }
    if (y0 > y1) {
        tmp = y0; y0 = y1; y1 = tmp;
    }
    if (z0 > z1) {
        tmp = z0; z0 = z1; z1 = tmp;
    }
    v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
    v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
    v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
    v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
    v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
    v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;

    for (i = 0; i < 6; i++) {
        glBegin(type);
        glNormal3dv(&n[i][0]);
        glVertex3dv(&v[faces[i][0]][0]);
        glNormal3dv(&n[i][0]);
        glVertex3dv(&v[faces[i][1]][0]);
        glNormal3dv(&n[i][0]);
        glVertex3dv(&v[faces[i][2]][0]);
        glNormal3dv(&n[i][0]);
        glVertex3dv(&v[faces[i][3]][0]);
        glEnd();
    }
}


void CGLMgrDlg::SolidBox(double width, double height, double depth)
{
    Box(-width/(GLdouble)2., width/(GLdouble)2., -height/(GLdouble)2., height/(GLdouble)2.,-depth/(GLdouble)2., depth/(GLdouble)2., GL_QUADS);
}



ซึ่งจะวุ่นวายมากแม้จะทำ Wrapper Class ให้ใช้งานได้ง่ายๆ แล้วก็ตามนอกจากนี้หากต้องการสร้างรูปแบบ Wire
เพื่อใช้ test เส้นขอบของวัตถุฉายลงมาตรงวัตถุหรือไม่ หากเป็นรูปทรงสี่เหลี่ยม ต้องสร้าง Line ให้ครบทุกด้านเลยทีเดียวซึ่งยุ่งยากมาก

แต่ในที่นี้เราจะใช้เทคนิคสร้างลูกบาศก์ขึ้นมาขนาด 1x1x1 แล้วใช้การขยายขนาดโดย Transformation Matrix
เช่นเราอยากให้สีเหลี่ยมขนาด กว้าง x ยาว x ลึก  เช่น 50 x 25 x 25
เราจะขยายมุมของกล่องโดยใช้ฟังกชัน glScaled
    /*
    * Wire Box + Scale
    */
    glPushMatrix ();
        glColor3f (1.0, 1.0, 1.0);
        glScaled (50.0, 25.0, 25.0);
        glutWireCube (1);
    glPopMatrix ();
ทำให้เขียนโปรแกรมได้ง่ายขึ้นมากโดยคำสั่งแค่ 2 บรรทัด ก็สามารถสร้างกล่องขนาดต่างๆกันได้มากมาย