首页 > 解决方案 > 如何使用 opencv 和 Qt 对桌面的一部分进行拍照

问题描述

在此先感谢您的帮助。所以下面我正在尝试创建一个截图工具。我使用 Qt 创建了一个小部件并使其几乎透明。用户使用鼠标创建一个他们想要复制的正方形区域。我可以让它复制一个部分,而不是写入部分。我使用 getcursor 函数来获取用户光标位置a 以及正方形的终点和起点。我将我的小部件设置为我的屏幕大小,然后使用我的 void 函数拍摄整个桌面的照片(使用我的小部件窗口的大小作为我的图像大小)。然而,屏幕和图像的 x,y 值不会“重叠”,而不是获取用户绘制的正方形中的内容,而是获取屏幕上的其他正方形。有没有什么办法解决这一问题?

Frame_Record::Frame_Record(QWidget* parent) : QWidget(parent)
{
    //this->setStyleSheet("background-color:rgba(0,0,0,0)");

    this->setWindowState(Qt::WindowFullScreen);
    this->setWindowOpacity(0.1);
    this->setStyleSheet("QWidget{background:#000000}");
    x_size = this->size().width();
    y_size = this->size().height();
    //cv::waitKey(0);
    //setAttribute(Qt::WA_TranslucentBackground);

    /*setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
    setAttribute(Qt::WA_NoSystemBackground);
    setAttribute(Qt::WA_TranslucentBackground);
    //setAttribute(Qt::WA_PaintOnScreen);
    //setAttribute(Qt::transparent);
    setAttribute(Qt::WA_MouseNoMask,true);
    setAttribute(Qt::WA_MouseTracking,true);*/
}

void Frame_Record::mousePressEvent(QMouseEvent* events)
{
    POINT start;
    GetCursorPos(&start);
    qDebug() << "Mouse pressed PRessed";
    x_start = start.x;
    y_start = start.y;
}

void Frame_Record::mouseReleaseEvent(QMouseEvent* events)
{
    qDebug() << "Mouse unpressed";
    qDebug() << x_start;
    qDebug() << y_start;
    qDebug() << x_end;
    qDebug() << y_end;
    POINT end;
    GetCursorPos(&end);

    x_end = end.x;
    y_end = end.y;
    get_Image(y_size, x_size); //y then x   
    this->close();
}

void Frame_Record::mouseMoveEvent(QMouseEvent* events)
{
    POINT end;
    GetCursorPos(&end);

    x_end = end.x;
    y_end = end.y;
    qDebug() << "mouse is moving";
}

void Frame_Record::get_Image(int screen_w, int screen_h)
{
    HBITMAP bitmap;
    cv::Mat pic;

    HDC hdcSys = GetDC(NULL);
    HDC hdcMem = CreateCompatibleDC(hdcSys);

    void* ptrBitmapPixels;

    BITMAPINFO bInfo;
    HDC hdc{};
    ZeroMemory(&bInfo, sizeof(BITMAPINFO));
    bInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bInfo.bmiHeader.biWidth = screen_w;
    bInfo.bmiHeader.biHeight = -screen_h;
    bInfo.bmiHeader.biPlanes = 1;
    bInfo.bmiHeader.biBitCount = 32;

    bitmap = CreateDIBSection(hdc, &bInfo, DIB_RGB_COLORS, &ptrBitmapPixels, NULL, 0);
    SelectObject(hdcMem, bitmap);

    pic =cv::Mat(screen_h, screen_w, CV_8UC4, ptrBitmapPixels, 0);
    BitBlt(hdcMem, 0, 0, screen_w, screen_h, hdcSys, 0, 0, SRCCOPY);
    cv::Mat mod_pic(pic, cv::Range(x_start, x_end), cv::Range(y_start, y_end));

    // pic(cv::Rect(x_start, y_start, x_start - x_end, y_start - y_end));   
    // Mat matRef=matBitmap(Range(100,200), Range(100,200));
    //bitwise_not(matRef,matRef);

    cv::imshow("Title", mod_pic);
    cv::waitKey(0);
    cv::destroyAllWindows();
}

标签: c++qtopencv

解决方案


您可以在 Qt 中尝试以下代码来获取屏幕

QScreen *screen = // init screen first (application.primaryScreen();)
QRect rect = screen->geometry();
// instead you can also use your x and y coordinates
QPixmap pixmap = screen->grabWindow(0, rect .x(), rect .y(), rect .width(), rect .height());

然后你可以做你想做的事QPixmap


推荐阅读