Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
pt2d
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
QIM
Tools
pt2d
Commits
6bcc3a83
Commit
6bcc3a83
authored
2 months ago
by
s224361
Browse files
Options
Downloads
Patches
Plain Diff
Cleaned up modules
parent
4cfed8cb
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
modules/mainWindow.py
+62
-21
62 additions, 21 deletions
modules/mainWindow.py
with
62 additions
and
21 deletions
modules/mainWindow.py
+
62
−
21
View file @
6bcc3a83
import
math
import
numpy
as
np
from
scipy.signal
import
savgol_filter
from
PyQt5.QtWidgets
import
(
QMainWindow
,
QPushButton
,
QHBoxLayout
,
QVBoxLayout
,
QWidget
,
QFileDialog
)
from
PyQt5.QtGui
import
QPixmap
,
QImage
from
PyQt5.QtCore
import
QCloseEvent
from
compute_cost_image
import
compute_cost_image
from
preprocess_image
import
preprocess_image
from
advancedSettingsWidget
import
AdvancedSettingsWidget
...
...
@@ -21,28 +21,26 @@ class MainWindow(QMainWindow):
self
.
_circle_calibrated_radius
=
6
self
.
_last_loaded_file_path
=
None
#
F
or the contrast slider
#
Value f
or the contrast slider
self
.
_current_clip_limit
=
0.01
# Outer widget
+
layout
# Outer widget
and
layout
self
.
_main_widget
=
QWidget
()
self
.
_main_layout
=
QHBoxLayout
(
self
.
_main_widget
)
#
The "left" part: c
ontainer for the image area
+
its controls
#
C
ontainer for the image area
and
its controls
self
.
_left_panel
=
QVBoxLayout
()
#
We'll make a c
ontainer widget for
the left panel, so we can set stretches:
#
C
ontainer widget for
stretching the panel
self
.
_left_container
=
QWidget
()
self
.
_left_container
.
setLayout
(
self
.
_left_panel
)
# Now we add them to the main layout with 70%:30% ratio
self
.
_main_layout
.
addWidget
(
self
.
_left_container
,
7
)
# 70%
self
.
_main_layout
.
addWidget
(
self
.
_left_container
,
7
)
# 70% ratio of the full window
#
We haven't added the advanced widget yet, but we'll do so with ratio=3 => 30%
#
Advanced widget window
self
.
_advanced_widget
=
AdvancedSettingsWidget
(
self
)
# Hide it initially
self
.
_advanced_widget
.
hide
()
self
.
_main_layout
.
addWidget
(
self
.
_advanced_widget
,
3
)
self
.
_main_layout
.
addWidget
(
self
.
_advanced_widget
,
3
)
# 30% ratio of the full window
self
.
setCentralWidget
(
self
.
_main_widget
)
...
...
@@ -64,7 +62,6 @@ class MainWindow(QMainWindow):
self
.
btn_clear_points
.
clicked
.
connect
(
self
.
clear_points
)
btn_layout
.
addWidget
(
self
.
btn_clear_points
)
# "Advanced Settings" toggle
self
.
btn_advanced
=
QPushButton
(
"
Advanced Settings
"
)
self
.
btn_advanced
.
setCheckable
(
True
)
self
.
btn_advanced
.
clicked
.
connect
(
self
.
_toggle_advanced_settings
)
...
...
@@ -76,7 +73,10 @@ class MainWindow(QMainWindow):
self
.
_old_central_widget
=
None
self
.
_editor
=
None
def
_toggle_advanced_settings
(
self
,
checked
):
def
_toggle_advanced_settings
(
self
,
checked
:
bool
):
"""
Toggles the visibility of the advanced settings widget.
"""
if
checked
:
self
.
_advanced_widget
.
show
()
else
:
...
...
@@ -84,8 +84,11 @@ class MainWindow(QMainWindow):
# Force re-layout
self
.
adjustSize
()
def
open_circle_editor
(
self
):
"""
Replace central widget with circle editor.
"""
"""
Replace central widget with circle editor.
"""
if
not
self
.
_last_loaded_pixmap
:
print
(
"
No image loaded yet! Cannot open circle editor.
"
)
return
...
...
@@ -102,10 +105,17 @@ class MainWindow(QMainWindow):
self
.
_editor
=
editor
self
.
setCentralWidget
(
editor
)
def
_on_circle_editor_done
(
self
,
final_radius
):
def
_on_circle_editor_done
(
self
,
final_radius
:
int
):
"""
Updates the calibrated radius, computes the cost image based on the new radius,
and updates the image view with the new cost image.
It also restores the previous central widget and cleans up the editor widget.
"""
self
.
_circle_calibrated_radius
=
final_radius
print
(
f
"
Circle Editor done. Radius =
{
final_radius
}
"
)
# Update cost image and path using new radius
if
self
.
_last_loaded_file_path
:
cost_img
=
compute_cost_image
(
self
.
_last_loaded_file_path
,
...
...
@@ -118,6 +128,7 @@ class MainWindow(QMainWindow):
self
.
image_view
.
_rebuild_full_path
()
self
.
_update_advanced_images
()
# Swap back to central widget
editor_widget
=
self
.
takeCentralWidget
()
if
editor_widget
is
not
None
:
editor_widget
.
setParent
(
None
)
...
...
@@ -131,15 +142,23 @@ class MainWindow(QMainWindow):
self
.
_editor
=
None
def
toggle_rainbow
(
self
):
"""
Toggle rainbow coloring of the path.
"""
self
.
image_view
.
toggle_rainbow
()
def
load_image
(
self
):
"""
Load an image and update the image view and cost image.
The supported image formats are: PNG, JPG, JPEG, BMP, and TIF.
"""
options
=
QFileDialog
.
Options
()
file_path
,
_
=
QFileDialog
.
getOpenFileName
(
self
,
"
Open Image
"
,
""
,
"
Images (*.png *.jpg *.jpeg *.bmp *.tif)
"
,
options
=
options
)
if
file_path
:
self
.
image_view
.
load_image
(
file_path
)
...
...
@@ -158,7 +177,10 @@ class MainWindow(QMainWindow):
self
.
_last_loaded_file_path
=
file_path
self
.
_update_advanced_images
()
def
update_contrast
(
self
,
clip_limit
):
def
update_contrast
(
self
,
clip_limit
:
float
):
"""
Updates and applies the contrast value of the image.
"""
self
.
_current_clip_limit
=
clip_limit
if
self
.
_last_loaded_file_path
:
cost_img
=
compute_cost_image
(
...
...
@@ -174,6 +196,10 @@ class MainWindow(QMainWindow):
self
.
_update_advanced_images
()
def
_update_advanced_images
(
self
):
"""
Updates the advanced images display with the latest image.
If no image has been loaded, the method returns without making any updates.
"""
if
not
self
.
_last_loaded_pixmap
:
return
pm_np
=
self
.
_qpixmap_to_gray_float
(
self
.
_last_loaded_pixmap
)
...
...
@@ -185,7 +211,16 @@ class MainWindow(QMainWindow):
cost_img_np
=
self
.
image_view
.
cost_image
self
.
_advanced_widget
.
update_displays
(
contrasted_blurred
,
cost_img_np
)
def
_qpixmap_to_gray_float
(
self
,
qpix
):
def
_qpixmap_to_gray_float
(
self
,
qpix
:
QPixmap
)
->
np
.
ndarray
:
"""
Convert a QPixmap to a grayscale float array.
Args:
qpix: The QPixmap to be converted.
Returns:
A 2D numpy array representing the grayscale image.
"""
img
=
qpix
.
toImage
()
img
=
img
.
convertToFormat
(
QImage
.
Format_ARGB32
)
ptr
=
img
.
bits
()
...
...
@@ -205,12 +240,9 @@ class MainWindow(QMainWindow):
print
(
"
No path to export.
"
)
return
# We'll consider each anchor point as "USER-PLACED".
# But unlike a distance-threshold approach, we assign each anchor
# to exactly one closest path point.
anchor_points
=
self
.
image_view
.
anchor_points
# F
or each anchor, f
ind the index of the closest path point
# Find
s
the index of the closest path point
for each anchor point
user_placed_indices
=
set
()
for
ax
,
ay
in
anchor_points
:
min_dist
=
float
(
'
inf
'
)
...
...
@@ -245,7 +277,16 @@ class MainWindow(QMainWindow):
print
(
f
"
Exported path with
{
len
(
full_xy
)
}
points to
{
file_path
}
"
)
def
clear_points
(
self
):
"""
Clears points from the image.
"""
self
.
image_view
.
clear_guide_points
()
def
closeEvent
(
self
,
event
):
def
closeEvent
(
self
,
event
:
QCloseEvent
):
"""
Handle the window close event.
Args:
event: The close event.
"""
super
().
closeEvent
(
event
)
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment