OpenCV et Rebol V3
ldci25-Jan-2015/16:02:04+1:00
Bonjour à tous les reboliens!
Après avoir joué un peu avec OpenCV et Python, je suis en train de terminer la version 3 du portage d'OpenCV vers Rebol 2.7.8.
J'ai revu environ 600 fonctions et il m'en reste quelques unes à terminer. Il y a plein de nouveautés pour jouer avec des images stéréo et autres ...
Le code est compatible avec OPenCV2.4.9 et 2.4.10 et sera maintenu pour les nouvelles versions d'openCV.
On peut également travailler avec la dll en static ou en dynamic à partir de Rebol
J'ai beaucoup simplifié les appels aux fonctions C qui, sauf indication contraire renvoient un pointeur (une adresse sous forme d'entier). C'est plus simple pour programmer.
J'ai aussi implémenté une fonction "magique" qui donne accès au contenu des structures si le besoin s'en fait sentir.

getPointerValues: func [ptr [integer!] structureType [struct!]] [
	"Gets the contents of opencv structures" 
	struct: make struct! (structureType) none			; make a rebol structure for cv Structure
	content: get-memory ptr length? third struct		; get the content of the pointer
	change third struct content					; update rebol structure
	struct									; return structure 
]



L'appel est très simple:

; load image
image: cvLoadImage filename CV_LOAD_IMAGE_COLOR; on charge l'image sous la forme d'un pointeur
imageS: getPointerValues image IplImage! ; on récupère le contenu de la structure
;Create the color output image
cedge: cvCreateImage imageS/width imageS/height IPL_DEPTH_8U 3 ; on se sert des valeurs de la structures pour créer une autre image 


On ne peut pas faire plus simple pour travailler sur toutes les structures OpenCV

Voici encore un exemple qui montre comment transformer une image OpenCV en image rebol
;this is for memory alignment of IplImage in OpenCV;
; processes line by line 
;get the line data with the ACTUAL size : width * nChannels and not widthStep
 
cvtoRebol: func [img dest /local src rgb] [
"Transforms OpenCV image to REBOL image"
    src: getPointerValues img IplImage!	 				; get values of IplImage
	rgb: copy #{}									; make a binary 
	for y 0 src/height - 1 1 [
		index: y * src/widthStep 					; go to line y and get data
		line: get-memory (src/imageData + index) (src/width * src/nChannels)  
		append tail rgb line
	]
	; mow makes the REBOL image
    dest/image: make image! reduce [as-pair (src/width) (src/height) reverse rgb]
    dest/effect: [fit flip 1x1] ;
	show dest
] 



J'adore ce type de programmation: clair, concis et efficace. Tout REBOL quoi!
GreG26-Jan-2015/9:40:15+1:00
Merci de partager ces travaux avec nous
Effectivement, OpenCV contient énormément de fonctions!
François, sais-tu si il est possible de modulariser OpenCV de façon à construire une librairie OpenCV qui ne contient que les fonctions souhaitées?
ldci26-Jan-2015/10:38:24+1:00
Salut Greg,
La réponse est oui. J'ai adopté l'approche en modules qui est développée par opencv depuis ses dernières versions


if system/version/4 = 2  [
		calib3d: load/library %/usr/local/lib32/opencv/libopencv_calib3d.dylib
		core: load/library %/usr/local/lib32/opencv/libopencv_core.dylib
		imgproc: load/library %/usr/local/lib32/opencv/libopencv_imgproc.dylib
		highgui: load/library %/usr/local/lib32/opencv/libopencv_highgui.dylib
		legacy: load/library %/usr/local/lib32/opencv/libopencv_legacy.dylib
		objectd: load/library %/usr/local/lib32/opencv/libopencv_objdetect.2.4.dylib
		photo: load/library %/usr/local/lib32/opencv/libopencv_photo.dylib
		video: load/library %/usr/local/lib32/opencv/libopencv_video.dylib
	 ]


Tu peux donc choisir le module qui t'intéresse. Ensuite il faut utiliser une fonction mezzanine qui te permet de charger les routines qui t'intéressent

cvFunc: func [specs lib id] [make routine! specs lib id]


Cette technique te permet de charger "à la volée" les fonctions opnecv dont tu as besoin. Voici un exemple qui illustre mon propos


#! /usr/bin/rebol
REBOL [
	Title:		"OpenCV Tests: Pyramids demo"
	Author:		"François Jouen"
	Rights:		"Copyright (c) 2012-2014 François Jouen. All rights reserved."
	License:    "BSD-3 - https://github.com/dockimbel/Red/blob/master/BSD-3-License.txt"
]

set 'appDir what-dir 
ocvDir: join appDir "libs/opencv/"
do to-file join ocvDir "opencv249.r" ; for new opencv 2.4.9
do to-file join ocvDir "rtools.r" ; for memory management


wName1: "Pyramids Demo"
w: h: 0
nChannels: 3


;some OpenCV constants
CV_WINDOW_AUTOSIZE: 1
CV_GAUSSIAN_5x5: 7
IPL_DEPTH_8U: 8
CV_LOAD_IMAGE_COLOR: 3

; external opencv functions we need

cvNamedWindow: cvFunc [name [string!] flag [integer!] return: [ptr!]] highgui "cvNamedWindow"	
cvWaitKey: cvFunc [delay [integer!] return: [ptr!]] highgui "cvWaitKey"
cvLoadImage: cvFunc [name [string!] flag [integer!] return: [ptr!]] highgui"cvLoadImage"
cvShowImage: cvFunc [name [string!] img [ptr!]] highgui "cvShowImage"
cvCreateImage: cvFunc [w [integer!] h [integer!] depth [integer!] channels [integer!] return: [ptr!]] cxcore "cvCreateImage" 
cvPyrUp: cvFunc [s [ptr!] d [ptr!] filter [integer!]] imgproc "cvPyrUp"
cvPyrDown: cvFunc [s [ptr!] d [ptr!] filter [integer!]] imgproc "cvPyrDown"


picture:  to-string to-local-file join appDir "images/lena.jpg"

src: cvLoadImage picture CV_LOAD_IMAGE_COLOR; CV_LOAD_IMAGE_GRAYSCALE; 
dst: tmp: src
cvNamedWindow wName1 CV_WINDOW_AUTOSIZE


c: 0
ivalues: getIPLValues/address tmp; get informations about the image					
w: ivalues/11 ; width
h: ivalues/12 ;height



while [c <> 27] [
	c: cvWaitKey 10
	if c > 0 [
    	; u ; 117
   	 	if  c = 117 [ 					
			w: ivalues/11 * 2
			h: ivalues/12 * 2
    		print join to-char c [" Image size: " w " " h]
    		dst: cvCreateImage w h IPL_DEPTH_8U nChannels
    		cvPyrUp tmp dst CV_GAUSSIAN_5x5	
    	]
    
    	;d ; 100
    	if c = 100 [ 						
			w: ivalues/11 / 2
			h: ivalues/12 / 2
			if w >= 4 [
    			print join to-char c [" Image size: " w " " h]
    			dst: cvCreateImage w h IPL_DEPTH_8U nChannels
    			cvPyrDown tmp dst CV_GAUSSIAN_5x5
    		]
    	]
    ]
	cvShowImage wName1 dst
	tmp: dst	
	ivalues: getIPLValues/address tmp	
]


Cette technique fonctionne très bien, mais elle implique que tu charges tous les modules dont tu as besoin. L'idéal serait que REBOL soit capable d'aller chercher dans le module UNIQUEMENT les fonctions requises un peu comme modula2 le faisait ou comme python le fait avec la fonction import: "from SimpleCV import Camera".
Si tu as une idée comment faire, elle est la bienvenue
D'après mes échanges avec Nenad, cela ne semble pas évident ni avec Rebol ni avec Red.
Dernier point, ce serait pas mal maintenant d'interfaçer opencv avec Rebol 3. Je n'ai pas encore eu vraiment le temps de m'intéresser à R3 et les dll, car j'ai passé pas mal de temps à optimiser les appels aux fonctions opencv et la constructions des structures de données openCV. Ca m'a permis de développer des algorithmes un peu sophistiqués pour traiter des images thermiques et autres joyeusetés. dans cette option recherche, j'ai vraiment besoin d'avoir accès aux paramétrages précis des fonctions opencv. Mais pour beaucoup d'applications, on peut simplifier. Une idée intéressante serait de faire un langage métier permettant de faire du "computer vision" simplement et avec REBOL. Ca existe en python (http://simplecv.org/) et c'est assez efficace.
Evidemment, pour tout ça, il faut des bras
GreG26-Jan-2015/10:59:59+1:00
Atronix a implémenté FFI sur Rebol 3, ce qui facilite l'interfaçage avec des libs existantes.
Quelques exemples:
https://github.com/zsx/r3/blob/atronix/make/tests/test-ffi.r
https://github.com/zsx/r3/blob/atronix/make/tests/ms-drives.r
ldci26-Jan-2015/21:30:19+1:00
Merci Greg pour le lien
C'est très intéressant comme approche car c'est simple.
Quelques problèmes à gérer sur OSX 10.10 (le makefile est à revoir). Je regarde tout ça dès que possible.Un autre intérêt c'est qu'on peut passer en 64 bits!
A +
GreG26-Jan-2015/22:48:53+1:00
Par contre il n'y a toujours pas de View pour OSX, ce sera à nous de le faire!
Windows et Linux pour le moment...

Login required to Post.


Powered by RebelBB and REBOL 2.7.8.4.2