Hi all
Thanks for all the support and suggestions. I have a better solution and I am posting it here for your review. Please let me know if you find any other improvements that can be made.
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QWidget>
#include <QImage>
#include <QGraphicsSceneMouseEvent>
#include <QVBoxLayout>
#include <QGraphicsPixmapItem>
#include <QGraphicsRectItem>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
class OverlayRectangle : public QGraphicsItem
{
public:
enum { Type = UserType + 1026 };
OverlayRectangle(const QRectF &, cv::Mat &, QGraphicsItem *parent = 0);
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget) override;
int type() const override;
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
QRectF rectShape;
QSizeF dragDelta;
bool resizeShape;
cv::Mat & overlayImage;
};
class ImageViewer : public QWidget
{
Q_OBJECT
public:
explicit ImageViewer(QWidget *parent = nullptr);
void setImage(const QString & fileName);
void addOverlay(QRectF rect);
private:
QGraphicsScene *imageScene;
QGraphicsView *imageView;
QGraphicsPixmapItem *imagePixmap;
cv::Mat cvImage;
};
#include "image_viewer.h"
#include "cvmatandqimage.h"
#include <QDebug>
OverlayRectangle::OverlayRectangle(const QRectF & cvRect,
cv::Mat & overlayImg,
QGraphicsItem *parent) :
QGraphicsItem(parent),
rectShape(cvRect),
overlayImage(overlayImg)
{
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
resizeShape = false;
}
QRectF OverlayRectangle::boundingRect() const
{
return rectShape;
}
void OverlayRectangle::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
try
{
QRectF rect0 = mapRectToScene(boundingRect());
cv::Rect2d cvRect0(rect0.x(), rect0.y(), rect0.width(), rect0.height());
cv::Mat croppedImage = overlayImage(cvRect0);
cv::cvtColor(croppedImage, croppedImage, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(croppedImage, croppedImage, cv::Size(51, 51), 51, 51);
QImage processedImage = QtOcv::mat2Image(croppedImage);
painter->drawImage(rectShape, processedImage);
}
catch (...)
{
return;
}
QPen blackPen(Qt::blue);
blackPen.setWidth(2);
painter->setPen(blackPen);
painter->drawRect(rectShape);
QRectF brRect(rectShape.x() + rectShape.width() - 20,
rectShape.y() + rectShape.height() - 20, 20, 20);
painter->drawRect(brRect);
}
int OverlayRectangle::type() const { return Type;}
void OverlayRectangle::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
auto currentPos0 = event->scenePos();
QPointF dragRectBR = mapToScene(boundingRect().bottomRight());
QRectF dragRect(dragRectBR.x() - 20, dragRectBR.y() - 20, 20, 20);
if(dragRect.contains(currentPos0))
{
dragDelta.setWidth(dragRectBR.x() - currentPos0.x());
dragDelta.setHeight(dragRectBR.y() - currentPos0.y());
resizeShape = true;
}
QGraphicsItem::mousePressEvent(event);
}
void OverlayRectangle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
auto currentPos0 = event->scenePos();
auto sceneRectTL0 = mapToScene(boundingRect().topLeft());
if(resizeShape == true)
{
auto newWidth = currentPos0.x() - sceneRectTL0.x() + dragDelta.height();
auto newHeight = currentPos0.y() - sceneRectTL0.y() + dragDelta.height();
if( newWidth > 50 && newHeight > 50 )
{
prepareGeometryChange();
rectShape.setWidth(newWidth);
rectShape.setHeight(newHeight);
update();
}
return;
}
QGraphicsItem::mouseMoveEvent(event);
}
void OverlayRectangle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
resizeShape = false;
QGraphicsItem::mouseReleaseEvent(event);
}
ImageViewer::ImageViewer(QWidget *parent) : QWidget(parent)
{
imageScene = new QGraphicsScene(this);
imageView = new QGraphicsView(imageScene);
imagePixmap = nullptr;
QVBoxLayout *topLayout = new QVBoxLayout;
topLayout->addWidget(imageView);
setLayout(topLayout);
imageView->setDragMode(QGraphicsView::NoDrag);
}
void ImageViewer::setImage(const QString & fileName)
{
QImage image(fileName);
if(imagePixmap != nullptr)
{
imageScene->removeItem(imagePixmap);
delete imagePixmap;
}
imagePixmap = new QGraphicsPixmapItem(QPixmap::fromImage(image));
imageView->setSceneRect(0, 0, image.width(), image.height());
imageScene->addItem(imagePixmap);
cvImage = cv::imread(fileName.toStdString().c_str());
}
void ImageViewer::addOverlay(QRectF cvRect)
{
auto overlayRect = new OverlayRectangle(cvRect, cvImage);
imageScene->addItem(overlayRect);
}