Qt 结合 OpenCV 的 Mat 对象绘制矩形区域,拖到矩形区域可用于 ROI 区域的截取

文章详细描述了如何在Qt中创建TB_DrawRectangle类,实现在QLabel上基于GRectangle参数和OpenCVMat对象进行图像的矩形绘制,以及GRectangle类的拖动和尺寸调整功能。
摘要由CSDN通过智能技术生成

TB_DrawRectangle 表示绘制矩形类,在 QLabel 上实现绘制功能;GRectangle 表示矩形参数类; Mat 为 OpenCV 的图像类。

在这里插入图片描述

// ui->framePicture 表示显示区域;
// qScrollArea 实现图像的放大缩小显示
QScrollArea* qScrollArea=new QScrollArea(ui->framePicture);
QHBoxLayout* layout=new QHBoxLayout(ui->framePicture);
layout->addWidget(qScrollArea);
//qLabelView 表示图像的显示容器
QLabel* qLabelView=new QLabel(qScrollArea);
qLabelView->setScaledContents(true);
qLabelView->setBackgroundRole(QPalette::Background);
qLabelView->setFrameStyle(QFrame::StyledPanel);
qLabelView->setFrameShadow(QFrame::Sunken);
qLabelView->setGeometry(0, 0, qScrollArea->width(), qScrollArea->height());
qScrollArea->setWidget(qLabelView);
//制矩形的参数类
GRectangle rect; 
//Opencv 的图像类
Mat image; 
//qDrawView 表示矩形绘制的对象
TB_DrawRectangle* qDrawView=new TB_DrawRectangle(qLabelView, &rect, &image);
qDrawView->setParent(qLabelView);
qDrawView->setWindowFlags(Qt::WindowStaysOnTopHint);
qDrawView->setAttribute(Qt::WA_TranslucentBackground,true);
qDrawView->setStyleSheet("background-color:transparent");

GRectangle 类对象

GRectangle 类对象表示矩形的参数,里面包含了 P0、P1、P2 三个点的坐标参数,拖到 P0 可实现整个矩形的移动;拖到 P1、P2 可实现矩形的长宽大小变化。

#define MOUSE_LENGTH_LEN 10
#define MOUSE_RADIU_LEN  5

// GRectangle 类对象
class GRectangle
{
public:
    GRectangle();
    ~GRectangle(){}
private:
    Point2f p0;
    Point2f p1;
    Point2f p2;
    void UpdataPoint2fApi();
public:
    void SetPosLimit(Size imageSize);
    void DragPointApi(QPointF point, Size imageSize, Size labelSize);
    void DrawApi(QPainter* painter, QColor color, Size imageSize, Size labelSize);
public:
    Point2f p1_;
    Point2f p2_;
};

// GRectangle 类对象初始化
GRectangle::GRectangle()
{
    p1_=Point2f(100, 100);
    p2_=Point2f(300, 300);
    p1=p1_;
    p2=p2_;
}

//更新点状态
void GRectangle::UpdataPoint2fApi()
{
    p0=Point2f((p1.x + p2.x)/2, (p1.y + p2.y)/2);
}

//设置限制
void GRectangle::SetPosLimit(Size imageSize)
{
    int w=imageSize.width;
    int h=imageSize.height;
    if(w==0 || h==0)
        return;
    p1.x = p1.x<0 ? 0 : (p1.x>=w ? w-1 : p1.x);
    p2.x = p2.x<0 ? 0 : (p2.x>=w ? w-1 : p2.x);
    p1.y = p1.y<0 ? 0 : (p1.y>=h ? h-1 : p1.y);
    p2.y = p2.y<0 ? 0 : (p2.y>=h ? h-1 : p2.y);
    if(p1.x==p2.x && p1.y==p2.y && (p1.x==0 || p1.x==w-1) && (p1.y==0 || p1.y==h-1))
    {
        p1=Point2f(w/2-10, h/2);
        p2=Point2f(w/2+10, h/2);
    }
}

//点距离
float cvPointDistance(Point2f p1, Point2f p2)
{
    return sqrt(pow(p2.x-p1.x, 2) + pow(p2.y-p1.y, 2));
}

// 拖动点位置, sX表示图像宽度/控件宽度, sY表示图像高度/控件高度
void GRectangle::DragPointApi(QPointF point, Size imageSize, Size labelSize)
{
    float sX=(float)imageSize.width/labelSize.width;
    float sY=(float)imageSize.height/labelSize.height;
    float sZ=(sX + sY)/2;
    Point2f p(point.x()*sX, point.y()*sY);
    vector<Point2f> sorts;
    sorts.push_back(p0);
    sorts.push_back(p1);
    sorts.push_back(p2);
    float length=10e9;
    int   index=-1;
    for(size_t i=0;i<sorts.size();i++)
    {
        float l=cvPointDistance(p, sorts[i]);
        if(l<=length)
        {
            length=l;
            index=(int)i;
        }
    }
    if(length<=(MOUSE_LENGTH_LEN*sZ))
    {
        switch(index)
        {
        //P0
        case 0:
        {
            int x=p.x-p0.x;
            int y=p.y-p0.y;
            p1=Point2f(p1.x + x, p1.y + y);
            p2=Point2f(p2.x + x, p2.y + y);
            break;
        }
        //P1
        case 1:
        {
            if(!(p.x<p2.x && p.y<p2.y))
                return;
            p1=Point2f(p.x, p.y);
            break;
        }
        //P2
        case 2:
        {
            if(!(p.x>p1.x && p.y>p1.y))
                return;
            p2=Point2f(p.x, p.y);
            break;
        }
        default:
            break;
        }
    }
    //限制位置尺寸大小
    this->SetPosLimit(imageSize);
}

//绘图
void GRectangle::DrawApi(QPainter* painter, QColor color, Size imageSize, Size labelSize)
{
    if(!(labelSize.width>0 && imageSize.width>0))
        return;
    float sX=(float)imageSize.width/labelSize.width;
    float sY=(float)imageSize.height/labelSize.height;
    //更新位置点
    this->UpdataPoint2fApi();
    //实际点装换为灰度点
    QPointF P0(p0.x/sX, p0.y/sY);
    QPointF P1(p1.x/sX, p1.y/sY);
    QPointF P2(p2.x/sX, p2.y/sY);
    //初始化绘图工具
    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->setPen(color);
    QRectF rect1(P0.x()-MOUSE_RADIU_LEN, P0.y()-MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN);
    painter->drawEllipse(rect1);
    QRectF rect2(P1.x()-MOUSE_RADIU_LEN, P1.y()-MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN);
    painter->drawEllipse(rect2);
    QRectF rect3(P2.x()-MOUSE_RADIU_LEN, P2.y()-MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN, 2*MOUSE_RADIU_LEN);
    painter->drawEllipse(rect3);
    QPoint l2=QPoint(P2.x(), P1.y());
    QPoint l4=QPoint(P1.x(), P2.y());
    painter->drawLine(P1, l2);
    painter->drawLine(l2, P2);
    painter->drawLine(P2, l4);
    painter->drawLine(l4, P1);
}

TB_DrawRectangle 类实现拖到、绘制等功能

class TB_DrawRectangle : public QWidget
{
    Q_OBJECT
public:
    explicit TB_DrawRectangle(QWidget *parent, GRectangle *rect, Mat *image);
    void mouseMoveEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);
    void paintEvent(QPaintEvent *event);
    ~TB_DrawRectangle(){}
public:
    GRectangle* graphic;  
    Mat* imageSize;
    QColor color;
};

//初始化
TB_DrawRectangle::TB_DrawRectangle(QWidget *parent, GRectangle *rect, Mat *image) :
    QWidget(parent), graphic(rect), imageSize(image), color(Qt::red)
{}

//鼠标移动事件
void TB_DrawRectangle::mouseMoveEvent(QMouseEvent *e)
{
    if(!(e->buttons() & Qt::LeftButton))
        return;
    int x=e->x();
    int y=e->y();
    if(x<0 || y<0 || x>this->width() || y>this->height())
        return;
    if(!(graphic && imageSize))
        return;
    graphic->DragPointApi(QPointF(x, y), Size(imageSize->cols, imageSize->rows), Size(this->width(), this->height()));
}

//鼠标释放事件
void TB_DrawRectangle::mouseReleaseEvent(QMouseEvent *e)
{
    e->accept();
}

//鼠标绘制事件
void TB_DrawRectangle::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    if(!(graphic && imageSize))
        return;
    graphic->DrawApi(&painter, color, Size(imageSize->cols, imageSize->rows), Size(this->width(), this->height()));
    this->update();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刚出道的菜鸟@丢丢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值