My GSoC 2012 Proposal

This is my first attempt at Google Summer of Code (GSoC) 2012. I will propose my project idea to SimpleCV. I think it would be useful if I share my proposal here whether it will be accepted or rejected. 🙂 Anyway, you can find it [here].

Below is the quote from Anthony (one of the developers for SimpleCV) in pythonvision at googlegroups dot com. I would like to post it here, so readers can get the idea what SimpleCV is.

SimpleCV wrappers OpenCV amongst others. If you are new to computer vision it is probably worth a look as we have a bunch of examples: http://examples.simplecv.org

To be honest, that's how the whole SimpleCV project started. We got sick of their not being documentation, and were using other tools like ipython, etc, that we wanted integrated.  We have also written our own blob detection library because we got sick of compile errors and having to use cvblob as a dependency.

We have a long way to go, and for seasoned vision programmers SimpleCV is probably not the route you want to go, if you are beginner it's definitely easier to get up and running.  I wrote an article about the differences recently and I welcome any feedback: http://simplecv.tumblr.com/post/19307835766/opencv-vs-matlab-vs-simplecv

I think people get the misconception we are trying to replace opencv, and by no means is the case. We label ourselves as a framework not as a library.  Think of us as a jquery or rails (ruby on rails) for vision. 🙂

ตัวอย่างการใช้ OpenCV เพื่อหา Homography

ผมไม่ขอกล่าวถึงว่า Homography คืออะไรนะครับ จะกล่าวถึงแค่ตัวอย่างการคำนวณหา Homography โดยใช้ OpenCV ในบล็อกนี้ ซึ่งค่อนข้างง่ายครับ เพราะ OpenCV นั้นมีฟังก์ชั่น cvFindHomography อยู่แล้ว งานของเราก็แค่ใส่ข้อมูลตามที่ฟังก์ชั่นนี้ต้องการ ซึ่งอย่างน้อยเราต้องให้ตัวแปรตามข้างล่างนี้กับฟังก์ชั่น

  1. จุดบนระนาบต้นฉบับ (srcPoints) อย่างน้อย 2 จุดขึ้นไป จำนวนจุดนี้ขึ้นอยู่กับแต่ละงานนะครับ
  2. จุดบนระนาบปลายทาง (destPoints) ซึ่งจำนวนจุดก็เท่ากับที่กำหนดไว้บนระนาบเริ่มต้น
  3. Homography เมทริกซ์ ขนาด 3x3 (เริ่มแรกก็คือเมทริกซ์ว่างๆ นั่นแหละ)

จริงๆ เราสามารถใส่ option เพิ่มได้ ไว้ไปลองกันเองนะครับ 🙂

Continue reading "ตัวอย่างการใช้ OpenCV เพื่อหา Homography"

How to install OpenCV 2.1 on Ubuntu

The new version of OpenCV's changed the way to install by using cmake. I also have to update myself and find some information regarding it. Recently, I've read the tutorial on installing OpenCV 2.1 in Ubuntu which explains very well; so, I follow this tutorial and I would note my installation steps here.

  1. install dependencies as follows (please also see the screen shots below).
    • libcv4
    • libcv-dev
    • libcvaux4
    • libcvaux-dev
    • libhighgui4
    • libhighgui-dev
    • opencv-doc (optional)
    • ffmpeg (optional; if you want to use ffmpeg to do video processing)

    check-opencv-packages01

    check-opencv-packages02

  2. install cmake using the command sudo apt-get install cmake.
  3. run cmake -D WITH_FFMPEG=ON -D CMAKE_INSTALL_PREFIX=${HOME}/opencv/ ..
    • Note that there is a dot at the end of the command above which means to run at the current directory.
    • The options mean to use ffmpeg and to set the OpenCV path in your home directory.
  4. check if ffmpeg is available and the folder to install is correct. See the screen shot below.

    config-checking

  5. run the command make
  6. run the command sudo make install.
  7. The last thing is to is to tell the dynamic linker where the DLLs are; so, add the line: export LD_LIBRARY_PATH=${HOME}/opencv/lib to ~/.bashrc and then relogin.

finish.. 🙂

การใช้ OpenCV สร้างกราฟ Histogram จากรูป

บล็อกนี้ผมขอเสนอวิธีใช้ฟังก์ชั่นจาก OpenCV สร้างกราฟ Histogram จากค่าสีที่ได้จากรูปที่เป็น Grayscale นะครับ ซึ่งก็สามารถนำไปประยุกต์ใช้กับรูปที่เป็น RGB หรือ HSV ได้เหมือนกันครับ

ก่อนอื่นเลย Histogram ของรูป คืออะไร.. มันก็คือกราฟที่เกิดจากการพลอตจำนวนของ pixel ที่ค่าสีนั้นๆ นั่นเอง แกน X คือค่าของสี ส่วนแกน Y คือจำนวนของ pixel (อ่านเพิ่มเติมได้ที่ Image histogram ครับ)

เมื่อเราทราบหลักการของการสร้าง Histogram จากรูปแล้ว เราก็มาดูที่โค้ดกันครับ เริ่มต้นเราก็ประกาศขนาดของ Histogram ครับ ให้มีขนาด 256 ช่อง (ค่าสีปกติจะมีค่าระหว่าง 0-255 ในที่นี้ผมจะให้ช่องหนึ่งคือค่าสีหนึ่งนะครับ ซึ่งค่านี้สามารถเปลี่ยนแปลงได้แล้วแต่งานครับ)

int bins = 256;
int hsize[] = { bins };

ในโค้ดของผมนี้ผมจะสร้าง Histogram ที่เป็น uniform นะครับ เราก็ต้องกำหนดขอบเขตของค่า x ซึ่งต้องกำหนดตาม format ดังนี้ครับ โดย ranges[] จะต้องมีจำนวน dimension เท่ากับจำนวนค่าที่เป็นคู่ที่เราประกาศไว้ (คู่ 0 กับ 255)

float xranges[] = { 0, 255 };
float* ranges[] = { xranges };

เนื่องจากรูปตัวอย่างเป็น RGB เราก็ต้องแปลงให้เป็น Grayscale ก่อนนะครับ โดย image ในที่นี้คือรูปที่เราโหลดมาตั้งแต่ต้นนะครับ

IplImage* gray = cvCreateImage( cvGetSize( image ), 8, 1 );
cvCvtColor( image, gray, CV_BGR2GRAY );

จากนั้นเราต้องสร้างเพลน (plane) เพื่อมาคำนวณกราฟกันครับ ในที่นี้มีแค่ 1

IplImage* planes[] = { gray };

แล้วเราก็คำนวณค่าของ Histogram ดังนี้ โดยค่า 1 ตัวแรกหมายถึง จำนวน dimension ครับ ส่วน CV_HIST_ARRAY หมายถึงให้ type เป็นชนิด array และค่า 1 ตัวสุดท้ายหมายถึงว่าเป็น uniform ครับ

CvHistogram* hist = cvCreateHist( 1, hsize, CV_HIST_ARRAY, ranges, 1 );
cvCalHist( planes, hist, 0, NULL );

ในการคำนวณโดยใช้ cvCalHist นั้น เราเซตค่าที่ 3 ว่าให้เป็น 1 แปลว่า ถ้าสมมุติว่าเราวนลูปอ่านค่าสีจากรูปมาเรื่อยๆ เราสามารถบวกค่า pixel เพิ่มได้ในกราฟ Histogram อันเดิมครับ แต่ถ้าเป็น 0 ก็แปลว่าไม่ต้องบวกเพิ่ม ส่วนค่าสุดท้าย ถ้าไม่ใช่ NULL เราจะนำแค่จุด pixel ที่ไม่ใช่ 0 และมีการ mask ไว้ในรูปมาคำนวณครับ

ขั้นตอนต่อไป เราก็ต้องสร้างรูปขึ้นมาเพื่อแสดงผลครับ ในที่นี้เรากำหนดให้มีความสูงแค่ 50 พอครับ

IplImage* imgHistogram = cvCreateImage( cvGetSize( bins, 50 ), 8, 1 );
cvRectangle( imgHistogram, cvPoint( 0, 0 ), cvPoint( 256, 50 ), CV_RGB( 255, 255, 255 ), -1 ); // ค่าสุดท้ายคือค่า thickness ครับ ถ้าเป็น -1 แสดงว่าให้เป็นค่าสูงสุดเลย (เพื่อที่ว่าเราจะระบายสีขาวให้เต็มสีเหลี่ยมเลยครับ)

ขั้นตอนสุดท้ายเราก็วาดกราฟครับ และแสดงผล วิธีการก็คือดึงค่าออกมาทีละค่านั่นเอง แต่เนื่องจากเราเซตความสูงไว้ที่ 50 เราจะต้อง normalize ด้วยนะครับ แต่การที่เราจะ normalize ได้เราต้องมีค่าสูงสุดของ Histogram ก่อนครับ หาได้ดังนี้

float max_value = 0, min_value = 0;
cvGetMinMaxHistValue( hist, &min_value, $max_value );

และสุดท้ายจริงๆ ก็ดังนี้ครับ

cvNamedWindow( "histogram", 1 );
for( int i = 0; i < bins; i++ ) {
  float value = cvQueryHistValue_1D( hist, i );
  int normalized = cvRound( value * 50 / max_value );
  cvLine( imgHistogram, cvPoint( i, 50 ), cvPoint( i, 50 - normalized ), CV_RGB( 0, 0, 0 ) );
}
cvShowImage( "histogram", imgHistogram );

หวังว่าจะเป็นจุดอ้างอิงสำหรับผู้ที่เริ่มต้นสนใจในด้าน Image Processing นะครับ

Source code: hist.cc

credit: Isaias Gonzalez (siderevs at gmail dot com)

การจัดการปัญหา Memory Leak ใน OpenCV (C/C++)

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

ถ้าโค้ดของเรามีดังนี้

IplImage* img = cvCreateImage( ... );  // ประกาศตัวแปร img และได้จองหน่วยความจำไว้
img = xfunction( ... );  // ส่งค่า IplImage* กลับ
…
cvReleaseImage( &img );  // ลบหน่วยความจำตัวใหม่ที่เกิดจาก xfunction

แบบนี้แสดงว่าเกิด Memory leak ที่ xfunction ครับ คือตอนแรกเราจองหน่วยความจำให้กับตัวแปร img และต่อมาได้เรียกฟังก์ชั่น xfunction ซึ่งฟังก์ชั่นนี้ จะจองหน่วยความจำไว้อีกที่หนึ่งสำหรับค่าที่จะส่งกลับ ทำให้ตัวแปร img ไปชี้ที่หน่วยความจำใหม่ และหน่วยความจำเก่าที่ได้จองไว้ตอนแรกยังคงอยู่ (ถ้าใช้ภาษา Java คิดว่าไม่น่าจะมีปัญหาตรงนี้ครับ)

วิธีแก้ก็ง่ายมากครับ แค่แทนที่จะใช้ cvCreateImage() เราก็เปลี่ยนให้ชี้ไปที่ NULL แทน ดังนี้ครับ

IplImage* img = NULL;
img = xfunction( ... );
…
cvReleaseImage( &img );

สรุปคือ ถ้าใช้ภาษา C/C++ ต้องระวังเป็นอย่างมากครับ ไม่งั้นโปรแกรมอาจจะใช้แรมไปจนหมดเครื่องแน่ๆ ต้องหมั่นตรวจสอบว่าเราจองหน่วยความจำไว้ที่ไหน และพยายามลบทิ้งถ้าไม่ได้ใช้แล้วนะครับ ถ้ายิ่งทำงานเกี่ยวกับการวิเคราห์ไฟล์วีดีโอด้วยแล้วยิ่งต้องระวัง

อ่านรายละเอียดทั้งหมดได้ที่: OpenCV Memory Management in C/C++