Monday, July 21, 2014

OpenCV Python: Digit Recognition

Here's an example of OpenCV digit recognition with a given TrueType font (*.ttf) and digit height. It uses python PIL module to load digit glyphs. These glyphs (converted to CV images) are then used to train a K-Nearest model.

import cv2
import numpy as np
from PIL import Image, ImageFont, ImageDraw, ImageOps

# create training model based on the given TTF font file
def createDigitsModel(fontfile, digitheight):
    ttfont = ImageFont.truetype(fontfile, digitheight)
    samples =  np.empty((0,digitheight*(digitheight/2)))
    responses = []
    for n in range(10):
        pil_im = Image.new("RGB", (digitheight, digitheight*2))
        ImageDraw.Draw(pil_im).text((0, 0), str(n), font=ttfont)
        pil_im = pil_im.crop(pil_im.getbbox())
        pil_im = ImageOps.invert(pil_im)
        #pil_im.save(str(n) + ".png")

        # convert to cv image
        cv_image = cv2.cvtColor(np.array( pil_im ), cv2.COLOR_RGBA2BGRA)
        gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY)
        blur = cv2.GaussianBlur(gray,(5,5),0)
        thresh = cv2.adaptiveThreshold(blur,255,1,1,11,2)

        roi = cv2.resize(thresh,(digitheight,digitheight/2))
        responses.append( n )
        sample = roi.reshape((1,digitheight*(digitheight/2)))
        samples = np.append(samples,sample,0)

    samples = np.array(samples,np.float32)
    responses = np.array(responses,np.float32)
    
    model = cv2.KNearest()
    model.train(samples,responses)
    return model

# digit recognition part
def findDigits(imagefile, digitheight, fontfile="C:\\Windows\\Fonts\\Arial.ttf"):
    im = cv2.imread(imagefile)
    out = np.zeros(im.shape,np.uint8)
    gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
    thresh = cv2.adaptiveThreshold(gray,255,1,1,11,2)

    contours,hierarchy = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL ,cv2.CHAIN_APPROX_SIMPLE)

    model = createDigitsModel(fontfile, digitheight)
    for cnt in contours:
        x,y,w,h = cv2.boundingRect(cnt)
        if  h>w and h>(digitheight*4)/5 and h<(digitheight*6)/5: #+/-20%
            cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),1)
            roi = thresh[y:y+h,x:x+w] # crop
            roi = cv2.resize(roi,(digitheight,digitheight/2))
            roi = roi.reshape((1,digitheight*(digitheight/2)))
            roi = np.float32(roi)
            retval, results, neigh_resp, dists = model.find_nearest(roi, k=1)
            string = str(int((results[0][0])))
            #cv2.drawContours(out,[cnt],-1,(0,255,255),1)
            cv2.putText(out,string,(x,y+h),0,1,(0,255,0))

    cv2.imshow('in',im)
    cv2.imshow('out',out)
    cv2.waitKey(0)
    cv2.destroyWindow( 'in' )
    cv2.destroyWindow( 'out' )

findDigits('pi.png', 32)
print 'done.'
download: digitrecognition.py

sources:
opencvpython.blogspot.com
stackoverflow.com


Monday, October 28, 2013

AVR32 GCC IDE


AVR32 IDE (C/C++)
- uses AVR32 GNU toolchain
- requires FLIP 3 for uart bootloading
- tested only on eGizmo AVR32 mcu board (AT32UC3L0128)
download:  avr32-gcc-ide-svn191.7z 25MB
svn repo source: 
svn co http://yus-repo.googlecode.com/svn/trunk/AVR32/avr32-ide


forum link:  AVR32 GCC IDE


.

Sunday, June 2, 2013

OpenCV ARM - Face Detect


Here's another application that uses opencv libraries in the Debian disto. It performs face detection using Haar cascade.


The code below continuously captures frames with a USB web-camera. (In this demo, I displayed a sample picture on a separate laptop but this will also work for actual faces). Using the input frames and a loaded Haar classifier cascade, vector of rectangles containing the detected faces is returned to the user. A bounding box is drawn to each face to show successful detection.

face_detect.py
import cv2.cv as cv

HAAR_CASCADE = "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml"

cv.NamedWindow( "mycamera" )
capture = cv.CreateCameraCapture(0)
storage = cv.CreateMemStorage()
cascade = cv.Load(HAAR_CASCADE)

while True:
    image = cv.QueryFrame(capture)
    faces = cv.HaarDetectObjects(image, cascade, storage, 1.1, 3, cv.CV_HAAR_DO_CANNY_PRUNING, (100,100))
    for((x,y,w,h),i) in faces:
        cv.Rectangle(image, (x,y), (x+w, y+h), (0,255,0), 3)
    cv.ShowImage( "mycamera", image )
    if cv.WaitKey(5) > 0:
        break

cv.DestroyWindow( "mycamera" )

Below is the C/C++ equivalent of the above python script. (The code appears lengthy due to the comments and cleanup routines.)

face_detect.cpp
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
using namespace cv;

#define HAAR_CASCADE "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml"

int main(int argc, const char ** argv)
{
    cvNamedWindow( "mycamera" /*, CV_WINDOW_AUTOSIZE*/); // create camera window, 1=CV_WINDOW_AUTOSIZE(default,the user cannot resize the window)
    CvCapture *capture = cvCreateCameraCapture(0); // start capturing frames from camera (i.e. /dev/video0 device)
    CvMemStorage *storage = cvCreateMemStorage(); // create new memory storage
    CvHaarClassifierCascade *cascade = (CvHaarClassifierCascade *)cvLoad(HAAR_CASCADE); // load frontal face detector

    while (1){
        IplImage *image = cvQueryFrame(capture); // grab and retrieve frame
        CvSeq *faces = cvHaarDetectObjects(image, cascade, storage, 1.1, 3, CV_HAAR_DO_CANNY_PRUNING, cvSize(100,100)); // find rectangular regions that contain faces
        for(int i=0; i < faces->total; i++){
            CvRect *r = (CvRect *)cvGetSeqElem(faces, i); // get bounding rectangle of the detected face
            cvRectangle(image, cvPoint(r->x, r->y), cvPoint(r->x + r->width, r->y + r->height), cvScalar(0,255,0), 3); // draw a green rectangle
        }
        cvShowImage( "mycamera", image ); // display image within window
        if (cvWaitKey(5) > 0) // press any key to exit
            break;
    }
    // cleanups
    cvReleaseHaarClassifierCascade( &cascade ); // release cascade
    cvReleaseMemStorage( &storage ); // release memory storage
    cvReleaseCapture( &capture ); // stop capturing/reading
    cvDestroyWindow( "mycamera" ); // end camera window
    return 0;
}

Saturday, June 1, 2013

OpenCV ARM - Hello World

Here is a sample application that utilizes OpenCV in my customized Debian disto. Sample codes are posted below. The demo simply displays images captured by the camera. This can be extended to utilize other opencv functions.



hello_camera.py
import cv2.cv as cv

cv.NamedWindow( "mycamera", 1 )
capture = cv.CreateCameraCapture( 0 )

while True:
    img = cv.QueryFrame( capture )
    cv.ShowImage( "mycamera", img )
    if cv.WaitKey(20) > 0:
        break

cv.DestroyWindow( "mycamera" )

Below is the C/C++ equivalent of the above Python script.

hello_camera.cpp
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

int main( int argc, const char** argv )
{
    cvNamedWindow( "mycamera", 1 ); // create camera window
    CvCapture *capture = cvCreateCameraCapture( 0 ); // start capturing frames from camera (i.e. /dev/video0 device)

    while(1){
        IplImage* img = cvQueryFrame( capture ); // grab and retrieve frame
        cvShowImage( "mycamera", img ); // display image within window
        if( waitKey(20) > 0 ) // press any key to exit (interval=20ms)
            break;
    }
    // cleanups
    cvReleaseCapture( &capture ); // stop capturing/reading // not needed in python (?)
    cvDestroyWindow( "mycamera" ); // end camera window
    return 0;
}


---------------------------------------------------------------------------
- thanks to hilite.me for formating the codes. (best viewed with Firefox browser)
- webcam can also be tested with guvcview (Applications Menu->Multimedia->guvcview)

Debian Wheezy on SUN4I (Allwinner A10)

I purchased a mini android tv box available at cd-rking. The item is actually a re-branded BC218 (similar specs to MK802+). This connects to a hdmi monitor, and with a mouse and keyboard this can function as a mini computer. After some testing, I decided to customize a Debian image dedicated for OpenCV development.


download: Debian Wheezy armhf image (~164MB)
- Debian Wheezy w/ XFCE4 desktop (debootstrap log )
- Kernel 3.4.43 (6416f0bf9e32d0950ba6f768ac20228ce8940a79) [Linaro 4.7]
- natively build MALI GPU drivers
- natively build OpenCV 2.4.5 libraries (C/C++ and Python2.7 support)
- with build-essential (e.g. compiler) and python packages

instructions:
- needs at least 2G microSD card
- extract *.img file using p7zip or 7zip,
   then use dd (Linux) or win32diskimager (Windows) to burn the image
- resize partitions (optional )
- root password: toor

notes:
- tested only on BC218; so the u-boot, script, and kernel may need to be modified to work for other boards)
- this Debian is intended only for opencv development, NOT for everyday use. There are other linux distro's that are more functional than this.
- no CedarX (VPU) libraries
- to keep the image size small: (1)there's no media player and no web browser included (wifi still works though); (2)remove docs, some locales, and /var/cache/ files.
- some kernel drivers in the default "sun4i_defconfig" were disabled. While, UVC, usb2serial, etc drivers were enabled for interfacing development.

--------------------------------------------------------------

update 06/09/13
Debian Wheezy armhf image V2
* with LXDE desktop
* apply some tweaks (may cause instability in the system!!!)
    - increase dram clock to 432MHz
    - increase default min cpu freq to 204MHz, default max to 1104MHz
    - use tmpfs for "tmp" and "log" folders
* re-build opencv libraries


If interested only on uboot and kernel files, here's the archive.
You may also need to mod the device by adding heatsink.










'yus

Wednesday, April 10, 2013

Stellaris Launchpad and Nokia 6100 LCD

... interfacing Nokia 6100 LCD shield to Stellaris Launchpad.
The LCD library used in this demo is included in the LM4F GCC-ARM IDE package.





LM4F-GCC-ARM-IDE


...an alternative Integrated Development Environment for TI's Stellaris® LM4F120 LaunchPad (ARM Cortex-M4F @80MHz, 256kB FLASH + 32kB SRAM)

download: lm4f-gcc-arm-ide-win32.7z   17.7 MB only.


IDE features:
  • fast light-weight IDE (PyQt based)
  • using gcc-arm-embedded 4.7.3
  • auto-completion (NOT IntelliSense)
  • code-outline using CLang
  • lm4flash (flash loader from lm4tools)
  • serial monitor
  • supports C++ projects
  • stellarisware peripheral driver library
  • supports 8 hardware UARTs: Serial0 to Serial7 (Serial0 is the same as the debug "Serial". Serial6 pins are mux w/ USB pins)
  • advanced libraries( USB device, FreeRTOS kernel)
  • basic libraries (gpio's, delay's, buttons, RGB led, N6100 lcd)



 forum discussion link