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);
^