From d729aaa23dd85d16ae2f70d24034f20f789748e2 Mon Sep 17 00:00:00 2001 From: "simon.fanetti" <simon.fanetti@etu.hesge.ch> Date: Wed, 20 May 2020 14:22:33 +0200 Subject: [PATCH] temp cropping mask app --- app/SandboxSetup/SandboxSetup.pro | 9 +- app/SandboxSetup/croppingmask.cpp | 104 +++++++++++++++++++++++ app/SandboxSetup/croppingmask.h | 45 ++++++++++ app/SandboxSetup/croppingmask.ui | 134 ++++++++++++++++++++++++++++++ app/SandboxSetup/main.cpp | 50 ++++++----- app/SandboxSetup/monitorgui.cpp | 8 +- inc/beamer.h | 4 +- inc/sandboxSetup.h | 3 + src/lib/sandboxSetup.cpp | 51 +++++++++--- 9 files changed, 369 insertions(+), 39 deletions(-) create mode 100644 app/SandboxSetup/croppingmask.cpp create mode 100644 app/SandboxSetup/croppingmask.h create mode 100644 app/SandboxSetup/croppingmask.ui diff --git a/app/SandboxSetup/SandboxSetup.pro b/app/SandboxSetup/SandboxSetup.pro index 69b20aa..b9aa084 100644 --- a/app/SandboxSetup/SandboxSetup.pro +++ b/app/SandboxSetup/SandboxSetup.pro @@ -26,15 +26,18 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ main.cpp \ monitorgui.cpp \ - camerafocus.cpp + camerafocus.cpp \ + croppingmask.cpp HEADERS += \ monitorgui.h \ - camerafocus.h + camerafocus.h \ + croppingmask.h FORMS += \ monitorgui.ui \ - camerafocus.ui + camerafocus.ui \ + croppingmask.ui diff --git a/app/SandboxSetup/croppingmask.cpp b/app/SandboxSetup/croppingmask.cpp new file mode 100644 index 0000000..b76acca --- /dev/null +++ b/app/SandboxSetup/croppingmask.cpp @@ -0,0 +1,104 @@ +#include "croppingmask.h" +#include "ui_croppingmask.h" + +CroppingMask::CroppingMask(SandboxSetup *sandbox, QWidget *parent) : + QDialog(parent), + ui(new Ui::CroppingMask) +{ + ui->setupUi(this); + setup = sandbox; + // TODO : try to load cropping mask from file + +} + +CroppingMask::~CroppingMask() +{ + delete ui; +} + +void CroppingMask::paintEvent(QPaintEvent *){ + QPainter p; + p.begin(this); + p.end(); +} + +void CroppingMask::on_btnTakePicture_clicked() +{ + setup->captureBlueScreen(); + cv::Mat rgb = setup->camera.getRGBFrame(); + cameraRGBFrame = rgb; + + QImage img = QImage((uchar *)rgb.data, (int)rgb.cols, (int)rgb.rows, static_cast<int>(rgb.step.buf[0]), QImage::Format_RGB888); + QPixmap image = QPixmap::fromImage(img); + + //ui->lblFrame->setPixmap(image); + + // no config found + if(!maskValideInFrame(rgb)){ + float y = ui->lblMask->height(); + float x = ui->lblMask->width(); + rectPoints = std::vector<cv::Point>{ cv::Point(1.0/4*x, 1.0/4*y), cv::Point(1.0/4*x, 3.0/4*y), cv::Point(3.0/4*x, 3.0/4*y), cv::Point(3.0/4*x, 1.0/4*y) }; + } + drawMask(rectPoints); +} + +bool CroppingMask::maskValideInFrame(cv::Mat rgb){ + + if(rectPoints.empty()) + return false; + + for(uint i=0; i<rectPoints.size(); i++){ + if( !(( 0<=rectPoints[i].x && rectPoints[i].x<rgb.size().width ) && + ( 0<=rectPoints[i].y && rectPoints[i].y<rgb.size().height ) )) + { + return false; + } + } + + return true; +} + +void CroppingMask::drawMask(std::vector<cv::Point> rectPoints){ + + QPixmap img; + QPainter maskPainter(&img); + QPolygon poly; + + for(uint i=0; i<rectPoints.size(); i++){ + poly << QPoint(rectPoints[i].x, rectPoints[i].y); + } + + // QPen: style(), width(), brush(), capStyle() and joinStyle(). + QPen pen(Qt::green, 2, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin); + maskPainter.setPen(pen); + maskPainter.drawPolygon(poly); + + maskPainter.drawRect(15,15,100,100); + + + QPixmap px; + QPainter p(&px); + p.setPen(Qt::blue); + p.drawLine(5,5, 40, 40); + p.end(); + + ui->lblMask->setPixmap(px); +} + +void CroppingMask::scaleMaskWindowToFrame(){ + + float xCoeff = cameraRGBFrame.size().width / ui->lblMask->width(); + float yCoeff = cameraRGBFrame.size().height / ui->lblMask->height(); + + for(uint i=0; i<rectPoints.size(); i++){ + rectPoints[i].x = rectPoints[i].x * xCoeff; + rectPoints[i].y = rectPoints[i].y * yCoeff; + } +} + +void CroppingMask::on_btnbxEnd_accepted() +{ + state = true; + // Needed because the image shown is stretched + scaleMaskWindowToFrame(); +} diff --git a/app/SandboxSetup/croppingmask.h b/app/SandboxSetup/croppingmask.h new file mode 100644 index 0000000..b582cbc --- /dev/null +++ b/app/SandboxSetup/croppingmask.h @@ -0,0 +1,45 @@ +#ifndef CROPPINGMASK_H +#define CROPPINGMASK_H + +#include <QDialog> +#include <sandboxSetup.h> + +#include <QPainter> +#include <QPolygon> +//#include <QPainterPath> + +namespace Ui { +class CroppingMask; +} + +class CroppingMask : public QDialog +{ + Q_OBJECT + +public: + explicit CroppingMask(SandboxSetup *sandbox,QWidget *parent = 0); + ~CroppingMask(); + std::vector<cv::Point> getRectPoints(){ return rectPoints; }; + bool isOk(){ return state; }; + +private slots: + void on_btnTakePicture_clicked(); + void on_btnbxEnd_accepted(); + +private: + Ui::CroppingMask *ui; + SandboxSetup *setup; + std::vector<cv::Point> rectPoints; + bool state = false; + cv::Mat cameraRGBFrame; + + bool maskValideInFrame(cv::Mat rgb); + void drawMask(std::vector<cv::Point> rectPoints); + void scaleMaskWindowToFrame(); + +protected: + void paintEvent(QPaintEvent* event); + +}; + +#endif // CROPPINGMASK_H diff --git a/app/SandboxSetup/croppingmask.ui b/app/SandboxSetup/croppingmask.ui new file mode 100644 index 0000000..c206a8c --- /dev/null +++ b/app/SandboxSetup/croppingmask.ui @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>CroppingMask</class> + <widget class="QDialog" name="CroppingMask"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>635</width> + <height>422</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <widget class="QDialogButtonBox" name="btnbxEnd"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="geometry"> + <rect> + <x>270</x> + <y>370</y> + <width>341</width> + <height>32</height> + </rect> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + <widget class="QLabel" name="lblFrame"> + <property name="geometry"> + <rect> + <x>40</x> + <y>30</y> + <width>441</width> + <height>281</height> + </rect> + </property> + <property name="lineWidth"> + <number>3</number> + </property> + <property name="text"> + <string>Press "Take Picture" when your beamer is ready</string> + </property> + <property name="scaledContents"> + <bool>true</bool> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + <widget class="QPushButton" name="btnTakePicture"> + <property name="geometry"> + <rect> + <x>520</x> + <y>60</y> + <width>101</width> + <height>25</height> + </rect> + </property> + <property name="text"> + <string>Take Picture</string> + </property> + </widget> + <widget class="QLabel" name="lblMask"> + <property name="geometry"> + <rect> + <x>40</x> + <y>30</y> + <width>441</width> + <height>281</height> + </rect> + </property> + <property name="lineWidth"> + <number>3</number> + </property> + <property name="text"> + <string/> + </property> + <property name="scaledContents"> + <bool>true</bool> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </widget> + <resources/> + <connections> + <connection> + <sender>btnbxEnd</sender> + <signal>accepted()</signal> + <receiver>CroppingMask</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>btnbxEnd</sender> + <signal>rejected()</signal> + <receiver>CroppingMask</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/SandboxSetup/main.cpp b/app/SandboxSetup/main.cpp index 079ccbf..8c5d5dc 100644 --- a/app/SandboxSetup/main.cpp +++ b/app/SandboxSetup/main.cpp @@ -1,5 +1,6 @@ #include "monitorgui.h" #include "camerafocus.h" +#include "croppingmask.h" #include <QApplication> #include <sandboxSetup.h> @@ -8,44 +9,55 @@ int main(int argc, char *argv[]) { SandboxSetup setup; - QApplication a(argc, argv); + QApplication app(argc, argv); - MonitorGui m; - m.show(); - a.exec(); - if(!m.isOk()){ + + // Select output screen and projection's resolutions + MonitorGui mg; + mg.show(); + app.exec(); + if(!mg.isOk()){ std::cout << "Cancel resolution" << std::endl; return 1; } - setup.setBeamerResolution(cv::Size(m.getWidth(), m.getHeight())); + setup.setBeamerResolution(cv::Size(mg.getWidth(), mg.getHeight())); + - CameraFocus c(&setup); - c.show(); - a.exec(); - if(!c.isOk()){ + // Edit frame process profil for the setupBeamerLocation routine + CameraFocus cf(&setup); + cf.show(); + app.exec(); + if(!cf.isOk()){ std::cout << "Cancel camera parameters" << std::endl; return 1; } - FrameProcessProfil p = *setup.beamer.getProfil(); - std::cout << "params" << std::endl; - std::cout << p.getContrast() << std::endl; - std::cout << p.getBrightness() << std::endl; - std::cout << p.getRadiusRatio() << std::endl; - std::cout << p.getUpperMinThreshold() << std::endl; - std::cout << p.getLowerMinThreshold() << std::endl; - - if(setup.setupProjection()){ + // Setup the adjust matrix and cropping mask + CroppingMask cm(&setup); + cm.show(); + app.exec(); + if(!cm.isOk()){ std::cout << "Cancel crop" << std::endl; return 1; } + cv::Size s = setup.camera.getDepthFrame().size(); + cv::Point center(s.width / 2, s.height / 2); + std::vector<cv::Point> rectPoints = cm.getRectPoints(); + + setup.setupAdjustMatrix(rectPoints, center); + setup.setupCroppingMask(rectPoints); + + + // Setup the beamer location if(setup.setupBeamerLocation()){ std::cout << "Cancel beamer position" << std::endl; return 1; } + + // Save config in file if(setup.saveConfig()){ std::cout << "Failed to save configuration" << std::endl; return 1; diff --git a/app/SandboxSetup/monitorgui.cpp b/app/SandboxSetup/monitorgui.cpp index 17c43a3..d146386 100644 --- a/app/SandboxSetup/monitorgui.cpp +++ b/app/SandboxSetup/monitorgui.cpp @@ -47,7 +47,11 @@ void MonitorGui::on_btnbxMonitors_accepted() void MonitorGui::initMonitorMapWithFile(std::string path){ // Save in file the monitors and their resolutions - system( ("xrandr -d :0 | sed -n '1!p' > " + path).c_str() ); + int err = system( ("xrandr -d :0 | sed -n '1!p' > " + path).c_str() ); + if(err){ + std::cout << "Couldn't get screens and their resolutions" << std::endl; + exit(err); + } loadResolutionsFromFile(path); std::remove(path.c_str()); } @@ -58,7 +62,7 @@ void MonitorGui::loadResolutionsOf(QScreen* sc){ const char *key = sc->name().toStdString().c_str(); std::vector<std::string> resolutions = monitors[key]; - for(int i=0; i<resolutions.size(); i++){ + for(uint i=0; i<resolutions.size(); i++){ std::vector<std::string> res = splitResolution(resolutions[i]); ui->cbxResolutions->addItem( QString::fromStdString(res[0] + "x" + res[1]) ); } diff --git a/inc/beamer.h b/inc/beamer.h index d0460f5..c1caea0 100644 --- a/inc/beamer.h +++ b/inc/beamer.h @@ -13,8 +13,8 @@ class FrameProcessProfil{ // radius of the circle based on the width of the frame, where : // radius = frame.width / ratioRadius int ratioRadius; // [1, n] - int upperMinThreshold; // [lowerMin, 255] - int lowerMinThreshold; // [0, upperMin] + int upperMinThreshold; // [lowerMin, 255] the strongest the contrast in the image is, the higher this param should be + int lowerMinThreshold; // [0, upperMin] should be set way lower than upperMin if cicles have weak contrasts at their edges public: FrameProcessProfil(double c=1.0, int b=0, int r=8, int up=200, int low=100){ diff --git a/inc/sandboxSetup.h b/inc/sandboxSetup.h index e3a9389..574d6c0 100644 --- a/inc/sandboxSetup.h +++ b/inc/sandboxSetup.h @@ -28,6 +28,9 @@ class SandboxSetup{ int saveFrameProcessProfil(); // edit variables of config => not persistant + void captureBlueScreen(); + void setupAdjustMatrix(std::vector<cv::Point> rectPoints, cv::Point center); + void setupCroppingMask(std::vector<cv::Point> rectPoints); int setupProjection(); int setupBeamerResolution(); int setupBeamerLocation(); diff --git a/src/lib/sandboxSetup.cpp b/src/lib/sandboxSetup.cpp index 3938ff8..46d0f2d 100644 --- a/src/lib/sandboxSetup.cpp +++ b/src/lib/sandboxSetup.cpp @@ -61,6 +61,10 @@ int SandboxSetup::saveFrameProcessProfil(){ } +// +// Default setup routines +// + int SandboxSetup::setupBeamerResolution(){ int width = 0; int height = 0; @@ -92,22 +96,12 @@ int SandboxSetup::setupBeamerLocation(){ // return 1 when user exits process int SandboxSetup::setupProjection(){ - // Blue screen - char windowName[] = "border"; - initWindowsFullScreen(windowName); - cv::Mat frameBeamer(cv::Size(beamer.getWidth(), beamer.getHeight()), CV_8UC3, cv::Scalar(255, 0, 0)); - cv::imshow(windowName, frameBeamer); - cv::waitKey(100); + captureBlueScreen(); - // Take picture - camera.start(); // 1 seconde of warming up - camera.captureFrame(); cv::Mat frameData = camera.getDepthFrame(); cv::Mat coloredFrame = camera.getRGBFrame(); cv::Size s = frameData.size(); cv::Point center(s.width / 2, s.height / 2); - camera.stop(); - cv::destroyAllWindows(); // Edit projection float y = coloredFrame.size().height; @@ -118,18 +112,49 @@ int SandboxSetup::setupProjection(){ } cv::destroyAllWindows(); + + // must be called before setupCroppingMask + setupAdjustMatrix(rectPoints, center); + + setupCroppingMask(rectPoints); + + return 0; +} + + +void SandboxSetup::captureBlueScreen(){ + + // Blue screen + char windowName[] = "border"; + initWindowsFullScreen(windowName); + cv::Mat frameBeamer(cv::Size(beamer.getWidth(), beamer.getHeight()), CV_8UC3, cv::Scalar(255, 0, 0)); + cv::imshow(windowName, frameBeamer); + cv::waitKey(100); + + // Take picture + camera.start(); // 1 seconde of warming up + camera.captureFrame(); + camera.stop(); + cv::destroyAllWindows(); +} + + +void SandboxSetup::setupAdjustMatrix(std::vector<cv::Point> rectPoints, cv::Point center){ + // Set adjusting matrix for the projection int widthTop = rectPoints[3].x - rectPoints[0].x; double angle1 = atan((double)(rectPoints[3].y - rectPoints[0].y) / widthTop); cv::Mat matRotation = cv::getRotationMatrix2D(center, toDegrees(angle1), 1); // adjustingMatrix projection.setAdjustingMatrix(matRotation); +} + +void SandboxSetup::setupCroppingMask(std::vector<cv::Point> rectPoints){ // Set cropping mask + int widthTop = rectPoints[3].x - rectPoints[0].x; cv::Size rectSize = cv::Size(widthTop, cvRound(widthTop / 1.33333) + 5); cv::Point p = projection.rotatePixel(rectPoints[0]); camera.setCroppingMask(cv::Rect(p, rectSize)); // croppingMask - - return 0; } -- GitLab