QPainter 仅在 QImage 上绘制矩形的一部分

Posted

技术标签:

【中文标题】QPainter 仅在 QImage 上绘制矩形的一部分【英文标题】:QPainter paints only part of the rectangle over QImage 【发布时间】:2020-08-17 15:23:46 【问题描述】:

我正在将图像从内存中的数据加载到 QImage 中,我已经成功地使用 QPainter 将它绘制到 QWidget 上。然后我尝试更改此 QImage 的一些像素以使用橡皮筋突出显示矩形区域。我的问题是我只得到了矩形的一部分,有时什么都没有(见下图)。 Code .h:

class PaintWidget : public QWidget

    Q_OBJECT
public:
    using QWidget::QWidget;

    void setSourceSample(Sample src) ;
    void drawRectangle(OCRRectangle rect);
protected:
    void paintEvent(QPaintEvent *event) override;
    void mousePressEvent(QMouseEvent *ev) override;
    void mouseMoveEvent(QMouseEvent *ev) override;
    void mouseReleaseEvent(QMouseEvent *ev) override;

private:
    QRectF target=QRectF(0, 0, 1000, 1000);
    QImage p_source;
    QPoint origin, end;
    QRubberBand * rubberBand;
    QPair<float, float> rsz_ratio;
    void calcROI();
    QPoint translateCoordinates(cv::Point point);
;

代码.cpp:

void PaintWidget::paintEvent(QPaintEvent *event) 
    QPainter p(this);
    p.drawImage(target, p_source);

void PaintWidget::mousePressEvent(QMouseEvent *ev) 
    origin=ev->pos();
    rubberBand=new QRubberBand(QRubberBand::Rectangle, this);
    rubberBand->setGeometry(QRect(origin, QSize()));
    rubberBand->show();

void PaintWidget::mouseMoveEvent(QMouseEvent *ev) 
    rubberBand->setGeometry(QRect(origin, ev->pos()).normalized());

void PaintWidget::mouseReleaseEvent(QMouseEvent *ev) 
    end=ev->pos();
    rubberBand->hide();
    delete rubberBand;
    calcROI();

void PaintWidget::calcROI() 
    int p1x=min(end.x(),origin.x())*rsz_ratio.first;
    int p2x=max(end.x(),origin.x())*rsz_ratio.first;
    int p1y=min(end.y(), origin.y())*rsz_ratio.second;
    int p2y=max(end.y(), origin.y())*rsz_ratio.second;
    drawRectangle(OCRRectangle(cv::Point(p1x, p1y),cv::Point(p2x, p2y)));

void PaintWidget::setSourceSample(Sample src) 
    QImage inter=src.toQImage();
    p_source=inter.convertToFormat(QImage::Format::Format_RGB32);
    rsz_ratio.first=(float)src.size().width/(float)(target.width());
    rsz_ratio.second=(float)src.size().height/(float)target.height();

QPoint PaintWidget::translateCoordinates(cv::Point point) 
    QPoint qtpoint;
    qtpoint.setX(point.x);
    qtpoint.setY(point.y);
    return qtpoint;

void PaintWidget::drawRectangle(OCRRectangle rect) 
    QPoint p1(translateCoordinates(rect.p1)), p2(translateCoordinates(rect.p2));
    for (int i=p1.x(); i<=p2.x(); i++) 
       p_source.setPixelColor(i,p1.y(),QColor(255,0,0));
       p_source.setPixelColor(i, p2.y(), QColor(255,0,0));
    
    for (int i=p1.y(); i<=p2.y(); i++) 
       p_source.setPixelColor(p1.x(),i,QColor(255,0,0));
       p_source.setPixelColor(p2.x(),i,QColor(255,0,0));
    

更新:问题似乎在于原始图像的重新缩放。当我绘制填充的红色矩形时,它绝对没问题,我的猜测是重新缩放 1px 边框矩形只是擦除边框。但是设置更厚的边框(最多 5 个像素)并没有为我提供解决方案。

【问题讨论】:

什么是OCRRectangle类? 是自定义类,基本上就是两个openCV点。 为什么要画到QImage?您可以改为在paintEvent() 中绘制矩形。然后你总是得到最好的质量。如果您愿意,也可以先将 QPainters 坐标系转换为像素坐标。使用大小为 0 的笔始终绘制细线(屏幕坐标中为 1px),这也非常方便。 这是因为需要在从内存加载的图像上绘制矩形。 @ypnos ,谢谢,我找到了一种在图像上绘制矩形的方法,它比更改像素要好得多。 【参考方案1】:

加粗边框解决了这个问题。

【讨论】:

以上是关于QPainter 仅在 QImage 上绘制矩形的一部分的主要内容,如果未能解决你的问题,请参考以下文章

从一个实例来看QMutex的使用

Qt 5.10 中的 QPainter::drawImage() 故障

使用 QPainter 在 QWidget 上绘制 QPixmap Rects

如何使用 Qpainter 在 Qt 中绘制棋盘

QT源码拾贝0-5(qimage和qpainter)

QT源码拾贝0-5(qimage和qpainter)