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
7418827e
Commit
7418827e
authored
6 months ago
by
Christian
Browse files
Options
Downloads
Patches
Plain Diff
Added rainbow toggle button functionality for visualizing point order
parent
e7488d98
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
+70
-30
70 additions, 30 deletions
GUI_draft_live.py
with
70 additions
and
30 deletions
GUI_draft_live.py
+
70
−
30
View file @
7418827e
...
@@ -126,6 +126,19 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -126,6 +126,19 @@ class ImageGraphicsView(QGraphicsView):
self
.
cost_image_original
=
None
self
.
cost_image_original
=
None
self
.
cost_image
=
None
self
.
cost_image
=
None
# Rainbow toggle
self
.
_rainbow_enabled
=
True
def
set_rainbow_enabled
(
self
,
enabled
:
bool
):
"""
Enable/disable rainbow mode, then rebuild the path.
"""
self
.
_rainbow_enabled
=
enabled
self
.
_rebuild_full_path
()
def
toggle_rainbow
(
self
):
"""
Flip the rainbow mode and rebuild path.
"""
self
.
_rainbow_enabled
=
not
self
.
_rainbow_enabled
self
.
_rebuild_full_path
()
# --------------------------------------------------------------------
# --------------------------------------------------------------------
# LOADING
# LOADING
# --------------------------------------------------------------------
# --------------------------------------------------------------------
...
@@ -179,7 +192,7 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -179,7 +192,7 @@ class ImageGraphicsView(QGraphicsView):
self
.
_revert_cost_to_original
()
self
.
_revert_cost_to_original
()
if
not
self
.
_full_path_xy
:
if
not
self
.
_full_path_xy
:
# If there's no existing path built,
we
just insert
normally
# If there's no existing path built, just insert
at the end
self
.
_insert_anchor_point
(
-
1
,
x_clamped
,
y_clamped
,
self
.
_insert_anchor_point
(
-
1
,
x_clamped
,
y_clamped
,
label
=
""
,
removable
=
True
,
z_val
=
1
,
radius
=
self
.
dot_radius
)
label
=
""
,
removable
=
True
,
z_val
=
1
,
radius
=
self
.
dot_radius
)
else
:
else
:
...
@@ -193,8 +206,8 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -193,8 +206,8 @@ class ImageGraphicsView(QGraphicsView):
def
_insert_anchor_between_subpath
(
self
,
x_new
,
y_new
):
def
_insert_anchor_between_subpath
(
self
,
x_new
,
y_new
):
"""
Find the subpath bounding (x_new,y_new) and insert the new anchor accordingly.
"""
"""
Find the subpath bounding (x_new,y_new) and insert the new anchor accordingly.
"""
# If no path, fallback
if
not
self
.
_full_path_xy
:
if
not
self
.
_full_path_xy
:
# Fallback if no path
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
return
return
...
@@ -214,22 +227,18 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -214,22 +227,18 @@ class ImageGraphicsView(QGraphicsView):
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
return
return
# 2) Identify bounding anchors by walking left / right
def
approx_equal
(
xa
,
ya
,
xb
,
yb
,
tol
=
1e-3
):
def
approx_equal
(
xa
,
ya
,
xb
,
yb
,
tol
=
1e-3
):
return
(
abs
(
xa
-
xb
)
<
tol
)
and
(
abs
(
ya
-
yb
)
<
tol
)
return
(
abs
(
xa
-
xb
)
<
tol
)
and
(
abs
(
ya
-
yb
)
<
tol
)
def
is_anchor
(
coord
):
def
is_anchor
(
coord
):
cx
,
cy
=
coord
cx
,
cy
=
coord
# check if (cx,cy) is approx any anchor in self.anchor_points
for
(
ax
,
ay
)
in
self
.
anchor_points
:
for
(
ax
,
ay
)
in
self
.
anchor_points
:
if
approx_equal
(
ax
,
ay
,
cx
,
cy
):
if
approx_equal
(
ax
,
ay
,
cx
,
cy
):
return
True
return
True
return
False
return
False
# 2) Walk left
left_anchor_pt
=
None
left_anchor_pt
=
None
right_anchor_pt
=
None
# walk left
iL
=
best_idx
iL
=
best_idx
while
iL
>=
0
:
while
iL
>=
0
:
px
,
py
=
self
.
_full_path_xy
[
iL
]
px
,
py
=
self
.
_full_path_xy
[
iL
]
...
@@ -238,7 +247,8 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -238,7 +247,8 @@ class ImageGraphicsView(QGraphicsView):
break
break
iL
-=
1
iL
-=
1
# walk right
# 3) Walk right
right_anchor_pt
=
None
iR
=
best_idx
iR
=
best_idx
while
iR
<
len
(
self
.
_full_path_xy
):
while
iR
<
len
(
self
.
_full_path_xy
):
px
,
py
=
self
.
_full_path_xy
[
iR
]
px
,
py
=
self
.
_full_path_xy
[
iR
]
...
@@ -247,12 +257,17 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -247,12 +257,17 @@ class ImageGraphicsView(QGraphicsView):
break
break
iR
+=
1
iR
+=
1
# fallback if missing anchors
if
not
left_anchor_pt
or
not
right_anchor_pt
:
if
not
left_anchor_pt
or
not
right_anchor_pt
:
# If we can't find bounding anchors => fallback
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
return
return
# 3) Find which anchor_points indices correspond to left_anchor_pt, right_anchor_pt
# If they happen to be the same anchor, fallback
if
left_anchor_pt
==
right_anchor_pt
:
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
return
# 4) Map these anchor coords to indices in self.anchor_points
left_idx
=
None
left_idx
=
None
right_idx
=
None
right_idx
=
None
for
i
,
(
ax
,
ay
)
in
enumerate
(
self
.
anchor_points
):
for
i
,
(
ax
,
ay
)
in
enumerate
(
self
.
anchor_points
):
...
@@ -262,23 +277,14 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -262,23 +277,14 @@ class ImageGraphicsView(QGraphicsView):
right_idx
=
i
right_idx
=
i
if
left_idx
is
None
or
right_idx
is
None
:
if
left_idx
is
None
or
right_idx
is
None
:
# fallback
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
self
.
_insert_anchor_point
(
-
1
,
x_new
,
y_new
)
return
return
# We want the new anchor to be inserted right after left_idx,
# 5) Insert new point in between
# so that the subpath between left_idx and right_idx
# is effectively subdivided.
# This ensures anchor_points = [..., left_anchor, new_point, ..., right_anchor, ...]
insert_idx
=
right_idx
# But if left_idx < right_idx => we do insert_idx=left_idx+1
# in case we want them consecutive.
if
left_idx
<
right_idx
:
if
left_idx
<
right_idx
:
insert_idx
=
left_idx
+
1
insert_idx
=
left_idx
+
1
else
:
else
:
# means the path might be reversed, or there's some tricky indexing
insert_idx
=
right_idx
+
1
# We'll just do min or max
insert_idx
=
max
(
right_idx
,
left_idx
)
self
.
_insert_anchor_point
(
insert_idx
,
x_new
,
y_new
,
label
=
""
,
removable
=
True
,
self
.
_insert_anchor_point
(
insert_idx
,
x_new
,
y_new
,
label
=
""
,
removable
=
True
,
z_val
=
1
,
radius
=
self
.
dot_radius
)
z_val
=
1
,
radius
=
self
.
dot_radius
)
...
@@ -320,7 +326,6 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -320,7 +326,6 @@ class ImageGraphicsView(QGraphicsView):
# PATH BUILDING
# PATH BUILDING
# --------------------------------------------------------------------
# --------------------------------------------------------------------
def
_rebuild_full_path
(
self
):
def
_rebuild_full_path
(
self
):
"""
Compute subpaths between anchors, smooth them, store all coords, display all of them.
"""
# Clear old path visuals
# Clear old path visuals
for
item
in
self
.
full_path_points
:
for
item
in
self
.
full_path_points
:
self
.
scene
.
removeItem
(
item
)
self
.
scene
.
removeItem
(
item
)
...
@@ -338,7 +343,7 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -338,7 +343,7 @@ class ImageGraphicsView(QGraphicsView):
if
i
==
0
:
if
i
==
0
:
big_xy
.
extend
(
sub_xy
)
big_xy
.
extend
(
sub_xy
)
else
:
else
:
#
a
void repeating the shared anchor
#
A
void repeating the shared anchor
if
len
(
sub_xy
)
>
1
:
if
len
(
sub_xy
)
>
1
:
big_xy
.
extend
(
sub_xy
[
1
:])
big_xy
.
extend
(
sub_xy
[
1
:])
...
@@ -348,17 +353,32 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -348,17 +353,32 @@ class ImageGraphicsView(QGraphicsView):
smoothed
=
savgol_filter
(
arr_xy
,
window_length
=
7
,
polyorder
=
1
,
axis
=
0
)
smoothed
=
savgol_filter
(
arr_xy
,
window_length
=
7
,
polyorder
=
1
,
axis
=
0
)
big_xy
=
smoothed
.
tolist
()
big_xy
=
smoothed
.
tolist
()
#
We now s
tore the entire path
in _full_path_xy
#
S
tore the entire path
self
.
_full_path_xy
=
big_xy
[:]
self
.
_full_path_xy
=
big_xy
[:]
# Display ALL points
# Draw the path
for
(
px
,
py
)
in
big_xy
:
n_points
=
len
(
big_xy
)
path_item
=
LabeledPointItem
(
px
,
py
,
label
=
""
,
radius
=
self
.
path_radius
,
for
i
,
(
px
,
py
)
in
enumerate
(
big_xy
):
color
=
Qt
.
magenta
,
removable
=
False
,
z_value
=
0
)
if
n_points
>
1
:
fraction
=
i
/
(
n_points
-
1
)
else
:
fraction
=
0
# If rainbow is on, use the rainbow color; else use a constant color
if
self
.
_rainbow_enabled
:
color
=
self
.
_rainbow_color
(
fraction
)
else
:
color
=
Qt
.
red
path_item
=
LabeledPointItem
(
px
,
py
,
label
=
""
,
radius
=
self
.
path_radius
,
color
=
color
,
removable
=
False
,
z_value
=
0
)
self
.
full_path_points
.
append
(
path_item
)
self
.
full_path_points
.
append
(
path_item
)
self
.
scene
.
addItem
(
path_item
)
self
.
scene
.
addItem
(
path_item
)
# Keep S/E on top
# Keep S/E on top
if they have labels
for
p_item
in
self
.
point_items
:
for
p_item
in
self
.
point_items
:
if
p_item
.
_text_item
:
if
p_item
.
_text_item
:
p_item
.
setZValue
(
100
)
p_item
.
setZValue
(
100
)
...
@@ -381,6 +401,17 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -381,6 +401,17 @@ class ImageGraphicsView(QGraphicsView):
return
[]
return
[]
return
[(
c
,
r
)
for
(
r
,
c
)
in
path_rc
]
return
[(
c
,
r
)
for
(
r
,
c
)
in
path_rc
]
def
_rainbow_color
(
self
,
fraction
):
"""
fraction: 0..1
Returns a QColor whose hue is fraction * 300 (for example),
at full saturation and full brightness.
"""
hue
=
int
(
300
*
fraction
)
# up to 300 degrees
saturation
=
255
value
=
255
return
QColor
.
fromHsv
(
hue
,
saturation
,
value
)
# --------------------------------------------------------------------
# --------------------------------------------------------------------
# MOUSE EVENTS
# MOUSE EVENTS
# --------------------------------------------------------------------
# --------------------------------------------------------------------
...
@@ -403,7 +434,7 @@ class ImageGraphicsView(QGraphicsView):
...
@@ -403,7 +434,7 @@ class ImageGraphicsView(QGraphicsView):
self
.
viewport
().
setCursor
(
Qt
.
ClosedHandCursor
)
self
.
viewport
().
setCursor
(
Qt
.
ClosedHandCursor
)
return
return
else
:
else
:
#
n
o anchor => we
'll
add a new point
#
N
o anchor => we
may
add a new point
self
.
setDragMode
(
QGraphicsView
.
ScrollHandDrag
)
self
.
setDragMode
(
QGraphicsView
.
ScrollHandDrag
)
self
.
viewport
().
setCursor
(
Qt
.
ClosedHandCursor
)
self
.
viewport
().
setCursor
(
Qt
.
ClosedHandCursor
)
...
@@ -586,10 +617,19 @@ class MainWindow(QMainWindow):
...
@@ -586,10 +617,19 @@ 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
)
# Toggle Rainbow
self
.
btn_toggle_rainbow
=
QPushButton
(
"
Toggle Rainbow
"
)
self
.
btn_toggle_rainbow
.
clicked
.
connect
(
self
.
toggle_rainbow
)
btn_layout
.
addWidget
(
self
.
btn_toggle_rainbow
)
main_layout
.
addLayout
(
btn_layout
)
main_layout
.
addLayout
(
btn_layout
)
self
.
setCentralWidget
(
main_widget
)
self
.
setCentralWidget
(
main_widget
)
self
.
resize
(
900
,
600
)
self
.
resize
(
900
,
600
)
def
toggle_rainbow
(
self
):
"""
Toggle the rainbow mode in the view.
"""
self
.
image_view
.
toggle_rainbow
()
def
load_image
(
self
):
def
load_image
(
self
):
options
=
QFileDialog
.
Options
()
options
=
QFileDialog
.
Options
()
file_path
,
_
=
QFileDialog
.
getOpenFileName
(
file_path
,
_
=
QFileDialog
.
getOpenFileName
(
...
...
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