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();
}