Rebol et OpenCV | |
ldci | 6-Jul-2013/1:24:27+2:00 |
Bien comme on a perdu le fil, j"en crée un nouveau. Juste pour vous dire que je remonté un vieux Dell Inspiron pour faire des tests et oh, merveille, tout le code fonctionne parfaitement sous windows XP. Il me reste à tester la vidéo dans les jours qui viennent ... Vous pouvez toujours récupérer ici http://www.wuala.com/fjouen/Code/OpenCV/REBOL/samples/ Bon c'est promis, je vais passer sous GitHub ... ASAP | |
ldci | 6-Jul-2013/16:36:01+2:00 |
Bien A part le problème de mémoire, la gestion des caméras est également parfaite avec windows ! D'après ce que j'ai pu lire, le garbage collector de Rebol s'en remet à l'OS pour les structures grosses consommatrices de mémoire. Va falloir que je trouve comment Rebol délègue cette mission à l'OS. A + | |
ldci | 10-Jul-2013/19:55:23+2:00 |
Des infos intéressantes à propos de la gestion de la mémoire avec Rebol/OpenCV Pas évident, car a première vue on n’a pas de GC en C et en C++ : on doit gérer la mémoire soi même. Le principe de base d'opencv: quand on crée une structure (image, matrice…) on doit utiliser une fonction release Exemple: cvCreateCapture -> cvReleaseCapture cvCreateImage -> cvReleaseImage Malheureusement, les fonctions cvRelease ne fonctionnent pas correctement avec Rebol car je pense que Rebol et OpenCV gèrent différemment le malloc associé à la création de la structure et la façon dont ils renvoient la structure. C ou C ++ (et Red/System) renvoient un pointeur (donc une adresse vers la structure) et Rebol une structure considérée comme un pointeur (on doit récupérer l’adresse de la structure soi-même). Exemple de l’utilisation mémoire avec print stats / (10 ** 6) Avant la création de la structure image par cvCreateImage : 6.093174 Après la création de la structure : 6.099702 Après le release de la structure par cvReleaseImage : 6.104198 On ne libère pas la mémoire !!! La solution qui fonctionne est de gérer soi-même la libération de la mémoire avec Rebol en utilisant la fonction free-mem de Nenad free-mem: func ['word] [set :word make none! recycle] Avant la création de la structure image par cvCreateImage : 6.093174 Après la création de la structure : 6.099702 Après le release de la structure free-mem image : 5.066818 On libère bien la mémoire allouée !! Cette technique fonctionne pour les images créées ou chargées Voici un bon moyen de gérer les fuites mémoire d’OpenCV Le seul cas où cette technique ne fonctionne pas c’est quand les images proviennent de la caméra ou d’un film vidéo. Dans ce cas, la mémoire est gérée par le « driver vidéo » et échappe à notre code. Ceci n’est pas spécifique à Rebol, mais à OpenCV. Le problème est qu’a vraiment un « memory leak » et pour ce cas je n'ai pas encore trouvé de solution efficace. Le bon point c'est que ce n'est pas lié au GC de Rebol A + | |
ldci | 11-Jul-2013/20:58:47+2:00 |
La suite des aventures avec les webcams! Pour la fuite mémoire, pas de pb avec Red/System ou avec du C. Pour Rebol, le GC fait son travail à intervalles réguliers : il suffit de mettre l’image issue de la webcam à none pour que le GC fonctionne et libère bien la mémoire: Exemple : foo: 0 ; repeat until q keypress (key: #"q"; 113 as integer) while [foo <> 113] [ image: cvQueryFrame capture ; get image cvShowImage "Test Window" image ; show frame print ["used : " system/stats / (10 ** 6)] ; used memory image: none ; free image foo: cvWaitKey 1 ] Bien, ce n'était pas évident, mais ça marche. Dernier point: Il ne faut surtout pas appeler un recycle à l’intérieur de la boucle, sinon le GC s’affole et ne sert plus à rien (je crois que ce point est documenté chez RT). Ah Rebol | |
ldci | 14-Jul-2013/20:22:46+2:00 |
Suite et fin ... Le dernier point à régler est la fonction cam2Rebol qui pose pb : A première vue, l’utilisation de timers entraîne un memory leak !!! (cf rambo) Am Freitag, 17. Oktober 2003 00:05 schrieb Terry Brownell: ➢ I've noticed a memory leak when you hover a mouse over any face using the > "feel" user interface events. Is this a known bug or ? If you run the > example below, and watch the memory usage of the Rebol.exe running it, it > will go up when you hover. Same thing with the engage feel. > Après une série de tests, l’utilisation de timers n’entraîne pas de memory leak. Ce point a dû être réglé par RT dans les mises à jour. C’est bien la fonction de conversion OpenCV to Rebol qui pose pb uniquement pour les images issues d’une caméra. Fondamentalement, cette fonction récupère le contenu binaire de l’image OpenCV via un pointeur puis crée une image rebol qui est renvoyée vers une face de type image (exemple : isu/image : cam2Rebol imageCV. cam2Rebol: func [src /local data im] [ rgb: get-memory src/imageData src/imageSize rgb: reverse data im: make image! reduce [as-pair (src/width) (src/height) rgb] ] Rien de bien sorcier en soi : les données sont bien récupérées et affichées correctement dans le widget. Par contre chaque appel à cette fonction augmente le mémoire consommée et provoque un crash quand la mémoire est épuisée. J’ai d’abord suspecté Rebol de me créer autant d’instance de l’image que d’appel à la fonction. Mais ce n’est pas le cas : for i 1 10000 1 [ rgb: 0.0.0 im: make image! reduce [512x512 rgb] visu/image: im visu/image/text: join to-string i [": Used Mem: " round/to stats / (10 ** 6) 0.01] show visu ] n’entraîne pas de consommation de mémoire et le GC fait son travail. J’ai donc pensé ensuite à un pb avec le get-memory. J’ai donc remplacé rgb: get-memory src/imageData src/imageSize par rgb: 0.0.0 sans succès : toujours une fuite mémoire. Il y a bien un problème avec la fonction cvQueryFrame capture (grab and retrieve image) avec Rebol qui se comporte comme si chaque image recueillie était une nouvelle instance de la structure IplImage ! (expliquant ainsi la fuite de mémoire). Finalement, la solution consiste à ne pas demander à Rebol de transformer les images et de laisser OpenCV faire les affichages dans son propre espace graphique: image: cvQueryFrame capture ; grab and retrieve image cvShowImage « testWindow » image Avec cette technique plus de problème : l’affichage par OpenCV ne joue pas sur le GB de Rebol qui assure correctement son travail. Comme je n’ai pas ce problème avec Red/System, je pense vraiment que cette difficulté est liée à la façon dont Rebol traite les structures renvoyées par les routines OpenCV (cf. supra) A suivre … | |
PierreCh | 16-Jul-2013/12:20:27+2:00 |
Ce problème, il survient avec Rebol 3? | |
ldci | 16-Jul-2013/21:35:33+2:00 |
@PierreCh: pour l'instant je n'ai pas investi Rebol3 qui n'est pas stabilisé (notamment avec Mac OSX) et ne possède pas beaucoup de documentation. | |
PierreCh | 16-Jul-2013/23:39:29+2:00 |
Oui, j'en suis un peu au même stade... Mais au moins, avec Rebol 3, nous eûssions pu savoir, en nous plongeant dans son code, d'où venait l'âne au Mali. | |
ldci | 18-Jul-2013/17:29:01+2:00 |
allez une petite image http://www.wuala.com/fjouen/Code/OpenCV/REBOL/pub/4Cams.jpg/ Comment gérer 4 cameras (ou plus) avec rebol ou red. Chaque caméra est indépendante des autres et peut avoir son propre FPS. A plus | |
PierreCh | 25-Jul-2013/18:35:51+2:00 |
Youpi, j'ai retrouvé une trace du fil précédent, qui s'était perdu: http://web.archive.org/liveweb/http://www.digicamsoft.com/cgi-bin/rebelBB.cgi?thread=%3C25May2012200150764026200%3E | |
PierreCh | 25-Jul-2013/18:40:47+2:00 |
Ah non, mince, pardon; j'ai causé trop vite, il n'y a pas tout le fil... :-s | |
ldci | 12-Sep-2013/15:11:50+2:00 |
Salut à tous De retour sur le site avec de bonnes nouvelles pour openCV J'ai mis à jour les libs (à récupérer sur Wuala) ainsi que le fichier opencv.r Pour simplifier le travail de ceux qui veulent faire des tests, j'ai introduit une fonction qui permet de sélectionner la version (1.0.0 ou 2.0.0) d'opencv et ce en fonction de son OS. Bon évidement on peut adapter selon ses propres besoins usedLib: func [version [tuple!]] [ runningOs: getOs if runningOs = "Mac OS X" [ switch version [ 1.0.0 [ocv: load/library %/Library/Frameworks/OpenCV1-0.framework/Versions/A/OpenCV] 2.0.0 [ocv: load/library %/Library/Frameworks/OpenCV2-0.framework/Versions/B/OpenCV] ] cvision: ocv highgui: ocv cxcore: ocv ] if runningOs = "Windows" [ switch version [ 1.0.0 [ cxcore: load/library to-file "c:\windows\system32\cxcore100.dll" cvision: load/library to-file "c:\windows\system32\cv100.dll" highgui: load/library to-file "c:\windows\system32\highgui100.dll" ] 2.0.0 [ cxcore: load/library to-file "c:\OpenCV2.0\bin\libcxcore200.dll" cvision: load/library to-file "c:\OpenCV2.0\bin\libcv200.dll" highgui: load/library to-file "c:\OpenCV2.0\bin\libhighgui200.dll" ] ] ] if runningOs = "linux" [ switch version [ 2.0.0 [ cxcore: load/library to-file "/usr/lib/libcxcore.so.2.1" cvision: load/library to-file "/usr/lib/libcv.so.2.1" highgui: load/library to-file "/usr/lib/libhighgui.so.2.1" ] ] ] ] ; l'appel est enfantin opencvVersion: 2.0.0 usedLib opencvVersion L'autre bonne nouvelle est qu'un étudiant de Master rejoint le projet: il va pouvoir améliorer et optimiser le portage? Cool, non? A + | |
ldci | 19-Sep-2013/21:55:19+2:00 |
Allez pour mettre un peu d'animation sur le site ... Rebol et OpenCV, c'est génial | |
ldci | 19-Sep-2013/21:56:10+2:00 |
Allez pour mettre un peu d'animation sur le site ... Rebol et OpenCV, c'est génial | |
ldci | 19-Sep-2013/21:56:39+2:00 |
Allez pour mettre un peu d'animation sur le site ... Rebol et OpenCV, c'est génial | |
ldci | 19-Sep-2013/21:56:52+2:00 |
Allez pour mettre un peu d'animation sur le site ... Rebol et OpenCV, c'est génial | |
ldci | 20-Sep-2013/13:22:59+2:00 |
désolé Je ne sais pas ce qu'il s'est passé avec l'image findfaces.jpg http://www.wuala.com/fjouen/Code/OpenCV/REBOL/pub/findfaces.jpg/ en tout cas voici le code qui permet de retrouver des visages dans une image findFaces: does [ ; looks for n faces in image use the fastest variant if isImage [cvZero isource isource: cvLoadImage file CV_LOAD_IMAGE_UNCHANGED cvShowImage "Input" isource] faces: cvHaarDetectObjects babyface cascade storage 1.1 2 CV_HAAR_DO_CANNY_PRUNING 20 20 for i 1 faces/total 1 [ faceRect: cvGetSeqElem faces i 0 ; we get a pointer to 4 integers x: to-integer reverse get-memory faceRect + 0 4 y: to-integer reverse get-memory faceRect + 4 4 wd: to-integer reverse get-memory faceRect + 8 4 hg: to-integer reverse get-memory faceRect + 12 4 roi: cvRect (x * scale) (y * scale) ((x + wd) * scale) ((y + hg) * scale) cvRectangle isource roi/x roi/y roi/width roi/height 0 255 0 0 thickness lineType 0 ] cvShowImage "Input" isource ] | |
ldci | 20-Sep-2013/13:23:10+2:00 |
désolé Je ne sais pas ce qu'il s'est passé avec l'image findfaces.jpg http://www.wuala.com/fjouen/Code/OpenCV/REBOL/pub/findfaces.jpg/ en tout cas voici le code qui permet de retrouver des visages dans une image findFaces: does [ ; looks for n faces in image use the fastest variant if isImage [cvZero isource isource: cvLoadImage file CV_LOAD_IMAGE_UNCHANGED cvShowImage "Input" isource] faces: cvHaarDetectObjects babyface cascade storage 1.1 2 CV_HAAR_DO_CANNY_PRUNING 20 20 for i 1 faces/total 1 [ faceRect: cvGetSeqElem faces i 0 ; we get a pointer to 4 integers x: to-integer reverse get-memory faceRect + 0 4 y: to-integer reverse get-memory faceRect + 4 4 wd: to-integer reverse get-memory faceRect + 8 4 hg: to-integer reverse get-memory faceRect + 12 4 roi: cvRect (x * scale) (y * scale) ((x + wd) * scale) ((y + hg) * scale) cvRectangle isource roi/x roi/y roi/width roi/height 0 255 0 0 thickness lineType 0 ] cvShowImage "Input" isource ] | |
PierreCh | 20-Sep-2013/23:55:57+2:00 |
En effet, cela a l'air rigolo! | |
ldci | 10-Mar-2014/14:26:27+1:00 |
Salut à tous Comme je vous l'avais annoncé il y a quelque temps, je suis en train de revoir tout le portage OpenCV vers Rebol et Red avec un de nos étudiants. J’aurais besoin de vos idées pour un petit problème. Comme l’avait bien documenté François Vanzeveren (vieux site Rebol ), Le type REBOL Struct ! n’est pas identique à une structure en C, car une structure REBOL est interprétée comme un pointeur, c’est-à-dire l’équivalent de struct* en C. Cela facilite l'accès au libraires externes qui font appel aux pointeurs. Ceci étant on a un problème lorsque la routine renvoie une C structure et non un pointeur comme dans l’exemple : CVAPI(CvSize) cvGetSize( const CvArr* arr ). La structure renvoyée CvSize contient deux entiers : width et height L'implémentation suivante en rebol ne fonctionne pas car elle ne renvoie que le premier entier et non les deux cvGetSize: make routine! compose/deep/only [ Returns width and height of array in elements arr [struct! (first CvArr!)] return: [integer! integer!]; CvSize not a pointer ] cxcore "cvGetSize" le reduce [integer! integer!] ne marche pas non plus. Qui aurait une idée lumineuse? | |
DocKimbel | 12-Mar-2014/10:58:22+1:00 |
Tu peux tenter de renvoyer un type decimal! et tu y accèdes en mode binaire ensuite pour extraire les deux entiers 32 bits. | |
ldci | 7-Apr-2014/13:31:10+2:00 |
Des nouvelles de la gestion de la mémoire. Bon à savoir J'ai trouvé pour les problèmes de consommation mémoire! http://www.rebol.com/docs/library.html#Garbage Il suffit de protéger les structures passées en paramètres aux routines pour éviter qu'elles tombent dans les oubliettes du Garbage Collector de Rebol avec [save] Exemple IplImage!: make struct! compose/deep/only [ [save] ; specific to rebol to inhibe GC ; nSize [integer!] ; sizeof(IplImage) ID [integer!] ; version (=0) nChannels [integer!] ; Most of OpenCV functions support 1,2,3 or 4 channels alphaChannel [integer!] ; Ignored by OpenCV */ depth [integer!] ; Pixel depth in bits: colorModel [integer!] ; Ignored by OpenCV char [4] channelSeq [integer!] ; ditto * dataOrder [integer!] ; 0 - interleaved color channels, 1 - separate color channels. origin [integer!] ; 0 - top-left origin, 1 - bottom-left origin (Windows bitmaps style). align [integer!] ; Alignment of image rows (4 or 8).OpenCV ignores it and uses widthStep instead. width [integer!] ; Image width in pixels height [integer!] ; Image height in pixels. ` roi [int]; [struct! (first IplROI! )] ; Image ROI. If NULL, the whole image is selected we absolutely need a pointer to IplRoi! structure when using routines with a ROI maskROI [int]; [struct! (first IplImage!)] ; Must be NULL [0]. IplImage! : pointer to maskROI if any imageId [int] ;[void*] ; " " tileInfo [int] ;[struct! (first IplTileInfo! )] ; [int]; here also" " imageSize [integer!] ; Image data size in bytes imageData [int]; [char*] ; Pointer to aligned image data. widthStep [integer!] ; Size of aligned image row in bytes. BorderMode [integer!] ; Ignored by OpenCV. BorderConst [integer!] ; Ditto. imageDataOrigin [int] ; Pointer to very origin of image data ] none Ca marche nickel et évite les fuites mémoires observées avant. | |
Login required to Post. |