OpenCV3.0 et Red
ldci4-Dec-2015/17:11:42+1:00
Bonjour à tous
Je suis en train de peaufiner le portage d'OpenCV 3.0 avec Red. Comme Red évolue bien avec notamment les premières interfaces graphiques, j'ai pas mal amélioré le code pour qu'on puisse utiliser le code avec Red et non pas uniquement Red/System. Ce sera disponible sur GitHub dans quelques jours...
Je profite de ce post pour vous livrer quelques notes rédigées pour le portage qui pourront être utiles à ceux qui se lancent dans l'aventure Red. La version utilisée est la 0.54.


Red/System permet un accès facile aux dll externes.Néanmoins il y a quelques éléments à savoir.

Les Structures

Les dll utilisent grandement les structures pour communiquer avec le programme appelant.
Red/System possède un type struct! qui est proche du C mais avec quelques différences non-négligeables.
s: declare struct! [
   a   [integer!]
   b   [c-string!]
]


La première est que Red/System considère implicitement les structures comme des pointeurs. Cela nous arrange dans bien des cas, car les fonctions des dll renvoient un pointeur sur une structure
exemple:
image: declare IplImage! ; on déclare une structure et on réserve l'espace mémoire
image: cvCreateImage 640 480 IPL_DEPTH_32F 3 ; image est maintenant un pointeur
sur la structure IplImage! et on peut accéder aux membres de la structure en
utilisant la "path notation"

image/widh = 640
image/height = 480
.... 


Bien que la structure soit implicitement un pointeur, si on besoin de passer en paramètre une structure pointée à la fonction de la dll, il faut IMPERATIVEMENT la passer par référence en forçant le casting avec un pointeur de type byte!, car le compilateur considère que image est une structure et non un pointeur sur la structure (c'est le choix de DocKimbel). On passe donc la structure par référence de façon très classique.
exemple:
cvZero as byte-ptr! image; met tous les pixels de l'image à zéro
[code]

Si maintenant on besoin de passer la structure par valeur à la fonction de la dll,
les choses se compliquent un peu. Les structures ne sont rien d'autre qu'une façon
de réserver un espace en mémoire pour stocker les données. Comme l'espace mémoire
de la dll et celui du code en Red/System n'est pas partagé et qu'implicitement
Red/System fournit une adresse vers la structure, la dll ne connaitra pas la taille
de la structure et la façon de stocker les valeurs associées à chaque membre.
La solution consiste simplement à passer par valeur chacun des membres de la structure. 

exemple
[code]
size: declare CvSize2D32f! (une structure avec 2 membres de type float32!)
size/width: 100.00
size/height: 200.00  
On peut donc écrire 
image: cvCreateImage size/width size/height IPL_DEPTH_32F 3

De cette façon, la dll réserve la place pour stocker 2 float32!

ATTENTION: Toutes les structures OpenCV qui ont été implémentées pour Red/System le sont sous cette forme. La même technique s'applique pour les structures contenant d'autres structures. Chacune des structure imbriquée est décomposée.

exemple:
Red/System permet l'imbrication des structures et on pourrait définir CvBox2D! de la façon suivante

CvBox2D!: alias struct! [
    center      [CvPoint2D32f!] ;center of the box 
    size        [CvSize2D32f!]	;box width and length
    angle       [float32!]	;angle between the horizontal axis and the first side (i.e. length) in degrees
]


mais dans ce cas la fonction C ne saura pas gérer l'espace allouée aux structures imbriquées CvPoint2D32f! et CvSize2D32f!

On choisit donc définir CvBox2D! comme suit:

CvBox2D!: alias struct! [
    x		[float32!] ;center of the box
    y		[float32!] 
    width   [float32!]	;box width and length
    height	[float32!]	
    angle   [float32!]	;angle between the horizontal axis and the first side (i.e. length) in degrees
]



PROBLEME: Le seul problème que je n'ai pas réussi à résoudre est lorsque la dll renvoie une structure et non un pointeur, comme par exemple cette fonction:
size: CvGetSize as byte-ptr! image
On ne récupère que le PREMIER membre de la structure en l'occurence size/width!
J'ai essayé différentes solutions sans succès. Si quelqu'un a une idée lumineuse je suis preneur!


Utiliser les dll avec Red
Nenad a très bien conçu les ponts d'accès entre Red/System et Red grâce à deux outils
# system et les routines.
#System [] vous permet d'importer dans son code red les dll externes et de définir des variables globales que vous pourrez utiliser dans votre code red
exemple
#system [
	; OpenCV functions we need
	#include %../../libs/red/types_r.reds           ; some specific structures for Red/S 
	#include %../../libs/core/types_c.reds          ; basic OpenCV types and structures`
	#include %../../libs/core/core.reds             ; OpenCV core functions
	#include %../../libs/highgui/highgui.reds       ; highgui functions
	#include %../../libs/videoio/videoio.reds       ; to play with camera
]


les routines vous permettent d'appeler à partir de votre code Red les fonctions que vous avez écrites en Red/System pour accéder aux fonctions des dll.
exemple:

createImage: routine [ name [string!]
	] [
	cvInitFont font CV_FONT_HERSHEY_SIMPLEX 2.0 2.0 0.0 1 CV_AA
	image: cvCreateImage width height IPL_DEPTH_32F 3
	cvNamedWindow as c-string! string/rs-head name CV_WINDOW_AUTOSIZE
	cvZero as byte-ptr! image
	cvGetTextSize "Any key to start" font text_size as int-ptr! ymin
	pt1/x: (width - text_size/width) / 2
	pt1/y: (height + text_size/height) / 2
	cvPutText as byte-ptr! image "Any key to start" pt1/x pt1/y font 0.0 56.0 -56.0 0.0
	cvShowImage as c-string! string/rs-head name as byte-ptr! image
	cvwaitKey 0
]



Les routines sont donc une interface entre le code red et le code Red/System. Néanmoins il y a quelques points à savoir.

Les variables globales définies en Red ne sont pas directement accessibles à l'intérieur des routines. En revanche les variables globales peuvent être passées en paramètre au routines. Attention cependant: avec la version 0.54 de red le passage de paramètre est différent selon le type. Les integer!, les pairs! sont passés par valeur et curieusement les floats! par référence (comme un pointeur donc). Je pense que cela sera amélioré par Nenad pour la version 0.6.

De la même façon, le traitement des variables Red/System est différent selon les cas.
les valeurs définies par #define ne sont accessibles que dans l'espace system mais pas dans les routines. En effet, le #define n'est pas une affectation, mais une macro de substitution pour la compilation qui est réservée manifestement à l'espace system. En revanche, les valeurs dans les #enums sont accessibles sans problèmes dans les routines car les éléments de l'énumération sont affectés et peuvent être importés dans les routines qui font l'interface avec Red/System. Bien évidemment tout ce qui est défini dans #system [...] n'est pas directement accessible par le code Red. Les espaces sont préservés et c'est bien pour éviter des effets de bords entre les deux types de code.

Pour le portage d'OpenCV3, j'ai fait un choix simple en ne gardant le #define uniquement pour wrapper les macros OpenCV qui peuvent être exportées par #System [] vers les routines. Toutes les autres valeurs sont affectées comme CV_AA: 16 et sont utilisables par les routines.


#call
Red/System permet d'appeler via #call des fonctions écrites en Red comme par exemple

Red []
inc: func [n [integer!]][random n]
#system [
   #call [inc 255]
   int: as red-integer! stack/arguments
   print int/value                     ;-- will print a random number
]


C'est super, car cela permet de suppléer aux fonctions qui n'existent pas dans le dialecte Red/System comme ici la fonction random. Cependant bien que la doc précise qu'on peut utiliser #call dans les routines, actuellement (0.54) #call ne fonctionne qu'avec #System []. Je pense que cela sera réglé dans les nouvelles versions car c'est très utile.


Le dernier point concerne la vitesse de compilation qui est radicalement augmentée pour red comme le montre les exemples pour un même code Red/System et Red
Red/System

-=== Red Compiler 0.5.4 ===-

Compiling /Users/fjouen/Programmation/Programmation en cours/OpenCV/OpenCV300/Red/samples/_redsystem/trackBar/trackbar.reds ...

Compiling to native code...
...compilation time : 1043 ms
...linking time : 12 ms
...output file size : 28672 bytes
...output file : /Users/fjouen/Programmation/Programmation en cours/OpenCV/OpenCV300/Red/samples/_redsystem/trackBar/trackbar

Red

-=== Red Compiler 0.5.4 ===-

Compiling /Users/fjouen/Programmation/Programmation en cours/OpenCV/OpenCV300/Red/samples/windows/trackbarwindow.red ...
...compilation time : 594 ms

Compiling to native code...
...compilation time : 22430 ms
...linking time : 138 ms
...output file size : 339968 bytes
...output file : /Users/fjouen/Programmation/Programmation en cours/OpenCV/OpenCV300/Red/samples/windows/trackbarwindow


Amitiés à tous
GreG7-Dec-2015/23:33:45+1:00
Merci Francois
Une belle introduction !
ldci11-Dec-2015/15:22:12+1:00
Bonjour à tous,
Comme promis le code est ici: https://github.com/ldci/OpenCV3-red
Comme vous pourrez le voir, les exemples ont été écrits en Red et utilisent les routines. J'aurais quelques améliorations à faire, mais l'idée est de montrer que Red est déjà bien avancé.
Amusez vous bien !
ldci13-Dec-2015/16:55:40+1:00
Bonjour à tous
Le support de Linux est activé. Si des linuxiens peuvent tester cela m'arrangerait
A +
DocKimbel14-Dec-2015/10:59:11+1:00
Félicitations pour le gros boulot sur le support OpenCV pour Red !

Concernant le point suivant:
PROBLEME: Le seul problème que je n'ai pas réussi à résoudre est lorsque la dll renvoie une structure et non un pointeur, comme par exemple cette fonction:
size: CvGetSize as byte-ptr! image
On ne récupère que le PREMIER membre de la structure en l'occurence size/width!
J'ai essayé différentes solutions sans succès. Si quelqu'un a une idée lumineuse je suis preneur!


Il n'y a pas vraiment de standard pour le retour d'un struct en C, mais la plupart des compilateurs l'implémentent de la manière suivante:

* si le struct tient dans 2 registres, il est retourné dans EAX/EDX (sur plateforme 32-bit)
* si le struct est plus grand, un pointeur sur le struct est retourné

Donc, tu peux utiliser system/cpu/edx[/d] (system/cpu/r1 sur ARM) pour récupérer la 2ième valeur dans le cas de CvSize, mais comme tu peux le constater, le code devient dépendant de la plateforme. Il est possible d'écrire une macro qui va tester la plateforme et produire le bon code, mais ça reste une solution de secours et pas vraiment pérenne.

#define GET_CVSIZEY() [#either target = 'IA32 [system/cpu/edx][system/cpu/r1]]


Un vrai support du passage des structs par valeur est nécessaire dans le compilo R/S pour avoir une solution propre. Je vais y travailler dès que possible.

Autre point: . Les integer!, les pairs! sont passés par valeur et curieusement les floats! par référence (comme un pointeur donc). Je pense que cela sera amélioré par Nenad pour la version 0.6.

Oui, les floats sont automatiquement convertis dans la version 0.6.0, tu peux le tester dans la branch master ou bien en téléchargeant une des builds automatiques (je crois que notre serveur de build MacOS X est encore dans les choux...).
ldci16-Dec-2015/9:27:02+1:00
Salut à tous
La solution (temporaire) de Nenad est OK
Voici une implémentation Red/S de la fonction cvGetSize


getSize: func [arr [CvArr!] return: [CvSize!]][
	sz: declare CvSize!
        cvGetSize arr
	sz/width: system/cpu/eax
	cvGetSize arr
	sz/height: system/cpu/edx
	sz
]


Parfait: on récupère bien les deux valeurs

L'autre bonne nouvelle est que les floats sont bien supportés avec la master branch (BTW le serveur Mac est out)
Dès que la 0.6.0 serait terminée, on pourra commencer les choses sérieuses avec les matrices et les blocks! Pour l'instant c'est instable.
On avance, on avance ...
ldci16-Dec-2015/16:06:47+1:00
Bonjour à tous
Je viens de rendre tout le code opencv compatible avec le build automatique (le serveur OSX est de nouveau actif).
Parfait: on a un support des floats et des blocs grandement amélioré.
Quelques points très intéressants qui montrent que Nenad est vraiment un sacré codeur

Le bloc #system est une sorte d'équivalent des fichiers .h en C ou en C++
Vous placez ici avec #include vos fichiers à importer et toutes les directives de compilation nécessaires à la compilation croisée pour les différents OS
Mais vous pouvez également placer ici toutes les variables globales qui seront utilisées par les routines.
C'est propre et efficace: en lisant l'entête vous connaissez les variables et les types que votre code va être amené à utiliser.
Les variables globales red (et non Red/System) sont accessibles aux routines comme paramètres aux fonctions. Ca ça sera bien quand le GUI sera disponible!
Dernier point: le compilateur est beaucoup plus strict maintenant. Gare à vous si vous me définissez pas par /local nom_variable les variables qui sont à l'intérieur de la routine, vous aurez sinon une belle erreur à la compilation. La même punition dans le cas des fonctions inline que vous ajoutez dans la lib.
Mais encore une fois cela force à écrire un code super propre et super clair à lire.
Avec tout ça je vais pouvoir optimiser le code qui gère les matrices OpenCV.
En attendant vous pouvez récupérer sur GitHub et tester les exemples qui fonctionnent parfaitement avec OSX et Windows.
Si un linuxien veut bien se lancer pour les tests cela m'arrangerait.
Amicalement
PierreCh20-Dec-2015/19:50:02+1:00
Bonsoir,
Je suis de retour au pays, et je décide de consacrer du temps à Red/Rebol.
Déjà, je tente de voir/lire/comprendre ce qui s'est déroulé dans le microcosme RedBolien durant les derniers mois (ou plutôt la dernière année) où j'ai été absent.

Pour ce qui concerne, les tests, je veux bien faire le linuxien (enfin, plutôt le GNU/Linuxien) testeur de service. Ça me mettra le pied à l'étrier tout de suite.
Je commence par tout git-puller comme il faut.
ldci25-Dec-2015/2:09:42+1:00
@PierreCh
Quelques tests sous linux Mint 17: premier problème pour installer libtiff4 qui est maintenant obsolète mais néanmoins requis par OpenCV.
Dis moi si tu as une solution.
Amicalement
PierreCh25-Dec-2015/22:26:25+1:00
@tous
Joyeux Noël à tous et toutes!

@ldci
Je suis sous Debian Jessie. Pour l'instant, j'en suis à avoir tout git-cloné, et à me trouver face à:
"This binding can be only used with 3.0 and higher version of opencv library."

Or c'est la version 2.4 qui est disponible sur ma Debian Jessie. Il faut que je voie s'il y a des backports, ou d'autres moyens d'avoir opencv => 3.0.
ldci26-Dec-2015/12:42:35+1:00
Bon Noël à tous!
@PierreCH: le code red est compatible avec les libs 2.4. Il y a juste à changer les liens sur les libs opencv. Faire attention cependant à la structure des répertoires qui est légèrement différente avec opencv3.
Sinon, tu télécharges le zip opencv3 ou 3.10 sur le site et tu recompiles le code avec CMake avec l'option -m32 pour compiler en 32 bits.
Amicalement
ldci26-Dec-2015/12:44+1:00
Suite : à titre d'aide la liste des fonctions

Total Basic C Fonctions OpenCV: 560

calib3D_c.reds: Camera Calibration, Pose Estimation and Stereo
Source: calib3D_c.h
Fonctions: 33
Version: >=3.0.0

core_c.reds: The Core Functionality
Source: core_c.h
Fonctions: 333
Version: >=3.0.0

highgui.reds: Basic GUI functions
Source: highgui_c.reds : c functions
Fonctions: 32
Version: >=3.0.0

imgcodecs_c.reds: images
Source: imgcodecs _c.h
Fonctions: 9
Version: >=3.0.0

imgproc_c.reds: Image Processing
Source: imgproc_c.h
Fonctions: 119
Version: >=3.0.0

objdetect_c.reds: Object Detection
Source: objdetect_c.h
Fonctions: 5
Version: >=3.0.0

photo_c.reds: Inpainting images
Source: photo_c.h
Fonctions: 1
Version: >=3.0.0

video_c.reds: optical flow and motion template
Source: video_c.h
Fonctions: 16
Version: >=3.0.0

Videoio_c.reds: video input functions
Source: videoio_c.h
Fonctions: 12
Version: >=3.0.0
ldci28-Dec-2015/18:44:25+1:00
Bonjour @ tous
Testé en version 3.1.0: je pense qu'on aura du mal à continuer, car les fonctions C disparaissent progressivement pour être remplacées par des API en C++. Ainsi les routines d'accès video utilisant un CvCapture! ne fonctionnent plus sous windows: il faut utiliser un objet VideoCapture. Ceci étant le CvCapture fonctionne toujours avec OSX. Va comprendre pourquoi. Je suis preneur de toute information pour windows.
Amicalement
ldci13-Jan-2016/14:14:04+1:00
Bonjour à tous
Le problème videocapture est réglé via une petite dll que j'ai programmée en C++.
Intéressant car cela ouvre des pistes pour les API en C++
Voici le code.

le fichier.h
#ifndef CAMERALIB_H
#define CAMERALIB_H

#include "cameralib_global.h"
#include <opencv2/opencv.hpp>

using namespace cv;



class CAMERALIBSHARED_EXPORT CameraLib
{

public:
    CameraLib();
};

extern "C"
{
    VideoCapture cam;
    bool openCamera(int index);
    void releaseCamera();
    double getCameraProperty(int propId);
    bool setCameraProperty(int propId, double value);
    bool readCamera(OutputArray image);
}


#endif // CAMERALIB_H


et l'implémentation C++

#include "cameralib.h"

CameraLib::CameraLib()
{
}

bool openCamera(int index)
{
    return cam.open(index);
}

void releaseCamera()
{
    cam.release();
}

bool setCameraProperty(int propId, double value)
{
    return cam.set(propId,value);
}

double getCameraProperty(int propId)
{
    return cam.get(propId);
}

bool readCamera(OutputArray image)
{
    return cam.read(image);
}


Qui pourrait tester ce code dans un environnement 32 bits?
ldci13-Jan-2016/16:12:21+1:00
OK testé en 32 bits. Et ça marche
Pour windows j'ai du rajouter cette macro CAMERALIBSHARED_EXPORT avant chaque méthode comme dans l'exemple

CAMERALIBSHARED_EXPORT bool readCamera(Mat image)
{
    return (CameraLib::readCamera(image));
}



Je fais le lien pour Red dès que possible.
A plus
ldci13-Jan-2016/16:13:19+1:00
OK testé en 32 bits. Et ça marche
Pour windows j'ai du rajouter cette macro CAMERALIBSHARED_EXPORT avant chaque méthode comme dans l'exemple

CAMERALIBSHARED_EXPORT bool readCamera(Mat image)
{
    return (readCamera(image));
}



Je fais le lien pour Red dès que possible.
A plus
ldci18-Jan-2016/18:19:33+1:00
Bonjour à tous
Le lien pour R2 et Red est fonctionnel: on peut utiliser les fonctions C++ pour accéder aux cameras sous windows. J'ai écrit le code de la lib avec Xcode. Un volontaire pour le faire dans l'environnement windows?
Amicalement
ldci23-Jan-2016/18:08:40+1:00
Bonjour à tous

La nouvelle version de OpenCV pour red est disponible https://github.com/ldci/OpenCV3-red.git
J'ai eu quelques problèmes avec GitHub et j'ai été obligé de supprimer la version précédente. Dommage pour le fork et les followers!
De nouvelles fonctionnalités et de nouveaux exemples
Amicalement
ldci4-Feb-2016/16:59:06+1:00
Bonjour
J'ai rajouté différents exemples en Red/System pour tester rapidement les libs.
Amicalement
ldci30-Apr-2016/19:13:40+2:00
Salut à tous
Une version compatible avec view sous windows
https://github.com/ldci/OpenCV3-red
Version très optimisée pour la tranformée d'une image OpenCV en image Red. Pour ceux qui pourraient être intéressés
; get memory as binary! string
getBinaryValue: routine [dataAddress [integer!] dataSize [integer!] return: [binary!] /local src p] [
"Get RBG values from OpenCV Image"
	src: as byte-ptr! dataAddress
	p:  allocate dataSize
	copy-memory p src dataSize
	stack/set-last as red-value! binary/load p dataSize
	binary/load p dataSize
]


Après un simple make Image! avec la chaine renvoyée suffit.
Excellent Red
ldci1-May-2016/14:48:58+2:00
Fonction optimisée !

; get memory as binary! string
; Thanks to Qtxie for the optimization!
getBinaryValue: routine [dataAddress [integer!] dataSize [integer!] return: [binary!]] [
	as red-binary! stack/set-last as red-value! binary/load as byte-ptr! dataAddress dataSize
]
ldci20-Dec-2016/12:42:52+1:00
Bonjour à tous les Reboleurs
J'ai mis à jour OpenCV pour R2 et Red (https://github.com/ldci)
Bonne fêtes de fin d'année à tous
jocko23-Dec-2016/11:07:27+1:00
Merci, joli travail
J'ai juste un peu de problèmes à trouver les chemins des dll (qui sont codés "en dur") (osx et windows)
ldci23-Dec-2016/21:57:19+1:00
Salut Jocko,
Tu trouveras dans /DLLs les versions compilées en 32 bits d'OpenCV pour OSX, Linux and Windows. Tu copies la dll où tu veux et fais le lien dans le fichier /libs/plateform.reds. Nénad m'a dit que la nouvelle version de RED permettrait un accès relatif au fichiers pour les bibliothèques Red/System.
En tout cas Joyeux Noël
ldci24-Dec-2016/15:45:30+1:00
Mise à jour ici: https://github.com/ldci/OpenCV3-red

Login required to Post.


Powered by RebelBB and REBOL 2.7.8.4.2