1

I have a piece of code that takes a screenshot of a window using XGetImage, converts it into OpenCV Mat object format. There is no problem with that.

Now, I have another piece of the code that detects QR code in another image using the Zbar library. Even this part works well when compiled.

But, when I merge both the codes so that I detect QR code in the screenshot of the window taken and compile the code, it gives me an error like the one below.

As far as I understand this error, it means that Window structure is defined in both the Zbar library and X11 library, in different ways, and hence the compiler is in a dilemma as to which one should be chosen.

The Window structure I am using here is that of the X11 library, not the Zbar's.

So, I would like to know if there is any method to specify which library should be chosen before using that particular structure in the code so that the compiler doesn't get confused. Or is it impossible?

For QR code detection, I referred this

Here is the code that I have been running:

//                                      SCANS AND REPLACES QR CODE IN A VIDEO BY REAL-TIME WINDOW SCREENSHOT

// can also stream any window that needs keyboard to work with
/*

    COMPILATION ...

    g++ ScrQr.cpp -o go `pkg-config --cflags --libs opencv` -lX11 -L/usr/local/lib -lzbar

*/



#include <opencv2/opencv.hpp>
#include <zbar.h>

#include <opencv2/core.hpp>     // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp>  
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

// ========= INCLUDING THE C and C++14 HEADERS ==========
#include<bits/stdc++.h>     // FOR C++

#include <stdio.h>          // FOR C 
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>   
#include <unistd.h>   // for sleep() function

#define NIL (0)       // A name for the void pointer


// ============ INCLUDING THE X11 HEADERS ================

#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xlib.h> // Every Xlib program must include this
#include <X11/Xlib.h>
#include <X11/Xatom.h>


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




typedef struct
{
  string type;
  string data;
  vector <Point> location;
} decodedObject;

// Find and decode barcodes and QR codes
void decode(Mat &im, vector<decodedObject>&decodedObjects)
{

  // Create zbar scanner
  ImageScanner scanner;

  // Configure scanner
  scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);

  // Convert image to grayscale
  Mat imGray;
  cvtColor(im, imGray,COLOR_BGR2GRAY);

  // Wrap image data in a zbar image
  Image image(im.cols, im.rows, "Y800", (uchar *)imGray.data, im.cols * im.rows);

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

  // Print results
  for(Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol)
  {
    decodedObject obj;

    obj.type = symbol->get_type_name();
    obj.data = symbol->get_data();

    // Print type and data
    cout << "Type : " << obj.type << endl;
    cout << "Data : " << obj.data << endl << endl;

    printf("-----------------------------------------------\n");
    // Obtain location
    for(int i = 0; i< symbol->get_location_size(); i++)
    {
      obj.location.push_back(Point(symbol->get_location_x(i),symbol->get_location_y(i)));
      cout << Point(symbol->get_location_x(i),symbol->get_location_y(i)) << "\n";   
    }
    printf("-----------------------------------------------\n");    
    decodedObjects.push_back(obj);
  }
}

// Display barcode and QR code location  
void display(Mat &im, vector<decodedObject>&decodedObjects, Mat scrn)
{
  cout << "decode obj size: " << decodedObjects.size() << "\n";

  int wid, ht, startx, starty;
  Mat toembed = scrn;       //imread("sample.jpg");


  // Loop over all decoded objects
  for(int i = 0; i < decodedObjects.size(); i++)
  {
    vector<Point> points = decodedObjects[i].location;
    vector<Point> hull;

    // If the points do not form a quad, find convex hull
    if(points.size() > 4)
      convexHull(points, hull);
    else
      hull = points;

    // Number of points in the convex hull
    int n = hull.size();

    for(int j = 0; j < n; j++)
    {
      line(im, hull[j], hull[ (j+1) % n], Scalar(255,0,0), 3);
      cout << "Getting indivs => " << hull[j].x << " "  << hull[j].y << "\n****\n";
    }


    wid = hull[3].x - hull[0].x + 1;
    ht = hull[2].y - hull[0].y + 1;
    startx = hull[0].x;
    starty = hull[0].y;

    printf("startx and starty ==> %d %d *********\n", startx, starty);

    Mat scrap(wid, ht, CV_8UC3);                // created just for Size structure argument of the resize() func.
    resize(toembed, toembed, scrap.size(), CV_INTER_AREA);


    // Replacing QR by resized window screenshot
    for(int j=0;j<ht;j++)       // j counts height, hence y
    {
      for(int k=0;k<wid;k++)    // k counts width, hence x
      {
        im.at<cv::Vec3b>(starty + k, startx + j)[0] = toembed.at<cv::Vec3b>(k, j)[0];
        im.at<cv::Vec3b>(starty + k, startx + j)[1] = toembed.at<cv::Vec3b>(k, j)[1];
        im.at<cv::Vec3b>(starty + k, startx + j)[2] = toembed.at<cv::Vec3b>(k, j)[2];
      }
    }

  }

  // Display results
  namedWindow("Result Video", CV_WINDOW_NORMAL); 
  imshow("Result Video", im);
  //waitKey(0);

}



// TO GENERATE LIST OF ALL OPEN WINDOWS
Window *winlist (Display *d, unsigned long *len)    // Generates the list of windows required
{
    Atom prop = XInternAtom(d,"_NET_CLIENT_LIST",False), type;  // _NET_CLIENT_LIST gives all the windows in the heirarchy
    int form;               // ignore
    unsigned long remain;   // ignore
    unsigned char *list;    // here we are specifying that we need window references as names (chars)                                       

    errno = 0;                      // ignore


    if (XGetWindowProperty(d,XDefaultRootWindow(d),prop,0,1024,False,XA_WINDOW, // getting the properties here
                &type,&form,len,&remain,&list) != Success) {
        perror("winlist() -- GetWinProp");
        return 0;
    }

    return (Window*)list;               // returning the list here (Now the list is bearing the reference of every window)
}

// TO GET THE NAME OF A PARTICULAR WINDOW
char *winame (Display *d, Window win)   
// We are basically importing the specific Windows here and returning theirr names !!!!!!
{
    Atom prop = XInternAtom(d,"WM_NAME",False), type;   // Atom property, 
                                                        // here we are asking for Window Names
    int form;                   // ignore
    unsigned long remain, len;  // ignore
    unsigned char *list;        // this list holds name of the specific window only
    errno = 0;

    if (XGetWindowProperty(d,win,prop,0,1024,False,XA_STRING,   // list is updated here
                &type,&form,&len,&remain,&list) != Success) {
        perror("winlist() -- GetWinProp");
        return NULL;
    }

    return (char*)list;     // The list, bearing the name of that window, is returned
}



int main(int argc, char* argv[])
{

  VideoCapture cap("cam_qr_vid.mp4");
  Mat QR;// = imread("qr.jpg"); 

  if(!cap.isOpened())
  {
    printf("Video not playing ... \n");
    exit(0);
  }

    Display *d;         // X display object
    Window root;        // X Root object
    int width, height;  // For Width and Height of the VM

    // Open the display
    d = XOpenDisplay(NIL);
    assert(d);          // Signal if no display found


    // Listing all active windows...
    int i;                      // Just a counter
    unsigned long len;          // For number of windows open
    Window *list;               // Window type list (holds the Window IDs of active windows)
    char *name;

    list = (Window*)winlist(d,&len);        // Getting the list         // GOTO winlist()

    cout << "Number of open windows >> " << len << "\n";

    cout << " >>> Index of the Window and the Window in the Stack <<< \n";

    for (i=0;i<(int)len;i++) 
    {           
        name = winame(d,list[i]);       // getting name             // GOTO winame()
        printf("--> %2d\t%s<--\n",i,name);
        free(name);             // clearing memory
    }
    cout << "------------------------------------------------------------------------------\n";
    int choice;
    cout << "Which window should be streamed ?? (0 indexed) :  ";
    cin >> choice;
    cout << "------------------------------------------------------------------------------\n";


    // %%%%%%%%%%%%%%%%%%% SETTING UP WINDOW SCREENSHOT PART %%%%%%%%%%%%%%%%%
    Window focal = list[choice];

    // Taking image of of the desired window:
    XWindowAttributes gwa;
    XGetWindowAttributes(d, focal, &gwa);   
    int wd1 = gwa.width;
    int ht1 = gwa.height;

    XImage *image = XGetImage(d, focal, 0, 0 , wd1, ht1, AllPlanes, ZPixmap);
    unsigned long rm = image->red_mask;
    unsigned long gm = image->green_mask;
    unsigned long bm = image->blue_mask;

    Mat img(ht1, wd1, CV_8UC3);             // OpenCV Mat object is initilaized

    for (int x = 0; x < wd1; x++)
        for (int y = 0; y < ht1 ; y++)
        {
            unsigned long pixel = XGetPixel(image,x,y);     
            unsigned char blue = pixel & bm;                // Applying the red/blue/green mask to obtain the indiv channel values
            unsigned char green = (pixel & gm) >> 8;
            unsigned char red = (pixel & rm) >> 16;     

            Vec3b color = img.at<Vec3b>(Point(x,y));        // Store RGB values in the OpenCV image
            color[0] = blue;
            color[1] = green;
            color[2] = red;
            img.at<Vec3b>(Point(x,y)) = color;
        }



  VideoWriter video("QRRealtimeWindow.avi", CV_FOURCC('M','J','P','G'), 10, Size(1280,720));
  namedWindow("Actual Video", CV_WINDOW_NORMAL);
  while(1)
  {
    // Read image
    Mat im;// = imread("rq_dec.jpg");

    cap >> im;      // `im` has the QR code frame in it
    cap >> QR;

    if(im.empty())
        break;

    printf("R = %d and C = %d===============\n", im.rows, im.cols);


    // ------------------ @@@@@ Screenshot part ------------------------

    XImage *image = XGetImage(d, focal, 0, 0 , wd1, ht1, AllPlanes, ZPixmap);

    // Getting the R, G, B masks of the XImage object
    rm = image->red_mask;
    gm = image->green_mask;
    bm = image->blue_mask;

    // CONVERTING THE XIMAGE TO OPENCV Mat FROMAT, PIXEL-BY-PIXEL
    for (int x = 0; x < wd1; x++)
    {           
        for (int y = 0; y < ht1 ; y++)
        {

            unsigned long pixel = XGetPixel(image,x,y);     
            unsigned char blue = pixel & bm;                // Applying the red/blue/green mask to obtain the indiv channel values
            unsigned char green = (pixel & gm) >> 8;
            unsigned char red = (pixel & rm) >> 16;     

            Vec3b color = img.at<Vec3b>(Point(x,y));        
            color[0] = blue;                                // Updating the individual channel values
            color[1] = green;
            color[2] = red;
            img.at<Vec3b>(Point(x,y)) = color;
        }   
    }

    // `img` has the window screenshot



    //  ------------ @@@@@@ Replacer PART -------------------------

    // Variable for decoded objects 
    vector<decodedObject> decodedObjects;

    // Find and decode barcodes and QR codes
    decode(im, decodedObjects);

    // Display location 
    display(im, decodedObjects, img);   // pass the window screenshot and the frame to modify the frame


    // ------------ @@@@@@@@@ Saving the video part
    video.write(im);

    imshow("Actual Video", QR);

    if(waitKey(40)==27)     // Necessary if the video should be viewable. 
        break;                  // If t increases in waitKey(t), video becomes slower. `27` means, press ESC to stop

  }

  video.release();
  cap.release();

  return EXIT_SUCCESS;
}

And here is the error message:

ScrQr.cpp:167:1: error: reference to ‘Window’ is ambiguous
 Window *winlist (Display *d, unsigned long *len)  // Generates the list of windows required
 ^
In file included from /usr/include/X11/Xlib.h:44:0,
                 from /usr/include/X11/Xutil.h:53,
                 from ScrQr.cpp:37:
/usr/include/X11/X.h:96:13: note: candidates are: typedef XID Window
 typedef XID Window;
             ^
In file included from /usr/include/zbar.h:1308:0,
                 from ScrQr.cpp:15:
/usr/include/zbar/Window.h:40:7: note:                 class zbar::Window
 class Window {
       ^
ScrQr.cpp:187:27: error: reference to ‘Window’ is ambiguous
 char *winame (Display *d, Window win)  
                           ^
In file included from /usr/include/X11/Xlib.h:44:0,
                 from /usr/include/X11/Xutil.h:53,
                 from ScrQr.cpp:37:
/usr/include/X11/X.h:96:13: note: candidates are: typedef XID Window
 typedef XID Window;
             ^
In file included from /usr/include/zbar.h:1308:0,
                 from ScrQr.cpp:15:
/usr/include/zbar/Window.h:40:7: note:                 class zbar::Window
 class Window {
       ^
ScrQr.cpp:187:27: error: ‘Window’ has not been declared
 char *winame (Display *d, Window win)  
                           ^
ScrQr.cpp: In function ‘int main(int, char**)’:
ScrQr.cpp:221:2: error: reference to ‘Window’ is ambiguous
  Window root;  // X Root object
  ^
In file included from /usr/include/X11/Xlib.h:44:0,
                 from /usr/include/X11/Xutil.h:53,
                 from ScrQr.cpp:37:
/usr/include/X11/X.h:96:13: note: candidates are: typedef XID Window
 typedef XID Window;
             ^
In file included from /usr/include/zbar.h:1308:0,
                 from ScrQr.cpp:15:
/usr/include/zbar/Window.h:40:7: note:                 class zbar::Window
 class Window {
       ^
ScrQr.cpp:232:2: error: reference to ‘Window’ is ambiguous
  Window *list;    // Window type list (holds the Window IDs of active windows)
  ^
In file included from /usr/include/X11/Xlib.h:44:0,
                 from /usr/include/X11/Xutil.h:53,
                 from ScrQr.cpp:37:
/usr/include/X11/X.h:96:13: note: candidates are: typedef XID Window
 typedef XID Window;
             ^
In file included from /usr/include/zbar.h:1308:0,
                 from ScrQr.cpp:15:
/usr/include/zbar/Window.h:40:7: note:                 class zbar::Window
 class Window {
       ^
ScrQr.cpp:232:14: error: missing template arguments before ‘;’ token
  Window *list;    // Window type list (holds the Window IDs of active windows)
              ^
ScrQr.cpp:235:7: error: missing template arguments before ‘=’ token
  list = (Window*)winlist(d,&len);  // Getting the list   // GOTO winlist()
       ^
ScrQr.cpp:235:10: error: reference to ‘Window’ is ambiguous
  list = (Window*)winlist(d,&len);  // Getting the list   // GOTO winlist()
          ^
In file included from /usr/include/X11/Xlib.h:44:0,
                 from /usr/include/X11/Xutil.h:53,
                 from ScrQr.cpp:37:
/usr/include/X11/X.h:96:13: note: candidates are: typedef XID Window
 typedef XID Window;
             ^
In file included from /usr/include/zbar.h:1308:0,
                 from ScrQr.cpp:15:
/usr/include/zbar/Window.h:40:7: note:                 class zbar::Window
 class Window {
       ^
ScrQr.cpp:235:17: error: expected primary-expression before ‘)’ token
  list = (Window*)winlist(d,&len);  // Getting the list   // GOTO winlist()
                 ^
ScrQr.cpp:243:29: error: missing template arguments before ‘[’ token
         name = winame(d,list[i]);  // getting name    // GOTO winame()
                             ^
ScrQr.cpp:255:2: error: reference to ‘Window’ is ambiguous
  Window focal = list[choice];
  ^
In file included from /usr/include/X11/Xlib.h:44:0,
                 from /usr/include/X11/Xutil.h:53,
                 from ScrQr.cpp:37:
/usr/include/X11/X.h:96:13: note: candidates are: typedef XID Window
 typedef XID Window;
             ^
In file included from /usr/include/zbar.h:1308:0,
                 from ScrQr.cpp:15:
/usr/include/zbar/Window.h:40:7: note:                 class zbar::Window
 class Window {
       ^
ScrQr.cpp:259:29: error: ‘focal’ was not declared in this scope
     XGetWindowAttributes(d, focal, &gwa); 
                             ^
Bms bharadwaj
  • 483
  • 5
  • 18
  • Please show a minimal example of the code that causes the error. Also, please do not post pictures of code or error messages - they are hard to search/run! – Mark Setchell Jan 31 '19 at 17:51
  • @MarkSetchell Ooops, sorry for that. I have edited the code a bit now ... – Bms bharadwaj Feb 01 '19 at 04:59
  • Sorry again. Edited further : ) – Bms bharadwaj Feb 01 '19 at 05:57
  • 1
    Of course it's possible. They use namespaces correctly to protect you from naming conflicts. By issuing `using namespace` you are saying "I don't need your stinky protection, I know I don't have conflicts". Well guess what, that's not true. NEVER EVER use `using namespace`. Not std, not zbar, not any other. That's all. – n. m. could be an AI Feb 01 '19 at 07:24
  • 1
    In concrete terms, remove the lines like `using namespace cv;` and everywhere you use a `Mat` or anything from OpenCV, explicitly use `cv:: Mat` instead. Likewise for `using namespace zbar;` and `std`. – Mark Setchell Feb 01 '19 at 08:00
  • @n.m. and @Mark Setchell. A big big thanks for the hint. Truly saved my day. And yes this was a problem with the `namespace` declaration. Removing the `using namepsace ...` part and prefixing corresponding keywords with `zbar::` and `cv::` solved the issue. Thanks again!! – Bms bharadwaj Feb 01 '19 at 08:26

0 Answers0