Lecture de code à barre et QR Code avec OpenCV et zbar

Voici la démarche pour faire un lecteur de code à barre pour Raspberry en utilisant OpenCV et l’API zbar.

Pré-requis :

Ensuite, il suffit d’utiliser ce petit programme :

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <zbar.h>
#include <iostream>

using namespace cv;
using namespace std;
using namespace zbar;

int main(int argc, char* argv[])
{
   VideoCapture cap(0); // open the video camera no. 0
   // cap.set(CV_CAP_PROP_FRAME_WIDTH,800);
   // cap.set(CV_CAP_PROP_FRAME_HEIGHT,640);
   if (!cap.isOpened()) // if not success, exit program
   {
      cout << "Cannot open the video cam" << endl;
      return -1;
   }

   ImageScanner scanner;
   scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);

   double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
   double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

   cout << "Frame size : " << dWidth << " x " << dHeight << endl;

   namedWindow("MyVideo", CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"

   while (1)
   {
      Mat frame;
      bool bSuccess = cap.read(frame); // read a new frame from video

      if (!bSuccess) //if not success, break loop
      {
         cout << "Cannot read a frame from video stream" << endl;
         break;
      }

      Mat grey;
      cvtColor(frame, grey, CV_BGR2GRAY);

      int width = frame.cols;
      int height = frame.rows;
      uchar *raw = (uchar *)grey.data;

      // wrap image data
      Image image(width, height, "Y800", raw, width * height);

      // scan the image for barcodes
      int n = scanner.scan(image);

      // extract results
      for(Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol)
      {
         vector<Point> vp;

         // do something useful with results
         cout << "decoded " << symbol->get_type_name() << " symbol \"" << symbol->get_data() << "\"" << endl;

        int n = symbol->get_location_size();
        for(int i=0;i<n;i++)
        {
           vp.push_back(Point(symbol->get_location_x(i), symbol->get_location_y(i)));
        }

        RotatedRect r = minAreaRect(vp);
        Point2f pts[4];
        r.points(pts);

        for(int i=0;i<4;i++){
          line(frame, pts[i], pts[(i+1)%4], Scalar(255,0,0), 3);
        }

        cout<<"Angle: "<<r.angle<<endl;
     }

     imshow("MyVideo", frame); //show the frame in "MyVideo" window

     if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
     {
         cout << "esc key is pressed by user" << endl;
         break;
     }
   }
   return 0;
}

Voici la ligne de commande pour le compiler :

g++ test.cpp -lopencv_highgui -lopencv_core -lopencv_imgproc -lzbar

A noter que pour ceux qui utilisent la raspicam : Elle est montée d’origine pour faire un focus à distance infinie… Ce qui ne nous arrange pas pour passer un code à barre ou un QR Code à 10cm de la lentille (l’image obtenue est floue et donc non reconnue). En fait, l’astuce consiste à dévisser la lentille afin de régler le focus aux alentours de 10cm. J’ai trouvé l’astuce sur ce lien : http://elinux.org/Rpi_Camera_Module (Paragraphe Customizing -> Adjusting Lens Focus).

ATTENTION : Pour ne pas abimer la lentille, il ne faut pas utiliser de pince ! Ça dérape facilement… ^^’ Je pense qu’avec une gomme pressée sur la lentille permettrait de la débloquer. Un fois la lentille débloquée, elle se dévisse / revisse facilement à la main.

 

18 réflexions sur « Lecture de code à barre et QR Code avec OpenCV et zbar »

  1. Hey, I’ve just looked through your tut by using google translate ( I dont know French). My project is reading the barcode using raspberry pi with webcam and then using the output to compare to a database, whether the code in the database or not.
    I dont know how to run your script. It looks like it’s C-language? What I have to do before the compiling process?

    • Hello !

      My script is not a script but a source of C++ code. All you have to do is to compil and install OpenCV Framework (see my post install OpenCV).
      Then, if you use raspicam (and only if you use it), you must install uv4l driver (see my post install uv4l driver).
      And then, you have to compil and install zbar Framework (see my post install zbar).

      Now, this C++ source code can compil. To do this, copy and past the source code to one file (« test.cpp » in my exemple) and run the command Line in this post (« g++ test.cpp -lopencv_highgui -lopencv_core -lopencv_imgproc -lzbar »).

      If no error occurs, this command line create a binary named a.out. You can run this program site this command line :

      ./a.out

      Y hope that my English is not too bad ^^’.

  2. Salut,
    je suis tombé sur ton site car j’essaye de lire un qrcode et le retranscrire en fichier .txt
    J’ai donc tout suivi à la lettre, d’ailleurs l’install d’OpenCV est effectivement bien longue..
    Du coup j’ai compilé et lancé la commande ./a.out et j’obtiens cela :
    HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP
    Frame size : 640 x 480
    : cannot connect to X server

    Je ne vois pas quand est ce dans le programme qu’il y a c message d’erreur.
    Ou est ce que je configure mon server web ?

    Merci pour tes informations, je ne suis pas encore expert en développement. =)

    • Rien a voir avec le serveur Web. Cette erreur survient car l’application est en mode fenêtrée et qu’elle désire afficher son contenu dans une fenêtre, mais qu’aucun gestionnaire de fenêtre n’est disponible (server X). Avez-vous essayé de lancer l’application depuis le bureau du raspberry (branché en HDMI sur un moniteur, session ouverte sur ce moniteur) ?

  3. Bonjour,
    j’ai suivi chacune des étapes, mais l’ouverture de la caméra ne fonctionne pas (IsOpen() == false).
    Pourtant:
    – open cv est bien linké;
    – zbar est bien linké;
    – le programme s’exécute;
    – raspistill fonctionne bien pour prendre des photos;
    – j’ai déjà capturé des vidéos de plusieurs minutes en python;

    Une piste ?

    Cordialement.

    • La seule piste que je vois est un problème de pilote de la raspicam. En effet, OpenCV ne fonctionne pas nativement avec cette caméra. Il faut obligatoirement installer le pilote uv4l. Mis à part cela, je ne vois pas :-/

  4. bonjour

    tout le code fonctionne tres bien, avec le bureau demarré, mais si je veux le lancer en mode console j’obtiens cette erreur :
    HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP
    Frame size : 640 x 480
    : cannot connect to X server

    est-il possible de lancer le programme sans avoir le bureau, uniquement en mode console ?

    • Bonjour,

      Le programme tel qu’il a été écrit doit obligatoirement avoir un bureau démarré. Si l’on veut l’utiliser uniquement en mode console, alors il faut en écrire un autre pour qu’il puisse se passer du mode fenêtré.

  5. Salut.
    merci pour tes expliquations, c’est exactement ce que je cherchais, on va l’utiliser dans notre projet open source.
    n’ésites pas a me contacter si tu veux des informations.

  6. Salut! Merci bien pour partager cette piéce de code 🙂 Si vous utilisez opencv 3.1, J’ai trouvé il faut ajouter encore un autre paramètre a la ligne de commande pour bien contruire le fichier executable, a suivre:
    g++ test.cpp -lopencv_highgui -lopencv_imageio -lopencv_core -lopencv_imgproc -lzbar
    Et aussi ajouter le header correspondant aux fichier source:
    #include

  7. Hi,

    you’ve made a very nice tutorial. It just won’t work for me. I do every part as told and by trying to run the test.cpp I get errors that the predicted functions like videocapture from opencv can’t be found. I tried different approaches. Best guess would be that it’s triggered by some differences do you have this setup as an image of your sd card or something like this? I would appreciate it very much.

    Best Wishes
    kallell

  8. Bonjour,
    J’ai à priori tout installé, le driver V4L aussi.
    La compilation ne donne pas d’erreur.
    Quand je lance le programme a.out j’ai les messages suivants :
    /dev/video0 does not support memory mapping
    munmap : Invalid argument
    munmap : Invalid argument
    munmap : Invalid argument
    munmap : Invalid argument
    Unable to stop the stram. : Bad file descriptor
    munmap : Invalid argument
    munmap : Invalid argument
    munmap : Invalid argument
    munmap : Invalid argument
    Frame size : 640 x 480

    et sur mon écran, j’ai deux fenêtres vidéo qui s’ouvrent, une petite centée et une autre appelée MyVideo que je peux déplacer sur l’écran.

    De plus, je ne peux pas sortir du programme sinon en fermant la fenêtre du terminal.
    Si vous avez des pistes, je vous remercie d’avance.
    Cordialement

  9. bonjour
    j’ai compiler ce programme mais j’ai trouvée une erreur .est ce que c’est possible de me guider que ce que je fais .
    cordialement .
    ||=== Build: Debug in code barre (compiler: GNU GCC Compiler) ===|
    /home/pi/Desktop/Haifa/code barre /main.cpp|3|fatal error: zbar.h: No such file or directory|
    ||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|

    c’est erreur au niveau #include

  10. Bonjour,

    Lorsque je compile le source présenté avec openCV 3.3.0 j’obtiens l’erreur suivante:
    /usr/bin/ld: /tmp/ccVcFtfJ.o: undefined reference to symbol ‘_ZN2cv12VideoCaptureD1Ev’
    //usr/local/lib/libopencv_videoio.so.3.3: error adding symbols: DSO missing from command line
    collect2: error: ld returned 1 exit status
    root@Rpi-Dev:/home/pi/BarCode# make
    make: *** No targets specified and no makefile found. Stop.

    A priori tout s’est bien installé correctement.
    Ca pourrait venir de la version 3.3.0 que j’utilise ?

    Merci

    • Bonjour,

      Oui, la version d’openCV 3.3 n’a pas les même pré-requis que celle que j’ai utilisée. Il faut regarder ce dont à besoin openCV en version 3.3 et voir s’il est possible de les récupérer.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.