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
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
QIM
Tools
pt2d
Commits
56fda2e4
Commit
56fda2e4
authored
6 months ago
by
Christian
Browse files
Options
Downloads
Patches
Plain Diff
added advanced settings
parent
76afb30a
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
GUI_draft_live.py
+249
-47
249 additions, 47 deletions
GUI_draft_live.py
with
249 additions
and
47 deletions
GUI_draft_live.py
+
249
−
47
View file @
56fda2e4
...
@@ -9,12 +9,17 @@ from PyQt5.QtWidgets import (
...
@@ -9,12 +9,17 @@ from PyQt5.QtWidgets import (
QApplication
,
QMainWindow
,
QGraphicsView
,
QGraphicsScene
,
QApplication
,
QMainWindow
,
QGraphicsView
,
QGraphicsScene
,
QGraphicsEllipseItem
,
QGraphicsPixmapItem
,
QPushButton
,
QGraphicsEllipseItem
,
QGraphicsPixmapItem
,
QPushButton
,
QHBoxLayout
,
QVBoxLayout
,
QWidget
,
QFileDialog
,
QGraphicsTextItem
,
QHBoxLayout
,
QVBoxLayout
,
QWidget
,
QFileDialog
,
QGraphicsTextItem
,
QSlider
,
QLabel
QSlider
,
QLabel
,
QCheckBox
,
QGridLayout
,
QSizePolicy
)
)
from
PyQt5.QtGui
import
QPixmap
,
QPen
,
QBrush
,
QColor
,
QFont
from
PyQt5.QtGui
import
QPixmap
,
QPen
,
QBrush
,
QColor
,
QFont
,
QImage
from
PyQt5.QtCore
import
Qt
,
QRectF
,
QSize
from
PyQt5.QtCore
import
Qt
,
QRectF
,
QSize
from
live_wire
import
compute_cost_image
,
find_path
# Make sure the following imports exist in live_wire.py (or similar):
# from skimage import exposure
# from skimage.filters import gaussian
# def preprocess_image(image, sigma=3, clip_limit=0.01): ...
from
live_wire
import
compute_cost_image
,
find_path
,
preprocess_image
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
...
@@ -28,6 +33,9 @@ class PanZoomGraphicsView(QGraphicsView):
...
@@ -28,6 +33,9 @@ class PanZoomGraphicsView(QGraphicsView):
self
.
_panning
=
False
self
.
_panning
=
False
self
.
_pan_start
=
None
self
.
_pan_start
=
None
# Let it expand in layouts
self
.
setSizePolicy
(
QSizePolicy
.
Expanding
,
QSizePolicy
.
Expanding
)
def
wheelEvent
(
self
,
event
):
def
wheelEvent
(
self
,
event
):
"""
"""
Zoom in/out with mouse wheel.
Zoom in/out with mouse wheel.
...
@@ -72,15 +80,9 @@ class PanZoomGraphicsView(QGraphicsView):
...
@@ -72,15 +80,9 @@ class PanZoomGraphicsView(QGraphicsView):
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
# A specialized PanZoomGraphicsView for the circle editor
# A specialized PanZoomGraphicsView for the circle editor
# - Only pan if user did NOT click on the draggable circle
# - If the mouse is over the circle item, scrolling changes radius
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
class
CircleEditorGraphicsView
(
PanZoomGraphicsView
):
class
CircleEditorGraphicsView
(
PanZoomGraphicsView
):
def
__init__
(
self
,
circle_editor_widget
,
parent
=
None
):
def
__init__
(
self
,
circle_editor_widget
,
parent
=
None
):
"""
:param circle_editor_widget: Reference to the parent CircleEditorWidget
so we can communicate (e.g. update slider).
"""
super
().
__init__
(
parent
)
super
().
__init__
(
parent
)
self
.
_circle_editor_widget
=
circle_editor_widget
self
.
_circle_editor_widget
=
circle_editor_widget
...
@@ -116,7 +118,7 @@ class CircleEditorGraphicsView(PanZoomGraphicsView):
...
@@ -116,7 +118,7 @@ class CircleEditorGraphicsView(PanZoomGraphicsView):
if
isinstance
(
it
,
DraggableCircleItem
):
if
isinstance
(
it
,
DraggableCircleItem
):
# Scroll up -> increase radius, scroll down -> decrease
# Scroll up -> increase radius, scroll down -> decrease
delta
=
event
.
angleDelta
().
y
()
delta
=
event
.
angleDelta
().
y
()
# each wheel "notch" is typically 120
, so let's do small steps
# each wheel "notch" is typically 120
step
=
1
if
delta
>
0
else
-
1
step
=
1
if
delta
>
0
else
-
1
old_r
=
it
.
radius
()
old_r
=
it
.
radius
()
...
@@ -232,7 +234,7 @@ class CircleEditorWidget(QWidget):
...
@@ -232,7 +234,7 @@ class CircleEditorWidget(QWidget):
Called by CircleEditorGraphicsView when the user scrolls on the circle item.
Called by CircleEditorGraphicsView when the user scrolls on the circle item.
We sync the slider to the new radius.
We sync the slider to the new radius.
"""
"""
self
.
_slider
.
blockSignals
(
True
)
# to avoid recursively calling set_radius
self
.
_slider
.
blockSignals
(
True
)
self
.
_slider
.
setValue
(
new_radius
)
self
.
_slider
.
setValue
(
new_radius
)
self
.
_slider
.
blockSignals
(
False
)
self
.
_slider
.
blockSignals
(
False
)
...
@@ -347,8 +349,12 @@ class ImageGraphicsView(PanZoomGraphicsView):
...
@@ -347,8 +349,12 @@ class ImageGraphicsView(PanZoomGraphicsView):
self
.
cost_image_original
=
None
self
.
cost_image_original
=
None
self
.
cost_image
=
None
self
.
cost_image
=
None
# Rainbow toggle
# Rainbow toggle => start with OFF
self
.
_rainbow_enabled
=
True
self
.
_rainbow_enabled
=
False
# Smoothing parameters
self
.
_savgol_window_length
=
7
self
.
_savgol_polyorder
=
1
def
set_rainbow_enabled
(
self
,
enabled
:
bool
):
def
set_rainbow_enabled
(
self
,
enabled
:
bool
):
"""
Enable/disable rainbow mode, then rebuild the path.
"""
"""
Enable/disable rainbow mode, then rebuild the path.
"""
...
@@ -360,6 +366,29 @@ class ImageGraphicsView(PanZoomGraphicsView):
...
@@ -360,6 +366,29 @@ class ImageGraphicsView(PanZoomGraphicsView):
self
.
_rainbow_enabled
=
not
self
.
_rainbow_enabled
self
.
_rainbow_enabled
=
not
self
.
_rainbow_enabled
self
.
_rebuild_full_path
()
self
.
_rebuild_full_path
()
def
set_savgol_window_length
(
self
,
wlen
:
int
):
"""
Set the window length for the Savitzky-Golay filter and update polyorder
based on window_length_polyorder_ratio.
"""
# SavGol requires window_length to be odd and >= 3
if
wlen
<
3
:
wlen
=
3
if
wlen
%
2
==
0
:
wlen
+=
1
self
.
_savgol_window_length
=
wlen
# polyorder is nearest integer to (window_length / 7)
# but must be >= 1 and < window_length
p
=
round
(
wlen
/
7.0
)
p
=
max
(
1
,
p
)
if
p
>=
wlen
:
p
=
wlen
-
1
self
.
_savgol_polyorder
=
p
self
.
_rebuild_full_path
()
# --------------------------------------------------------------------
# --------------------------------------------------------------------
# LOADING
# LOADING
# --------------------------------------------------------------------
# --------------------------------------------------------------------
...
@@ -407,7 +436,7 @@ class ImageGraphicsView(PanZoomGraphicsView):
...
@@ -407,7 +436,7 @@ class ImageGraphicsView(PanZoomGraphicsView):
def
_add_guide_point
(
self
,
x
,
y
):
def
_add_guide_point
(
self
,
x
,
y
):
x_clamped
=
self
.
_clamp
(
x
,
self
.
dot_radius
,
self
.
_img_w
-
self
.
dot_radius
)
x_clamped
=
self
.
_clamp
(
x
,
self
.
dot_radius
,
self
.
_img_w
-
self
.
dot_radius
)
y_clamped
=
self
.
_clamp
(
y
,
self
.
dot_radius
,
self
.
_img_
h
-
self
.
dot_radius
)
y_clamped
=
self
.
_clamp
(
y
,
self
.
dot_radius
,
self
.
_img_
w
-
self
.
dot_radius
)
self
.
_revert_cost_to_original
()
self
.
_revert_cost_to_original
()
...
@@ -553,9 +582,14 @@ class ImageGraphicsView(PanZoomGraphicsView):
...
@@ -553,9 +582,14 @@ class ImageGraphicsView(PanZoomGraphicsView):
if
len
(
sub_xy
)
>
1
:
if
len
(
sub_xy
)
>
1
:
big_xy
.
extend
(
sub_xy
[
1
:])
big_xy
.
extend
(
sub_xy
[
1
:])
if
len
(
big_xy
)
>=
7
:
if
len
(
big_xy
)
>=
self
.
_savgol_window_length
:
arr_xy
=
np
.
array
(
big_xy
)
arr_xy
=
np
.
array
(
big_xy
)
smoothed
=
savgol_filter
(
arr_xy
,
window_length
=
7
,
polyorder
=
1
,
axis
=
0
)
smoothed
=
savgol_filter
(
arr_xy
,
window_length
=
self
.
_savgol_window_length
,
polyorder
=
self
.
_savgol_polyorder
,
axis
=
0
)
big_xy
=
smoothed
.
tolist
()
big_xy
=
smoothed
.
tolist
()
self
.
_full_path_xy
=
big_xy
[:]
self
.
_full_path_xy
=
big_xy
[:]
...
@@ -605,7 +639,7 @@ class ImageGraphicsView(PanZoomGraphicsView):
...
@@ -605,7 +639,7 @@ class ImageGraphicsView(PanZoomGraphicsView):
return
QColor
.
fromHsv
(
hue
,
saturation
,
value
)
return
QColor
.
fromHsv
(
hue
,
saturation
,
value
)
# --------------------------------------------------------------------
# --------------------------------------------------------------------
# MOUSE EVENTS
(with pan & zoom from PanZoomGraphicsView)
# MOUSE EVENTS
# --------------------------------------------------------------------
# --------------------------------------------------------------------
def
mousePressEvent
(
self
,
event
):
def
mousePressEvent
(
self
,
event
):
if
event
.
button
()
==
Qt
.
LeftButton
:
if
event
.
button
()
==
Qt
.
LeftButton
:
...
@@ -750,6 +784,113 @@ class ImageGraphicsView(PanZoomGraphicsView):
...
@@ -750,6 +784,113 @@ class ImageGraphicsView(PanZoomGraphicsView):
return
self
.
_full_path_xy
return
self
.
_full_path_xy
# ------------------------------------------------------------------------
# Advanced Settings Widget
# ------------------------------------------------------------------------
class
AdvancedSettingsWidget
(
QWidget
):
def
__init__
(
self
,
main_window
,
parent
=
None
):
super
().
__init__
(
parent
)
self
.
_main_window
=
main_window
# to call e.g. main_window.open_circle_editor()
main_layout
=
QVBoxLayout
()
self
.
setLayout
(
main_layout
)
# A small grid for the controls (buttons/sliders)
controls_layout
=
QGridLayout
()
# 1) Rainbow toggle
self
.
btn_toggle_rainbow
=
QPushButton
(
"
Toggle Rainbow
"
)
self
.
btn_toggle_rainbow
.
clicked
.
connect
(
self
.
_on_toggle_rainbow
)
controls_layout
.
addWidget
(
self
.
btn_toggle_rainbow
,
0
,
0
)
# 2) Circle editor
self
.
btn_circle_editor
=
QPushButton
(
"
Open Circle Editor
"
)
self
.
btn_circle_editor
.
clicked
.
connect
(
self
.
_main_window
.
open_circle_editor
)
controls_layout
.
addWidget
(
self
.
btn_circle_editor
,
0
,
1
)
# 3) Line smoothing slider + label
lab_smoothing
=
QLabel
(
"
Line smoothing (SavGol window_length)
"
)
controls_layout
.
addWidget
(
lab_smoothing
,
1
,
0
)
self
.
line_smoothing_slider
=
QSlider
(
Qt
.
Horizontal
)
self
.
line_smoothing_slider
.
setRange
(
3
,
51
)
# allow from 3 to 51
self
.
line_smoothing_slider
.
setValue
(
7
)
# default
self
.
line_smoothing_slider
.
valueChanged
.
connect
(
self
.
_on_line_smoothing_slider
)
controls_layout
.
addWidget
(
self
.
line_smoothing_slider
,
1
,
1
)
# 4) Contrast slider + label
lab_contrast
=
QLabel
(
"
Contrast (clip_limit)
"
)
controls_layout
.
addWidget
(
lab_contrast
,
2
,
0
)
self
.
contrast_slider
=
QSlider
(
Qt
.
Horizontal
)
self
.
contrast_slider
.
setRange
(
0
,
100
)
# 0..100 => 0..1 with step of 0.01
self
.
contrast_slider
.
setValue
(
1
)
# default is 0.01
self
.
contrast_slider
.
valueChanged
.
connect
(
self
.
_on_contrast_slider
)
controls_layout
.
addWidget
(
self
.
contrast_slider
,
2
,
1
)
main_layout
.
addLayout
(
controls_layout
)
# Now a horizontal layout for the two images
images_layout
=
QHBoxLayout
()
# Contrasted blurred
self
.
label_contrasted_blurred
=
QLabel
()
self
.
label_contrasted_blurred
.
setText
(
"
CONTRASTED BLURRED IMG
"
)
self
.
label_contrasted_blurred
.
setAlignment
(
Qt
.
AlignCenter
)
self
.
label_contrasted_blurred
.
setSizePolicy
(
QSizePolicy
.
Expanding
,
QSizePolicy
.
Expanding
)
self
.
label_contrasted_blurred
.
setScaledContents
(
True
)
images_layout
.
addWidget
(
self
.
label_contrasted_blurred
)
# Cost image
self
.
label_cost_image
=
QLabel
()
self
.
label_cost_image
.
setText
(
"
Current COST IMAGE
"
)
self
.
label_cost_image
.
setAlignment
(
Qt
.
AlignCenter
)
self
.
label_cost_image
.
setSizePolicy
(
QSizePolicy
.
Expanding
,
QSizePolicy
.
Expanding
)
self
.
label_cost_image
.
setScaledContents
(
True
)
images_layout
.
addWidget
(
self
.
label_cost_image
)
main_layout
.
addLayout
(
images_layout
)
def
_on_toggle_rainbow
(
self
):
self
.
_main_window
.
toggle_rainbow
()
def
_on_line_smoothing_slider
(
self
,
value
):
self
.
_main_window
.
image_view
.
set_savgol_window_length
(
value
)
def
_on_contrast_slider
(
self
,
value
):
clip_limit
=
value
/
100.0
self
.
_main_window
.
update_contrast
(
clip_limit
)
def
update_displays
(
self
,
contrasted_img_np
,
cost_img_np
):
"""
Called by main_window to refresh the two images in the advanced panel.
contrasted_img_np = the grayscaled blurred+contrasted image as float or 0-1 array
cost_img_np = the current cost image (numpy array)
"""
cb_pix
=
self
.
_np_array_to_qpixmap
(
contrasted_img_np
)
cost_pix
=
self
.
_np_array_to_qpixmap
(
cost_img_np
,
normalize
=
True
)
if
cb_pix
is
not
None
:
self
.
label_contrasted_blurred
.
setPixmap
(
cb_pix
)
if
cost_pix
is
not
None
:
self
.
label_cost_image
.
setPixmap
(
cost_pix
)
def
_np_array_to_qpixmap
(
self
,
arr
,
normalize
=
False
):
if
arr
is
None
:
return
None
arr_
=
arr
.
copy
()
if
normalize
:
mn
,
mx
=
arr_
.
min
(),
arr_
.
max
()
if
abs
(
mx
-
mn
)
<
1e-12
:
arr_
[:]
=
0
else
:
arr_
=
(
arr_
-
mn
)
/
(
mx
-
mn
)
arr_
=
np
.
clip
(
arr_
,
0
,
1
)
arr_255
=
(
arr_
*
255
).
astype
(
np
.
uint8
)
h
,
w
=
arr_255
.
shape
qimage
=
QImage
(
arr_255
.
data
,
w
,
h
,
w
,
QImage
.
Format_Grayscale8
)
return
QPixmap
.
fromImage
(
qimage
)
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
# Main Window
# Main Window
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
...
@@ -759,19 +900,25 @@ class MainWindow(QMainWindow):
...
@@ -759,19 +900,25 @@ class MainWindow(QMainWindow):
self
.
setWindowTitle
(
"
Test GUI
"
)
self
.
setWindowTitle
(
"
Test GUI
"
)
self
.
_last_loaded_pixmap
=
None
self
.
_last_loaded_pixmap
=
None
self
.
_circle_radius_for_later_use
=
0
self
.
_circle_calibrated_radius
=
6
self
.
_last_loaded_file_path
=
None
# Original main widget
# For the contrast slider
self
.
_current_clip_limit
=
0.01
# Outer widget + layout
self
.
_main_widget
=
QWidget
()
self
.
_main_widget
=
QWidget
()
self
.
_main_layout
=
QVBoxLayout
(
self
.
_main_widget
)
self
.
_main_layout
=
QHBoxLayout
(
self
.
_main_widget
)
# horizontal so we can place advanced on the right
self
.
_left_panel
=
QVBoxLayout
()
# for the image & row of buttons
self
.
_main_layout
.
addLayout
(
self
.
_left_panel
)
self
.
setCentralWidget
(
self
.
_main_widget
)
# Image view
# Image view
self
.
image_view
=
ImageGraphicsView
()
self
.
image_view
=
ImageGraphicsView
()
self
.
_
main_layout
.
addWidget
(
self
.
image_view
)
self
.
_
left_panel
.
addWidget
(
self
.
image_view
)
# Button row
# Button row
btn_layout
=
QHBoxLayout
()
btn_layout
=
QHBoxLayout
()
self
.
btn_load_image
=
QPushButton
(
"
Load Image
"
)
self
.
btn_load_image
=
QPushButton
(
"
Load Image
"
)
self
.
btn_load_image
.
clicked
.
connect
(
self
.
load_image
)
self
.
btn_load_image
.
clicked
.
connect
(
self
.
load_image
)
btn_layout
.
addWidget
(
self
.
btn_load_image
)
btn_layout
.
addWidget
(
self
.
btn_load_image
)
...
@@ -784,36 +931,41 @@ class MainWindow(QMainWindow):
...
@@ -784,36 +931,41 @@ class MainWindow(QMainWindow):
self
.
btn_clear_points
.
clicked
.
connect
(
self
.
clear_points
)
self
.
btn_clear_points
.
clicked
.
connect
(
self
.
clear_points
)
btn_layout
.
addWidget
(
self
.
btn_clear_points
)
btn_layout
.
addWidget
(
self
.
btn_clear_points
)
self
.
btn_toggle_rainbow
=
QPushButton
(
"
Toggle Rainbow
"
)
# "Advanced Settings" button
self
.
btn_toggle_rainbow
.
clicked
.
connect
(
self
.
toggle_rainbow
)
self
.
btn_advanced
=
QPushButton
(
"
Advanced Settings
"
)
btn_layout
.
addWidget
(
self
.
btn_toggle_rainbow
)
self
.
btn_advanced
.
setCheckable
(
True
)
self
.
btn_advanced
.
clicked
.
connect
(
self
.
_toggle_advanced_settings
)
btn_layout
.
addWidget
(
self
.
btn_advanced
)
# New circle editor button
self
.
_left_panel
.
addLayout
(
btn_layout
)
self
.
btn_open_editor
=
QPushButton
(
"
Open Circle Editor
"
)
self
.
btn_open_editor
.
clicked
.
connect
(
self
.
open_circle_editor
)
btn_layout
.
addWidget
(
self
.
btn_open_editor
)
self
.
_main_layout
.
addLayout
(
btn_layou
t
)
# Create advanced settings widget (hidden by defaul
t)
self
.
setCentralWidget
(
self
.
_main_widget
)
self
.
_advanced_widget
=
AdvancedSettingsWidget
(
self
)
self
.
_advanced_widget
.
hide
()
self
.
resize
(
900
,
600
)
self
.
_main_layout
.
addWidget
(
self
.
_advanced_widget
)
# We keep references for old/new
self
.
resize
(
1000
,
600
)
self
.
_old_central_widget
=
None
self
.
_old_central_widget
=
None
self
.
_editor
=
None
self
.
_editor
=
None
def
_toggle_advanced_settings
(
self
,
checked
):
if
checked
:
self
.
_advanced_widget
.
show
()
else
:
self
.
_advanced_widget
.
hide
()
# Ask Qt to re-layout the window so it can expand/shrink as needed:
self
.
adjustSize
()
def
open_circle_editor
(
self
):
def
open_circle_editor
(
self
):
"""
Removes the current central widget, replaces with circle editor.
"""
"""
Removes the current central widget, replaces with circle editor.
"""
if
not
self
.
_last_loaded_pixmap
:
if
not
self
.
_last_loaded_pixmap
:
print
(
"
No image loaded yet! Cannot open circle editor.
"
)
print
(
"
No image loaded yet! Cannot open circle editor.
"
)
return
return
# Step 1: take the old widget out of QMainWindow ownership
old_widget
=
self
.
takeCentralWidget
()
old_widget
=
self
.
takeCentralWidget
()
self
.
_old_central_widget
=
old_widget
self
.
_old_central_widget
=
old_widget
# Step 2: create the editor
init_radius
=
self
.
_circle_calibrated_radius
init_radius
=
20
editor
=
CircleEditorWidget
(
editor
=
CircleEditorWidget
(
pixmap
=
self
.
_last_loaded_pixmap
,
pixmap
=
self
.
_last_loaded_pixmap
,
init_radius
=
init_radius
,
init_radius
=
init_radius
,
...
@@ -821,31 +973,36 @@ class MainWindow(QMainWindow):
...
@@ -821,31 +973,36 @@ class MainWindow(QMainWindow):
)
)
self
.
_editor
=
editor
self
.
_editor
=
editor
# Step 3: set the new editor as the central widget
self
.
setCentralWidget
(
editor
)
self
.
setCentralWidget
(
editor
)
def
_on_circle_editor_done
(
self
,
final_radius
):
def
_on_circle_editor_done
(
self
,
final_radius
):
self
.
_circle_
radius_for_later_
us
e
=
final_radius
self
.
_circle_
calibrated_radi
us
=
final_radius
print
(
f
"
Circle Editor done. Radius =
{
final_radius
}
"
)
print
(
f
"
Circle Editor done. Radius =
{
final_radius
}
"
)
# Take the editor out
if
self
.
_last_loaded_file_path
:
cost_img
=
compute_cost_image
(
self
.
_last_loaded_file_path
,
self
.
_circle_calibrated_radius
,
clip_limit
=
self
.
_current_clip_limit
)
self
.
image_view
.
cost_image_original
=
cost_img
self
.
image_view
.
cost_image
=
cost_img
.
copy
()
self
.
image_view
.
_apply_all_guide_points_to_cost
()
self
.
image_view
.
_rebuild_full_path
()
self
.
_update_advanced_images
()
editor_widget
=
self
.
takeCentralWidget
()
editor_widget
=
self
.
takeCentralWidget
()
if
editor_widget
is
not
None
:
if
editor_widget
is
not
None
:
editor_widget
.
setParent
(
None
)
editor_widget
.
setParent
(
None
)
# Put back the old widget
if
self
.
_old_central_widget
is
not
None
:
if
self
.
_old_central_widget
is
not
None
:
self
.
setCentralWidget
(
self
.
_old_central_widget
)
self
.
setCentralWidget
(
self
.
_old_central_widget
)
self
.
_old_central_widget
=
None
self
.
_old_central_widget
=
None
# We can delete the editor if we like
if
self
.
_editor
is
not
None
:
if
self
.
_editor
is
not
None
:
self
.
_editor
.
deleteLater
()
self
.
_editor
.
deleteLater
()
self
.
_editor
=
None
self
.
_editor
=
None
# --------------------------------------------------------------------
# Existing Functions
# --------------------------------------------------------------------
def
toggle_rainbow
(
self
):
def
toggle_rainbow
(
self
):
self
.
image_view
.
toggle_rainbow
()
self
.
image_view
.
toggle_rainbow
()
...
@@ -858,15 +1015,60 @@ class MainWindow(QMainWindow):
...
@@ -858,15 +1015,60 @@ class MainWindow(QMainWindow):
)
)
if
file_path
:
if
file_path
:
self
.
image_view
.
load_image
(
file_path
)
self
.
image_view
.
load_image
(
file_path
)
cost_img
=
compute_cost_image
(
file_path
)
cost_img
=
compute_cost_image
(
file_path
,
self
.
_circle_calibrated_radius
,
clip_limit
=
self
.
_current_clip_limit
)
self
.
image_view
.
cost_image_original
=
cost_img
self
.
image_view
.
cost_image_original
=
cost_img
self
.
image_view
.
cost_image
=
cost_img
.
copy
()
self
.
image_view
.
cost_image
=
cost_img
.
copy
()
# Store a pixmap to reuse
pm
=
QPixmap
(
file_path
)
pm
=
QPixmap
(
file_path
)
if
not
pm
.
isNull
():
if
not
pm
.
isNull
():
self
.
_last_loaded_pixmap
=
pm
self
.
_last_loaded_pixmap
=
pm
self
.
_last_loaded_file_path
=
file_path
self
.
_update_advanced_images
()
def
update_contrast
(
self
,
clip_limit
):
self
.
_current_clip_limit
=
clip_limit
if
self
.
_last_loaded_file_path
:
cost_img
=
compute_cost_image
(
self
.
_last_loaded_file_path
,
self
.
_circle_calibrated_radius
,
clip_limit
=
clip_limit
)
self
.
image_view
.
cost_image_original
=
cost_img
self
.
image_view
.
cost_image
=
cost_img
.
copy
()
self
.
image_view
.
_apply_all_guide_points_to_cost
()
self
.
image_view
.
_rebuild_full_path
()
self
.
_update_advanced_images
()
def
_update_advanced_images
(
self
):
if
not
self
.
_last_loaded_pixmap
:
return
pm_np
=
self
.
_qpixmap_to_gray_float
(
self
.
_last_loaded_pixmap
)
contrasted_blurred
=
preprocess_image
(
pm_np
,
sigma
=
3
,
clip_limit
=
self
.
_current_clip_limit
)
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
):
img
=
qpix
.
toImage
()
img
=
img
.
convertToFormat
(
QImage
.
Format_ARGB32
)
ptr
=
img
.
bits
()
ptr
.
setsize
(
img
.
byteCount
())
arr
=
np
.
frombuffer
(
ptr
,
np
.
uint8
).
reshape
((
img
.
height
(),
img
.
width
(),
4
))
rgb
=
arr
[...,
:
3
].
astype
(
np
.
float32
)
gray
=
rgb
.
mean
(
axis
=
2
)
/
255.0
return
gray
def
export_path
(
self
):
def
export_path
(
self
):
full_xy
=
self
.
image_view
.
get_full_path_xy
()
full_xy
=
self
.
image_view
.
get_full_path_xy
()
if
not
full_xy
:
if
not
full_xy
:
...
...
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