Qt快速绘制像素点的处理方法

在有些情况下,我们需要对屏幕上的像素点进行大量的绘制操作。比如我之前模拟写的一个渲染管线开源练习,涉及到了大量的像素点操作。而Qt本身的QPen和QPainter::drawPoint的API如果操作大量的像素点,会非常耗时,因此我Google了这个方式:

原文链接:https://www.vikingsoftware.com/qwidget-pixel-drawing-2/

以下是核心代码:

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QTime>
#include <QDebug>
const int loop = 25;
const int windowWidth = 400;
const int windowHeight = 300;
class PainterWindow : public QWidget {
    void paintEvent(QPaintEvent*) {
        QTime time;
        time.start();
        for (int i = 0; i < ::loop; ++i) {
            QPainter painter(this);
            for (int x = 0; x < width(); ++x) {
                for (int y = 0; y < height(); ++y) {
                    const QColor color(static_cast<QRgb>(i+x+y));
                    painter.setPen(color);
                    painter.drawPoint(x, y);
                }
            }
        }
        qDebug() << "drawPoint time:" << time.elapsed();
        close();
    }
};
 
class ImageWindow : public QWidget {
    void paintEvent(QPaintEvent*) {
        QRgb* pixels = new QRgb[width()*height()];
        QTime time;
        time.start();
        for (int i = 0; i < ::loop; ++i) {
            QPainter painter(this);
            QImage image((uchar*)pixels, width(), height(), QImage::Format_ARGB32);
            for (int x = 0; x < width(); ++x) {
                for (int y = 0; y < height(); ++y) {
                    pixels[x + y * height()] = static_cast<QRgb>(i+x+y);
                }
            }
            painter.drawImage(0, 0, image);
        }
        qDebug() << "drawImage time:" << time.elapsed();
        close();
        delete[] pixels;
    }
};
 
int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    PainterWindow w;
    w.resize(::windowWidth, ::windowHeight);
    w.show();
 
    a.exec();
 
    ImageWindow imageWindow;
    imageWindow.resize(::windowWidth, ::windowHeight);
    imageWindow.show();
 
    a.exec();
}

在使用 Qt 和 OpenCV 进行图像像素处理时,可以在图像上绘制十字线以辅助定位或分析特定像素点。具体实现方法如下: 首先,通过 OpenCV 的 `cv::Mat` 类型加载或捕获图像数据。接着,可以使用 OpenCV 的绘图函数 `cv::line` 在指定位置绘制水平和垂直的线条,形成十字线[^1]。绘制完成后,将图像数据更新到 Qt 的显示组件中,例如 `QLabel`,以便在界面上实时显示。 以下是一个绘制十字线的代码示例: ```cpp #include <opencv2/opencv.hpp> #include <QPixmap> #include <QLabel> // 假设已经加载了一张图像到 cv::Mat 中 cv::Mat image = cv::imread("path/to/image.png"); // 定义十字线的位置(例如图像中心) int cross_x = image.cols / 2; int cross_y = image.rows / 2; // 绘制垂直线 cv::line(image, cv::Point(cross_x, 0), cv::Point(cross_x, image.rows), cv::Scalar(0, 0, 255), 1); // 红色线 // 绘制水平线 cv::line(image, cv::Point(0, cross_y), cv::Point(image.cols, cross_y), cv::Scalar(0, 0, 255), 1); // 红色线 // 将图像转换为 QPixmap 并显示在 QLabel 上 QPixmap pixmap = QPixmap::fromImage(QImage(image.data, image.cols, image.rows, image.step, QImage::Format_BGR888)); ui->label_image->setPixmap(pixmap.scaled(ui->label_image->size(), Qt::KeepAspectRatio)); ``` 在上述代码中,`cv::line` 函数用于绘制线条,其中参数包括起始点、结束点、颜色和线宽。颜色参数使用 `cv::Scalar` 定义 BGR 值,例如 `(0, 0, 255)` 表示红色。绘制完成后,使用 `QPixmap::fromImage` 将 `cv::Mat` 转换为 `QImage`,然后通过 `QLabel` 显示图像[^1]。 如果需要根据用户交互动态绘制十字线(例如鼠标点击位置),可以在 Qt 的事件处理函数中获取鼠标坐标,并在对应位置绘制十字线。以下是一个简单的鼠标事件处理示例: ```cpp void ImageViewer::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { cross_x = event->x(); // 获取鼠标点击的 x 坐标 cross_y = event->y(); // 获取鼠标点击的 y 坐标 // 清除之前的十字线(重新加载原始图像) image = cv::imread("path/to/image.png"); // 绘制新的十字线 cv::line(image, cv::Point(cross_x, 0), cv::Point(cross_x, image.rows), cv::Scalar(0, 0, 255), 1); cv::line(image, cv::Point(0, cross_y), cv::Point(image.cols, cross_y), cv::Scalar(0, 0, 255), 1); // 更新界面显示 QPixmap pixmap = QPixmap::fromImage(QImage(image.data, image.cols, image.rows, image.step, QImage::Format_BGR888)); ui->label_image->setPixmap(pixmap.scaled(ui->label_image->size(), Qt::KeepAspectRatio)); } } ``` 在上述交互示例中,每次点击鼠标左键时,程序会清除之前的十字线(通过重新加载原始图像),并在新的坐标位置绘制十字线,实现动态的像素处理与定位功能[^1]。 ### 图像像素处理 除了绘制十字线,还可以对图像进行像素级别的处理。例如,读取和修改特定像素的颜色值: ```cpp // 获取指定位置的像素值 cv::Vec3b pixel = image.at<cv::Vec3b>(cross_y, cross_x); // 输出像素值(B, G, R) qDebug() << "Pixel value at (" << cross_x << ", " << cross_y << "): " << pixel[0] << ", " << pixel[1] << ", " << pixel[2]; // 修改像素值(例如设置为白色) image.at<cv::Vec3b>(cross_y, cross_x) = cv::Vec3b(255, 255, 255); ``` 上述代码展示了如何读取和修改图像中特定像素的颜色值。`cv::Vec3b` 表示三通道的 8 位无符号整数,分别对应 B、G、R 三个颜色通道。通过这种方式,可以实现更复杂的图像处理功能,例如边缘检测、滤波或颜色转换。 ### 总结 通过 Qt 和 OpenCV 的结合,可以灵活地实现图像像素处理与十字线绘制功能。利用 OpenCV 提供的绘图函数和像素操作方法,结合 Qt 的图形界面交互能力,可以开发出功能丰富的图像处理应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值