jfjoch_viewer: Extra panel for ROI (tbd)

This commit is contained in:
2025-11-05 11:57:59 +01:00
parent b15d06c1b0
commit 78d4f21d4b
8 changed files with 141 additions and 49 deletions

View File

@@ -56,6 +56,8 @@ ADD_EXECUTABLE(jfjoch_viewer jfjoch_viewer.cpp JFJochViewerWindow.cpp JFJochView
windows/JFJochViewerReflectionListWindow.h
widgets/JFJochOneOverResSqChartView.cpp
widgets/JFJochOneOverResSqChartView.h
JFJochViewerImageROIStatistics.cpp
JFJochViewerImageROIStatistics.h
)
TARGET_LINK_LIBRARIES(jfjoch_viewer Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Charts Qt6::DBus

View File

@@ -8,6 +8,7 @@
#include <QGraphicsScene>
#include <QWheelEvent>
#include <QScrollBar>
#include <QMenu>
#include <cmath>
// Constructor
@@ -107,6 +108,8 @@ void JFJochViewerImage::mousePressEvent(QMouseEvent *event) {
else
mouse_event_type = MouseEventType::Panning;
}
} else if (event->button() == Qt::RightButton) {
mouse_event_type = MouseEventType::RightClickMenu;
}
QGraphicsView::mousePressEvent(event); // Call base implementation
}
@@ -175,7 +178,9 @@ void JFJochViewerImage::mouseReleaseEvent(QMouseEvent *event) {
if (!scene() || !image) return;
setCursor(Qt::CursorShape::ArrowCursor);
if (mouse_event_type == MouseEventType::MovingROI) {
if (mouse_event_type == MouseEventType::RightClickMenu) {
ShowImageMenu(event);
} else if (mouse_event_type == MouseEventType::MovingROI) {
if (roi_type == RoiType::RoiBox) {
roiStartPos = RoundPoint(roiStartPos);
roiEndPos = RoundPoint(roiEndPos);
@@ -669,3 +674,57 @@ void JFJochViewerImage::highlightIceRings(bool input) {
highlight_ice_rings = input;
Redraw();
}
void JFJochViewerImage::ShowImageMenu(QMouseEvent *event) {
auto mouse_loc = mapToScene(event->pos());
float radius = roi_box.height() / 2.0;
QPointF center = roi_box.center();
bool mouse_in_roi = false;
if (roi_box.width() * roi_box.height() > 0) {
if (roi_box.contains(mouse_loc)) {
if (roi_type == RoiType::RoiCircle) {
float dx = mouse_loc.x() - center.x();
float dy = mouse_loc.y() - center.y();
float distance_sq = dx * dx + dy * dy;
if (distance_sq <= radius * radius) {
mouse_in_roi = true;
}
} else
mouse_in_roi = true;
}
}
if (mouse_in_roi) {
QMenu menu;
// Show ROI coordinates (read-only)
QString roi_coordinates;
if (roi_type == RoiType::RoiBox) {
roi_coordinates = QString("ROI Box x: [%1, %2] y: [%3, %4]")
.arg(roi_box.left())
.arg(roi_box.right())
.arg(roi_box.top())
.arg(roi_box.bottom());
} else {
roi_coordinates = QString("ROI Circle: center: [%1, %2] r: %3").arg(center.x()).arg(center.y()).arg(radius);
}
menu.addAction(roi_coordinates)->setDisabled(true);
// Add or remove from user mask
QAction *addMaskAction = menu.addAction("Add to user mask");
QAction *removeMaskAction = menu.addAction("Remove from user mask");
// Show the menu at the cursor's position
QAction *selectedAction = menu.exec(event->globalPos());
if (selectedAction == addMaskAction) {
// Implement "Add to user mask" functionality here
} else if (selectedAction == removeMaskAction) {
// Implement "Remove from user mask" functionality here
}
}
}

View File

@@ -48,6 +48,9 @@ private:
void DrawTopPixels();
void DrawSaturation();
void DrawCross(float x, float y, float size, float width, float z = 1);
void ShowImageMenu(QMouseEvent *event);
double scale_factor = 1.0;
ColorScale color_scale;
std::shared_ptr<const JFJochReaderImage> image;
@@ -71,7 +74,7 @@ private:
QPointF roiEndPos;
enum class RoiType {RoiBox, RoiCircle};
enum class MouseEventType {None, Panning, DrawingROI, MovingROI};
enum class MouseEventType {None, Panning, DrawingROI, MovingROI, RightClickMenu};
MouseEventType mouse_event_type = MouseEventType::None;
RoiType roi_type = RoiType::RoiBox;

View File

@@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "JFJochViewerImageROIStatistics.h"
#include "../../.cache/JetBrains/CLion2025.2/.docker/2025_2/Docker/gitea_psi_ch_leonarski_f_jfjoch_ubuntu2404_2510/usr/include/x86_64-linux-gnu/qt6/QtWidgets/QVBoxLayout"
JFJochViewerImageROIStatistics::JFJochViewerImageROIStatistics(QWidget *parent)
: QWidget(parent) {
QVBoxLayout* layout = new QVBoxLayout(this);
roi_pos = new QLabel("None", this);
roi_label = new QLabel("", this);
layout->addWidget(roi_pos);
layout->addWidget(roi_label);
}
void JFJochViewerImageROIStatistics::loadImage(std::shared_ptr<const JFJochReaderImage> image) {
if (!image) {
roi_pos->setText("None");
roi_label->setText("");
} else {
auto roi = image->GetROI();
if (roi && roi->pixels > 0) {
auto roi_npixel = static_cast<double>(roi->pixels);
double roi_mean_val = static_cast<double>(roi->sum) / roi_npixel;
double variance = static_cast<double>(roi->sum_square) / roi_npixel - roi_mean_val * roi_mean_val;
QString text = QString("Sum <b>%1</b> Mean <b>%2</b> Var <b>%3</b> Max <b>%4</b>")
.arg(roi->sum)
.arg(QString::number(roi_mean_val, 'f', 3))
.arg(QString::number(variance, 'f', 3))
.arg(roi->max_count);
roi_label->setText(text);
roi_pos->setText(QString::fromStdString(image->GetROIDescription()));
} else {
roi_label->setText("");
roi_pos->setText("None");
}
}
}

View File

@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JFJOCH_JFJOCHVIEWERIMAGEROISTATISTICS_H
#define JFJOCH_JFJOCHVIEWERIMAGEROISTATISTICS_H
#include <QLabel>
#include "../reader/JFJochReaderImage.h"
class JFJochViewerImageROIStatistics : public QWidget {
Q_OBJECT
QLabel *roi_pos;
QLabel *roi_label;
public:
JFJochViewerImageROIStatistics(QWidget *parent);
public slots:
void loadImage(std::shared_ptr<const JFJochReaderImage> image);
};
#endif //JFJOCH_JFJOCHVIEWERIMAGEROISTATISTICS_H

View File

@@ -128,19 +128,6 @@ JFJochViewerImageStatistics::JFJochViewerImageStatistics(QWidget *parent) : QWid
b_factor = new QLabel(this);
layout->addRow(new QLabel("B-factor:"), b_factor);
roi_sum = new QLabel(this);
layout->addRow(new QLabel("ROI sum:"), roi_sum);
roi_mean = new QLabel(this);
layout->addRow(new QLabel("ROI mean:"), roi_mean);
roi_stddev = new QLabel(this);
layout->addRow(new QLabel("ROI st. dev.:"), roi_stddev);
roi_max = new QLabel(this);
layout->addRow(new QLabel("ROI max:"), roi_max);
}
QString TrimZeros(double number, int precision) {
@@ -172,10 +159,6 @@ void JFJochViewerImageStatistics::loadImage(std::shared_ptr<const JFJochReaderIm
bkg_estimate->setText("");
indexed->setText("");
indexed->setToolTip("");
roi_sum->setText("");
roi_mean->setText("");
roi_stddev->setText("");
roi_max->setText("");
b_factor->setText("");
profile_radius->setText("");
res_estimate->setText("");
@@ -314,27 +297,4 @@ void JFJochViewerImageStatistics::loadImage(std::shared_ptr<const JFJochReaderIm
} else {
indexed->setText("N/A");
}
auto roi = image->GetROI();
if (roi && roi->pixels > 0) {
text = QString("<b>%1</b>").arg(roi->sum);
roi_sum->setText(text);
auto roi_npixel = static_cast<double>(roi->pixels);
double roi_mean_val = static_cast<double>(roi->sum) / roi_npixel;
text = QString("<b>%1</b>").arg(QString::number(roi_mean_val, 'f', 3));
roi_mean->setText(text);
double variance = static_cast<double>(roi->sum_square) / roi_npixel - roi_mean_val * roi_mean_val;
text = QString("<b>%1</b>").arg(QString::number(sqrt(variance), 'f', 3));
roi_stddev->setText(text);
text = QString("<b>%1</b>").arg(roi->max_count);
roi_max->setText(text);
} else {
roi_sum->setText("N/A");
roi_mean->setText("N/A");
roi_stddev->setText("N/A");
roi_max->setText("N/A");
}
}

View File

@@ -25,11 +25,6 @@ class JFJochViewerImageStatistics : public QWidget {
QLabel *b_factor;
QLabel *profile_radius;
QLabel *roi_sum;
QLabel *roi_mean;
QLabel *roi_stddev;
QLabel *roi_max;
public:
JFJochViewerImageStatistics(QWidget *parent);

View File

@@ -10,6 +10,8 @@
#include <QComboBox>
#include "JFJochViewerSidePanel.h"
#include "JFJochViewerImageROIStatistics.h"
#include "widgets/TitleLabel.h"
#include "JFJochViewerImageStatistics.h"
@@ -21,8 +23,13 @@ JFJochViewerSidePanel::JFJochViewerSidePanel(QWidget *parent) : QWidget(parent)
auto stats = new JFJochViewerImageStatistics(this);
layout->addWidget(stats);
connect(this, &JFJochViewerSidePanel::imageLoaded,
stats, &JFJochViewerImageStatistics::loadImage);
connect(this, &JFJochViewerSidePanel::imageLoaded, stats, &JFJochViewerImageStatistics::loadImage);
layout->addWidget(new TitleLabel("ROI", this));
auto roi = new JFJochViewerImageROIStatistics(this);
layout->addWidget(roi);
connect(this, &JFJochViewerSidePanel::imageLoaded, roi, &JFJochViewerImageROIStatistics::loadImage);
layout->addWidget(new TitleLabel("Image features", this));