将图像放入 x11 中的 Window
Putting image into a Window in x11
我有一个.JPG 格式的二维码。我使用 OpenCV 3.4.4 加载它。现在,我使用 XCreateSimpleWindow() 创建了一个新的 X11 window。然后,我会将 QR 图像调整为这个新 window 的大小。
接下来,我想将这个调整大小的二维码放入window。我尝试使用 XPutImage(),但没有成功,可能是因为我不知道用法。
为了使用 XPutImage(),我首先使用 XGetImage() 拍摄了 X11 window 的图像;然后获取QR图像的像素值,然后将其赋值给通过XGetImage获取的图像的像素值。
获得此 XImage 后,我尝试使用 XPutImage 将其放入 window。但是,它仍然显示黑色 window。
终端没有错误,但结果不尽如人意
这个问题有什么解决办法吗?例如,如何更改 window (X11) w.r.t 示例图像的背景,并使用 XPutImage()?
代码是这样的...
// Written by Ch. Tronche (http://tronche.lri.fr:8000/)
// Copyright by the author. This is unmaintained, no-warranty free software.
// Please use freely. It is appreciated (but by no means mandatory) to
// acknowledge the author's contribution. Thank you.
// Started on Thu Jun 26 23:29:03 1997
//
// Xlib tutorial: 2nd program
// Make a window appear on the screen and draw a line inside.
// If you don't understand this program, go to
// http://tronche.lri.fr:8000/gui/x/xlib-tutorial/2nd-program-anatomy.html
//
// compilation:
// g++ -o go qrinX11.cpp `pkg-config --cflags --libs opencv` -lX11
//
#include <opencv2/opencv.hpp>
#include "opencv2/opencv.hpp" // FOR OpenCV
#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <bits/stdc++.h>
#include <X11/Xlib.h> // Every Xlib program must include this
#include <assert.h> // I include this to test return values the lazy way
#include <unistd.h> // So we got the profile for 10 seconds
#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>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#define NIL (0) // A name for the void pointer
using namespace cv;
using namespace std;
int main()
{
XGCValues gr_values;
//GC gc;
XColor color, dummy;
Display *dpy = XOpenDisplay(NIL);
//assert(dpy);
//int screen = DefaultScreen(dpy);
// Get some colors
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
// Create the window
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, whiteColor, blackColor);
// We want to get MapNotify events
XSelectInput(dpy, w, StructureNotifyMask);
XMapWindow(dpy, w);
// Wait for the MapNotify event
for(;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify)
break;
}
Window focal = w;
XWindowAttributes gwa;
XGetWindowAttributes(dpy, w, &gwa);
int wd1 = gwa.width;
int ht1 = gwa.height;
XImage *image = XGetImage(dpy, w, 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
Mat scrap = imread("qr.jpg");//(wid, ht, CV_8UC3);
resize(scrap, img, img.size(), CV_INTER_AREA);
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;
pixel = color[0];//&color[1]&color[2];
}
namedWindow("QR", CV_WINDOW_NORMAL);
imshow("QR", img);
cout << "herererere\n";
GC gc = XCreateGC(dpy, w, 0, NIL);
XPutImage(dpy, w, gc, image, 0, 0, wd1, ht1, wd1, ht1);
waitKey(0);
//sleep(3);
return 0;
}
好的,我自己解决了。更改像素值并将其更新为实际图像然后将其放入 window 的背景时出现了一个愚蠢的错误。
先用XPutPixel()
,再用XPutImage()
这是最终正确的方法:
// compilation:
// g++ -o go qrinX11.cpp `pkg-config --cflags --libs opencv` -lX11
//
#include <opencv2/opencv.hpp>
#include "opencv2/opencv.hpp" // FOR OpenCV
#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <bits/stdc++.h>
#include <X11/Xlib.h> // Every Xlib program must include this
#include <assert.h> // I include this to test return values the lazy way
#include <unistd.h> // So we got the profile for 10 seconds
#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>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#define NIL (0) // A name for the void pointer
using namespace cv;
using namespace std;
int main()
{
XGCValues gr_values;
//GC gc;
XColor color, dummy;
Display *dpy = XOpenDisplay(NIL);
//assert(dpy);
//int screen = DefaultScreen(dpy);
// Get some colors
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
// Create the window
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, whiteColor, blackColor);
// We want to get MapNotify events
XSelectInput(dpy, w, StructureNotifyMask);
XMapWindow(dpy, w);
// Wait for the MapNotify event
for(;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify)
break;
}
Window focal = w;
XWindowAttributes gwa;
XGetWindowAttributes(dpy, w, &gwa);
int wd1 = gwa.width;
int ht1 = gwa.height;
XImage *image = XGetImage(dpy, w, 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
Mat scrap = imread("qr.jpg");//(wid, ht, CV_8UC3);
resize(scrap, img, img.size(), CV_INTER_AREA);
for (int x = 0; x < wd1; x++)
for (int y = 0; y < ht1 ; y++)
{
unsigned long pixel = XGetPixel(image,x,y);
Vec3b color = img.at<Vec3b>(Point(x,y));
pixel = 65536 * color[2] + 256 * color[1] + color[0];
XPutPixel(image, x, y, pixel);
}
namedWindow("QR", CV_WINDOW_NORMAL);
imshow("QR", img);
GC gc = XCreateGC(dpy, w, 0, NIL);
XPutImage(dpy, w, gc, image, 0, 0, 0, 0, wd1, ht1);
waitKey(0);
return 0;
}
简单是关键,可以提高性能(在本例中):
//..
// Mat img(ht1, wd1, CV_8UC3); // OpenCV Mat object is initilaized
cv::Mat img(ht1, wd1, CV_8UC4, image->data); // initilaize with existing mem
Mat scrap = imread("qr.jpg");//(wid, ht, CV_8UC3);
cv::cvtColor(scrap,scrap,cv::COLOR_BGR2BGRA);
resize(scrap, img, img.size(), cv::INTER_AREA);
// .. and we can skip the for loops
namedWindow("QR", CV_WINDOW_NORMAL);
imshow("QR", img);
// .. etc
我有一个.JPG 格式的二维码。我使用 OpenCV 3.4.4 加载它。现在,我使用 XCreateSimpleWindow() 创建了一个新的 X11 window。然后,我会将 QR 图像调整为这个新 window 的大小。
接下来,我想将这个调整大小的二维码放入window。我尝试使用 XPutImage(),但没有成功,可能是因为我不知道用法。
为了使用 XPutImage(),我首先使用 XGetImage() 拍摄了 X11 window 的图像;然后获取QR图像的像素值,然后将其赋值给通过XGetImage获取的图像的像素值。
获得此 XImage 后,我尝试使用 XPutImage 将其放入 window。但是,它仍然显示黑色 window。 终端没有错误,但结果不尽如人意
这个问题有什么解决办法吗?例如,如何更改 window (X11) w.r.t 示例图像的背景,并使用 XPutImage()?
代码是这样的...
// Written by Ch. Tronche (http://tronche.lri.fr:8000/)
// Copyright by the author. This is unmaintained, no-warranty free software.
// Please use freely. It is appreciated (but by no means mandatory) to
// acknowledge the author's contribution. Thank you.
// Started on Thu Jun 26 23:29:03 1997
//
// Xlib tutorial: 2nd program
// Make a window appear on the screen and draw a line inside.
// If you don't understand this program, go to
// http://tronche.lri.fr:8000/gui/x/xlib-tutorial/2nd-program-anatomy.html
//
// compilation:
// g++ -o go qrinX11.cpp `pkg-config --cflags --libs opencv` -lX11
//
#include <opencv2/opencv.hpp>
#include "opencv2/opencv.hpp" // FOR OpenCV
#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <bits/stdc++.h>
#include <X11/Xlib.h> // Every Xlib program must include this
#include <assert.h> // I include this to test return values the lazy way
#include <unistd.h> // So we got the profile for 10 seconds
#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>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#define NIL (0) // A name for the void pointer
using namespace cv;
using namespace std;
int main()
{
XGCValues gr_values;
//GC gc;
XColor color, dummy;
Display *dpy = XOpenDisplay(NIL);
//assert(dpy);
//int screen = DefaultScreen(dpy);
// Get some colors
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
// Create the window
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, whiteColor, blackColor);
// We want to get MapNotify events
XSelectInput(dpy, w, StructureNotifyMask);
XMapWindow(dpy, w);
// Wait for the MapNotify event
for(;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify)
break;
}
Window focal = w;
XWindowAttributes gwa;
XGetWindowAttributes(dpy, w, &gwa);
int wd1 = gwa.width;
int ht1 = gwa.height;
XImage *image = XGetImage(dpy, w, 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
Mat scrap = imread("qr.jpg");//(wid, ht, CV_8UC3);
resize(scrap, img, img.size(), CV_INTER_AREA);
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;
pixel = color[0];//&color[1]&color[2];
}
namedWindow("QR", CV_WINDOW_NORMAL);
imshow("QR", img);
cout << "herererere\n";
GC gc = XCreateGC(dpy, w, 0, NIL);
XPutImage(dpy, w, gc, image, 0, 0, wd1, ht1, wd1, ht1);
waitKey(0);
//sleep(3);
return 0;
}
好的,我自己解决了。更改像素值并将其更新为实际图像然后将其放入 window 的背景时出现了一个愚蠢的错误。
先用XPutPixel()
,再用XPutImage()
这是最终正确的方法:
// compilation:
// g++ -o go qrinX11.cpp `pkg-config --cflags --libs opencv` -lX11
//
#include <opencv2/opencv.hpp>
#include "opencv2/opencv.hpp" // FOR OpenCV
#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <bits/stdc++.h>
#include <X11/Xlib.h> // Every Xlib program must include this
#include <assert.h> // I include this to test return values the lazy way
#include <unistd.h> // So we got the profile for 10 seconds
#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>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#define NIL (0) // A name for the void pointer
using namespace cv;
using namespace std;
int main()
{
XGCValues gr_values;
//GC gc;
XColor color, dummy;
Display *dpy = XOpenDisplay(NIL);
//assert(dpy);
//int screen = DefaultScreen(dpy);
// Get some colors
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
// Create the window
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, whiteColor, blackColor);
// We want to get MapNotify events
XSelectInput(dpy, w, StructureNotifyMask);
XMapWindow(dpy, w);
// Wait for the MapNotify event
for(;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify)
break;
}
Window focal = w;
XWindowAttributes gwa;
XGetWindowAttributes(dpy, w, &gwa);
int wd1 = gwa.width;
int ht1 = gwa.height;
XImage *image = XGetImage(dpy, w, 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
Mat scrap = imread("qr.jpg");//(wid, ht, CV_8UC3);
resize(scrap, img, img.size(), CV_INTER_AREA);
for (int x = 0; x < wd1; x++)
for (int y = 0; y < ht1 ; y++)
{
unsigned long pixel = XGetPixel(image,x,y);
Vec3b color = img.at<Vec3b>(Point(x,y));
pixel = 65536 * color[2] + 256 * color[1] + color[0];
XPutPixel(image, x, y, pixel);
}
namedWindow("QR", CV_WINDOW_NORMAL);
imshow("QR", img);
GC gc = XCreateGC(dpy, w, 0, NIL);
XPutImage(dpy, w, gc, image, 0, 0, 0, 0, wd1, ht1);
waitKey(0);
return 0;
}
简单是关键,可以提高性能(在本例中):
//..
// Mat img(ht1, wd1, CV_8UC3); // OpenCV Mat object is initilaized
cv::Mat img(ht1, wd1, CV_8UC4, image->data); // initilaize with existing mem
Mat scrap = imread("qr.jpg");//(wid, ht, CV_8UC3);
cv::cvtColor(scrap,scrap,cv::COLOR_BGR2BGRA);
resize(scrap, img, img.size(), cv::INTER_AREA);
// .. and we can skip the for loops
namedWindow("QR", CV_WINDOW_NORMAL);
imshow("QR", img);
// .. etc