How to install OpenCV binding for Red
You need first the last Red stable version (0.63 or newer). Basically, you don’t need to install OpenCV. You’ll find in /DLLs directory a 32-bit compiled version of the OpenCV framework (3.0 and 3.10) for the three main operating systems (Mac OS, Linux and Windows). Just copy the library (.dylib, .so or .dll) somewhere on your computer and then edit the platforms.reds file (in /libs) and make the links according to your path.Red/System and Red for OpenCV
For this binding, most of 600 OpenCV functions were transformed to Red code with Red/System DSL. Imported OpenCV functions can be directly call by Red/System programs or can be accessed with routines if you use Red language. Routines are a fantastic tool that allows to use code written in Red/System inside Red code. Thus, routines give the possibility to access C functions included in DLL via the binding of the library written in Red/System. This means that you can use either Red/System DSL or Red language to write your image processing programs. Result will be the same.
However, there are some differences when writing Red Language code. First it’s necessary to use the #system directive to include OpenCV libraries. This is also the place to declare any global variables that will be used by routines. Second, you have to write routines that behave as an interface between you red code and the Red/System functions. OpenCV functions and global Red/System variables are thus directly called inside routines.
Using OpenCV with Red/View
The interest of using Red Language is that you can employ Red/View and Red/Draw DSL for creating GUI and developing sophisticated interface for computer vision such as in the next sample of face processing with Red.
OpenCV's face detection
Object Detection using Haar feature-based cascade classifiers is an effective object detection method proposed by Paul Viola and Michael Jones in 2001 (Rapid Object Detection using a Boosted Cascade of Simple Features). It is a machine learning based approach where a cascade function is trained from a lot of positive and negative images. It is then used to detect objects in other images. OpenCV already contains many pre-trained classifiers for face, eyes, smile or body. Those XML files are stored in opencv/data/haarcascades/ folder.
Using Red
All job is done in findFaces routine which allows to call red/system code accessing OpenCV functions.
First let's load the required XML classifiers
cascade: cvLoadHaarClassifierCascade classifier 20 20,
then detect faces with cvHaarDetectObjects function
faces: cvHaarDetectObjects pyrImg cascade storage sFactor minNB flag minS/x minS/y maxS/x maxS/y
Where the parameters are:
pyrImg : 8-bit Matrix containing an image where objects have to be detected.
cascade: OpenCV pre-trained classifiers for face
storage: a opaque pointer used to get the result of face detection
sFactor: This scale factor is used to create scale pyramid. It means we're using a small step for resizing and we increase the chance of a matching size with the model for detection.
minNB: Parameter specifying how many neighbors each candidate rectangle should have to retain it. This parameter will affect the quality of the detected faces: higher value results in less detections but with higher quality
flags : Mode of operation.
CV_HAAR_SCALE_IMAGE : for each scale factor used the function will downscale the image rather than "zoom" the feature coordinates in the classifier cascade.
CV_HAAR_DO_CANNY_PRUNING : If it is set, the function uses Canny edge detector to reject some image regions that contain too few or too much edges and thus can not contain the searched object. The particular threshold values are tuned for face detection and in this case the pruning speeds up the processing.
CV_HAAR_FIND_BIGGEST_OBJECT: If it is set, the function finds the largest object (if any) in the image. That is, the output sequence will contain one (or zero) element(s).
CV_HAAR_DO_ROUGH_SEARCH: used only when CV_HAAR_FIND_BIGGEST_OBJECT is set and min_neighbors > 0. If the flag is set, the function does not look for candidates of a smaller size as soon as it has found the object (with enough neighbor candinates) at the current scale. Typically, when min_neighbors is fixed, the mode yields less accurate (a bit larger) object rectangle than the regular single-object mode (flags=CV_HAAR_FIND_BIGGEST_OBJECT), but it is much faster, up to an order of magnitude. A greater value of min_neighbors may be specified to improve the accuracy.
minS : Minimum possible object size. Objects smaller than minS are ignored.
maxS : Maximum possible object size. Objects larger than maxS are ignored.
Code Sample
Red [
Title: "Find Face"
Author: "F. Jouen"
File: %findFaces.red
Needs: 'View
]
; import required OpenCV libraries
#system [
#include %../../libs/include.reds ; all OpenCV functions
img: declare CvArr!
imgCopy: declare CvArr!
clone: declare CvArr!
pyrImg: declare CvArr!
cascade: declare CvHaarClassifierCascade!
storage: declare CvMemStorage!
faces: declare CvSeq!
faceRect: declare byte-ptr!
ptr: declare int-ptr!
roi: declare cvRect!
nFaces: 0
classifier: "/red/OpenCV/cascades/haarcascades/haarcascade_frontalface_default.xml"
]
; global red variables to be passed as parameters to routines or used by red functions
set 'appDir what-dir
margins: 5x5
clName: "haarcascade_frontalface_default.xml"
scaleFactor: 1.1
minNeighbors: 3
minSize: 0x0
maxSize: 0x0
isFile: false
src: 0
flagValue: 1
nbFaces: 0
; some routines for image conversion from openCV to Red
#include %../../libs/red/cvroutines.red
; Red Routines for OpenCV access
; release all image pointers
freeOpenCV: routine [] [
releaseImage img
releaseImage pyrImg
releaseImage clone
releaseImage imgCopy
]
loadTraining: routine [name [string!]/local fName][
fName: as c-string! string/rs-head name;
classifier: fName
]
; loads image with faces and returns image address as an integer
loadImg: routine [name [string!] return: [integer!] /local fName tmp isLoaded] [
isLoaded: 0
fName: as c-string! string/rs-head name;
tmp: cvLoadImage fName CV_LOAD_IMAGE_COLOR ; CV_LOAD_IMAGE_ANYDEPTH OR CV_LOAD_IMAGE_ANYCOLOR;
img: as int-ptr! tmp
clone: as int-ptr! cvLoadImage fName CV_LOAD_IMAGE_COLOR
imgCopy: as int-ptr! cvLoadImage fName CV_LOAD_IMAGE_COLOR
pyrImg: as int-ptr! cvCreateImage tmp/width / 2 tmp/height / 2 IPL_DEPTH_8U 3
storage: cvCreateMemStorage 0
cvSmooth img img CV_GAUSSIAN 3 3 0.0 0.0 ;gaussian smoothing
cvPyrDown img pyrImg CV_GAUSSIAN_5x5 ;reduce original size to improve speed in face recognition
cvCopy img clone null
cvFlip clone clone -1
isLoaded: as integer! clone
isLoaded
]
; looks for faces
findFaces: routine [sFactor [float!] minNB [integer!] flag [integer!] minS [pair!] maxS [pair!] return: [integer!]
/local c x y wd hg ] [
cvCopy imgCopy img null
cascade: cvLoadHaarClassifierCascade classifier 20 20 ;seems OK
faces: cvHaarDetectObjects pyrImg cascade storage sFactor minNB flag minS/x minS/y maxS/x maxS/y
nFaces: faces/total ; for faceCount routine
if faces/total > 0 [
c: 0
until [
faceRect: cvGetSeqElem faces c ; faceRect is a byte-ptr!
ptr: as int-ptr! faceRect ; we cast to an int-ptr! since we have 4 integers to get here
; * 2 due to original image pyrdown
x: ptr/1 * 2
y: ptr/2 * 2
wd: (ptr/1 + ptr/3) * 2
hg: (ptr/2 + ptr/4) * 2
roi: cvRect x y wd hg
cvRectangle img roi/x roi/y roi/width roi/height 0.0 255.0 0.0 0.0 2 CV_AA 0
c: c + 1
c = faces/total
]
]
cvCopy img clone null
cvFlip clone clone -1
as integer! clone
]
;returns nb of found faces
countFaces: routine [return: [integer!]][nFaces]
;Red Functions calling routines
loadImage: does [
isFile: false
canvas/image: black
tmp: request-file
if not none? tmp [
fileName: to string! to-local-file tmp
src: loadImg fileName
if src <> 0 [
isFile: true
win/text: fileName
; update faces
wsz: getIWidth src wsz
hsz: getIHeight src hsz
canvas/image: makeRedImage src wsz hsz
]
]
]
loadClassifier: does [
tmp: request-file
if not none? tmp [
fileName: to string! to-local-file tmp
info1/data: form second split-path tmp
loadTraining fileName
]
]
faces: does [
t1: now/time/precise
src: findFaces scaleFactor minNeighbors flagValue minSize maxSize
t2: now/time/precise
s: form countFaces
append s " in "
append s third t2 - t1
append s " sec"
sb/data: s
canvas/image: makeRedImage src wsz hsz
]
;Red GUI Interface
view win: layout [
title "Find Faces"
button 50 "Load" [loadImage faces]
button 75 "Classifier" [loadClassifier if isFile [faces]]
info1: field 220 clname
text 35 "Flags"
flag: drop-down 210x24
data ["CV_HAAR_DO_CANNY_PRUNING" "CV_HAAR_FIND_BIGGEST_OBJECT"
"CV_HAAR_DO_ROUGH_SEARCH" "CV_HAAR_SCALE_IMAGE"]
select 1
on-change [
if isFile [
switch flag/selected[
1 [flagValue: 1]
2 [flagValue: 4]
3 [flagValue: 8]
4 [flagValue: 2]
]
faces
]
]
return
text "Scale Increase"
sl1: slider 100 [scaleFactor: 1.1 + to float! face/data
tscale/data: 1.1 + face/data if isFile [faces]]
tscale: field 40 "1.1"
text "Min Neighbors"
field 30 "3" [minNeighbors: to-integer face/data if isFile [faces]]
text 80 "Size Min Max"
field 40 "0x0" [minSize: to-pair face/data if isFile [faces]]
field 40 "0x0" [maxSize: to-pair face/data if isFile [faces]]
button 50 "Quit" [if isFile [freeOpenCV] Quit]
return
canvas: base 640x480 black
return
text 100 "Found faces : " sb: field 130
do [sl1/data: 0.0]
]
Result
Aucun commentaire:
Enregistrer un commentaire