Skip to content

Commit e6fe740

Browse files
committed
Changing how non-existant masks are handled, starting to integrate bspline code
1 parent 3ba9cde commit e6fe740

15 files changed

+92
-104
lines changed

Image_based/BaseStatsImage.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ def __init__(self, fname_mask_image, fname_calculated=None, fname_debug=None, b_
5555
if exists(fname_mask_image):
5656
mask_image_rgb = cv2.imread(fname_mask_image)
5757
else:
58-
self.mask_image = np.zeros((8, 8), dtype=np.uint8)
59-
return
60-
58+
mask_image_rgb = np.zeros((640, 480), dtype=np.uint8)
59+
mask_image_rgb[200:230, 10:260] = 1
60+
6161
if len(mask_image_rgb.shape) == 3:
6262
self.mask_image = cv2.cvtColor(mask_image_rgb, cv2.COLOR_BGR2GRAY)
6363
else:

Image_based/HandleFileNames.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -321,15 +321,15 @@ def get_mask_name(self, path, index, b_add_tag=True):
321321
return im_name
322322

323323
def loop_images(self):
324-
""" A generator that loops over all of the images and generates an index for each
324+
""" a generator that loops over all of the images and generates an index for each
325325
The index can be passed to get_image_name to get the actual image name
326326
@return a tuple that can be used to get the image name"""
327327
for i, _ in enumerate(self.sub_dirs):
328328
for j, _ in enumerate(self.image_names[i]):
329329
yield i, j
330330

331331
def loop_masks(self, mask_type=""):
332-
""" A generator that loops over all of the masks and generates an index for each
332+
""" a generator that loops over all of the masks and generates an index for each
333333
The index can be passed to get_mask_name to get the actual mask name
334334
@param mask_type: Optional parameter; if set, return only masks of the given name (eg trunk)
335335
@return a tuple that can be used to get the mask name"""

Image_based/bezier_cyl_2d.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#!/usr/bin/env python3
22

3-
# A 2D quadratic Bezier with additional radius information
3+
# a 2D quadratic Bezier with additional radius information
44
# - also keeps primary orientation (left, right or up, down)
55
# - Assumes this is a curve in the image; all coordinates are in image coordinates
66
#
77
# Primary code:
8-
# A bezier curve is defined by f(t)->[x,y] for t going from 0 to 1
8+
# a bezier curve is defined by f(t)->[x,y] for t going from 0 to 1
99
# Currently a fixed radius along the cylinder/tube
1010
# Using the tangent and the normal (orthogonal to tangent) we can define rectangles
1111
# 1) Rectangles that follow the axis of the curve and cover the interior of the curve

Image_based/extract_curves.py

-4
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ def __init__(self, fname_rgb_image, fname_edge_image, fname_mask_image, params=N
3939
fname_debug=fname_debug,
4040
b_recalc=b_recalc)
4141

42-
if not exists(fname_mask_image):
43-
self.params = None
44-
return
45-
4642
# List o pairs (t, plus/minus)
4743
self.left_curve = []
4844
self.right_curve = []

Image_based/fit_bezier_cyl_2d.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def setup_least_squares(self, ts):
3333
"""Setup the least squares approximation - ts is the number of constraints to add, also
3434
puts in a copule constraints to keep end points where they are
3535
@param ts - t values to use
36-
@returns A, B for Ax = b """
36+
@returns a, b for Ax = b """
3737
# Set up the matrix - include the 3 current points plus the centers of the mask
3838
a_constraints = np.zeros((len(ts) + 3, 3))
3939
ts_constraints = np.zeros((len(ts) + 3))
@@ -51,7 +51,7 @@ def setup_least_squares(self, ts):
5151

5252
def extract_least_squares(self, a_constraints, b_rhs):
5353
""" Do the actual Ax = b and keep horizontal/vertical end points
54-
@param a_constraints the A of Ax = b
54+
@param a_constraints the a of Ax = b
5555
@param b_rhs the b of Ax = b
5656
@returns fit error L0 norm"""
5757
if a_constraints.shape[0] < 3:

Image_based/fit_bezier_cyl_2d_edge.py

-4
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,6 @@ def __init__(self, fname_rgb_image, fname_edge_image, fname_mask_image, fname_ca
8484
# This is the curve that will be fit to the edge
8585
self.bezier_crv_fit_to_edge = None
8686

87-
if not exists(fname_mask_image):
88-
self.params = None
89-
return
90-
9187
# Copy params used in fit mask and add the new ones
9288
self.params = {}
9389
for k in self.mask_crv.params.keys():

Image_based/fit_bezier_cyl_2d_mask.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ def __init__(self, fname_mask_image, fname_calculated=None, fname_debug=None, pa
3434
# First do the stats - this also reads the image in
3535
self.stats_dict = BaseStatsImage(fname_mask_image, fname_calculated, fname_debug, b_recalc)
3636

37-
if not exists(fname_mask_image):
38-
self.params = None
39-
return
40-
4137
# Now initialize bezier curve with info from stats - no need to cache this because it's so light-weight
4238
p0 = self.stats_dict.stats_dict["lower_left"]
4339
p2 = self.stats_dict.stats_dict["upper_right"]
@@ -186,7 +182,7 @@ def fit_bezier_crv_to_mask(bezier_crv, im_mask, params):
186182
return fit_bezier_crv.get_copy_of_2d_bezier_curve()
187183

188184
def score_mask_fit(self, im_mask):
189-
""" A modified intersection over union that discounts pixels along the bezier cylinder mask
185+
""" a modified intersection over union that discounts pixels along the bezier cylinder mask
190186
@param im_mask - the mask image
191187
"""
192188

Image_based/line_seg_2d.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class LineSeg2D:
1010
def __init__(self, p1, p2):
11-
""" Line segment with Ax + By + C form for closest point
11+
""" Line segment with Ax + By + c form for closest point
1212
@param p1: Pt 1
1313
@param p2: Pt 2"""
1414

@@ -22,10 +22,10 @@ def __init__(self, p1, p2):
2222

2323
@staticmethod
2424
def line(p1, p2):
25-
""" A line in implicit coordinates
25+
""" a line in implicit coordinates
2626
@param p1 end point one
2727
@param p2 end point two
28-
@return A x + B y + C"""
28+
@return a x + b y + c"""
2929
A = (p1[1] - p2[1])
3030
B = (p2[0] - p1[0])
3131
C = (p1[0] * p2[1] - p2[0] * p1[1])
@@ -37,14 +37,14 @@ def intersection(L1, L2):
3737
@param L1 - line one in implicit coords
3838
@param L2 - line two in implicit coords
3939
@return x, y if intersection point, None otherwise"""
40-
D = L1.A * L2.B - L1.B * L2.A
41-
Dx = L1.C * L2.B - L1.B * L2.C
42-
Dy = L1.A * L2.C - L1.C * L2.A
40+
D = L1.a * L2.b - L1.b * L2.a
41+
Dx = L1.c * L2.b - L1.b * L2.c
42+
Dy = L1.a * L2.c - L1.c * L2.a
4343
if abs(D) > 1e-10:
4444
x = -Dx / D
4545
y = -Dy / D
46-
check1 = L1.A * x + L1.B * y + L1.C
47-
check2 = L2.A * x + L2.B * y + L2.C
46+
check1 = L1.a * x + L1.b * y + L1.c
47+
check2 = L2.a * x + L2.b * y + L2.c
4848
if not np.isclose(check1, 0.0) or not np.isclose(check2, 0.0):
4949
raise ValueError("LineSeg2D: Making line, pts not on line")
5050
return x, y
@@ -53,8 +53,8 @@ def intersection(L1, L2):
5353

5454
def projection(self, pt):
5555
"""Project the point onto the line and return the t value
56-
A ((1-t)p1x + t p2x) + B ((1-t)p1y + t p2y) + C = 0
57-
t (A(p2x-p1x) + B(p2y-p1y)) = -C - A (p1x + p2x) - B(p1y + p2y)
56+
a ((1-t)p1x + t p2x) + b ((1-t)p1y + t p2y) + c = 0
57+
t (a(p2x-p1x) + b(p2y-p1y)) = -c - a (p1x + p2x) - b(p1y + p2y)
5858
@param pt - pt to project
5959
@return t of projection point"""
6060

MySliders.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from PyQt5.QtWidgets import QHBoxLayout, QSlider, QWidget, QLabel, QPushButton
55

66

7-
# A helper class that implements a slider with given start and end float value; displays values
7+
# a helper class that implements a slider with given start and end float value; displays values
88
class SliderFloatDisplay(QWidget):
99
gui = None
1010

fit_routines/b_spline_curve_fit.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from matplotlib import pyplot as plt
88

99
from tree_geometry.b_spline_curve import BSplineCurve
10-
from .params import fit_params
10+
from params import fit_params
1111

1212
logger = logging.getLogger("b_spline_fit")
1313
logger.setLevel(level=logging.DEBUG)

sketch_curves_gui/Draw_spline_3D.py

+18-13
Original file line numberDiff line numberDiff line change
@@ -179,29 +179,34 @@ def draw_crv_3d(self, crv_3d):
179179
GL.glNormal3d(n[0], n[1], n[2])
180180
GL.glEnd()
181181

182-
def bind_texture(self, rgb_image, mask_image, edge_image, flow_image, depth_image):
183-
print(f"Binding texture {rgb_image.shape} {edge_image.shape}")
182+
def bind_texture(self, images):
183+
rgb_image = images["rgb"]
184184
self.aspect_ratio = rgb_image.shape[0] / rgb_image.shape[1]
185185
self.im_size = (rgb_image.shape[1], rgb_image.shape[0])
186186

187-
#im_check = np.ones((im_size, im_size, 3), dtype=np.uint8)
188-
#im_check[:,:] *= 64
189-
#im_check[:,:,0] *= 128
190-
#im_check[:,:,0] *= 192
191-
192187
im_size = 512
193188
if rgb_image.shape[0] > 1024:
194189
im_size = 1024
195190
im_sq = cv2.resize(rgb_image, (im_size, im_size))
196191

197-
im_sq_mask = cv2.cvtColor(cv2.resize(mask_image, (im_size, im_size)), cv2.COLOR_GRAY2RGB)
198-
im_sq_edge = cv2.cvtColor(cv2.resize(edge_image, (im_size, im_size)), cv2.COLOR_GRAY2RGB)
199-
if flow_image is not None:
200-
im_sq_flow = cv2.resize(flow_image, (im_size, im_size))
192+
if "mask" in images:
193+
im_sq_mask = cv2.cvtColor(cv2.resize(images["mask"], (im_size, im_size)), cv2.COLOR_GRAY2RGB)
194+
else:
195+
im_sq_mask = im_sq
196+
if "edge" in images:
197+
if len(images["edge"].shape) == 3:
198+
images["edge"] = cv2.cvtColor(images["edge"], cv2.COLOR_BGR2GRAY)
199+
im_sq_edge = cv2.cvtColor(cv2.resize(images["edge"], (im_size, im_size)), cv2.COLOR_GRAY2RGB)
200+
else:
201+
im_sq_edge = im_sq
202+
203+
if "flow" in images:
204+
im_sq_flow = cv2.resize(images["flow"], (im_size, im_size))
201205
else:
202206
im_sq_flow = None
203-
if depth_image is not None:
204-
im_sq_depth = cv2.resize(depth_image, (im_size, im_size))
207+
208+
if "depth" in images:
209+
im_sq_depth = cv2.resize(images["depth"], (im_size, im_size))
205210
else:
206211
im_sq_depth = None
207212

sketch_curves_gui/Sketch_curves_main_window.py

+21-26
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
sys.path.insert(0, os.path.abspath('./Image_based'))
77
sys.path.insert(0, os.path.abspath('./Utilities'))
88
sys.path.insert(0, os.path.abspath('./sketch_curves_gui'))
9+
sys.path.insert(0, os.path.abspath('./fit_routines'))
910
sys.path.insert(0, os.path.abspath('../'))
1011
sys.path.insert(0, os.path.abspath('../Image_based'))
1112
sys.path.insert(0, os.path.abspath('../Utilities'))
1213
sys.path.insert(0, os.path.abspath('../sketch_curves_gui'))
14+
sys.path.insert(0, os.path.abspath('../fit_routines'))
1315
from os.path import exists
1416

1517
# Get OpenGL
@@ -29,6 +31,7 @@
2931

3032
from sketch_curves_gui.Sketches_for_curves import SketchesForCurves
3133

34+
from b_spline_curve_fit import BSplineCurveFit
3235

3336
class SketchCurvesMainWindow(QMainWindow):
3437
def __init__(self):
@@ -77,8 +80,10 @@ def _init_left_layout_(self):
7780
path_names_layout = QGridLayout()
7881
path_names_layout.setColumnMinimumWidth(0, 40)
7982
path_names_layout.setColumnMinimumWidth(1, 200)
80-
self.path_name = QLineEdit("/Users/cindygrimm/PycharmProjects/treefitting/Image_based/data/EnvyTree/")
81-
self.file_name = QLineEdit("envy_fnames.json")
83+
# self.path_name = QLineEdit("/Users/cindygrimm/PycharmProjects/treefitting/Image_based/data/EnvyTree/")
84+
# self.file_name = QLineEdit("envy_fnames.json")
85+
self.path_name = QLineEdit("/Users/cindygrimm/PycharmProjects/treefitting/Image_based/data/")
86+
self.file_name = QLineEdit("forcindy_bspline.json")
8287
self.sub_dir_number = SliderIntDisplay("Sub dir", 0, 10, 0)
8388
self.image_number = SliderIntDisplay("Image", 0, 10, 0)
8489
self.mask_number = SliderIntDisplay("Mask", 0, 3, 0)
@@ -500,7 +505,7 @@ def set_crv(self, params):
500505

501506
depth_fname = self.handle_filenames.get_depth_image_name(index=self.last_index, b_add_tag=True)
502507
if exists(depth_fname):
503-
depth_fname_calculate = self.handle_filenames.get_mask_name(index=self.last_index, b_add_tag=False)
508+
depth_fname_calculate = self.handle_filenames.get_mask_name(index=self.last_index, b_calculate_path=True, b_add_tag=False)
504509
depth_fname_debug = self.handle_filenames.get_mask_name(index=self.last_index, b_debug_path=True, b_add_tag=False)
505510
params = {"camera_width_angle": self.horizontal_angle.value()}
506511
self.fit_crv_3d = FitBezierCyl3dDepth(depth_fname, self.crv.bezier_crv_fit_to_edge,
@@ -517,31 +522,21 @@ def read_images(self):
517522
b_get_image, self.last_index = self.reset_file_menus()
518523
print(f" masks {self.handle_filenames.mask_ids[self.last_index[0]][self.last_index[1]][self.last_index[2]]}")
519524
if b_get_image:
520-
image_flow_name = self.handle_filenames.get_flow_image_name(index=self.last_index, b_add_tag=True)
521-
image_depth_name = self.handle_filenames.get_depth_image_name(index=self.last_index, b_add_tag=True)
522-
523-
if exists(image_flow_name):
524-
image_flow = cv2.imread(image_flow_name)
525-
else:
526-
image_flow = None
527-
528-
if exists(image_depth_name):
529-
image_depth = cv2.imread(image_depth_name)
530-
else:
531-
image_depth = None
525+
self.image_names = {}
526+
self.image_names["rgb"] = self.handle_filenames.get_image_name(index=self.last_index, b_add_tag=True)
527+
self.image_names["mask"] = self.handle_filenames.get_mask_name(index=self.last_index, b_add_tag=True)
528+
self.image_names["edge"] = self.handle_filenames.get_edge_name(index=self.last_index, b_add_tag=True)
529+
self.image_names["flow"] = self.handle_filenames.get_flow_image_name(index=self.last_index, b_add_tag=True)
530+
self.image_names["depth"] = self.handle_filenames.get_depth_image_name(index=self.last_index, b_add_tag=True)
531+
532+
self.images = {}
533+
for k, v in self.image_names.items():
534+
if exists(v):
535+
self.images[k] = cv2.imread(v)
532536

533537
self.set_crv(params=None)
534-
if self.crv.mask_crv.stats_dict.mask_image.size < 256:
535-
img_mask = np.zeros((self.crv.image_rgb.shape[0],
536-
self.crv.image_rgb.shape[1]), np.uint8)
537-
else:
538-
img_mask = self.crv.mask_crv.stats_dict.mask_image
539-
540-
self.glWidget.bind_texture(self.crv.image_rgb,
541-
img_mask,
542-
self.crv.image_edge,
543-
image_flow,
544-
image_depth)
538+
539+
self.glWidget.bind_texture(self.images)
545540
self.set_corners()
546541
self.redraw_self()
547542
self.in_read_images = False

tree_geometry/b_spline_curve.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class BSplineCurve(object):
2727
cubic=3,
2828
)
2929
# uniform knot vector only
30-
# General Matrix Representations for B-Splines, Kaihuai Qin
30+
# General Matrix Representations for b-Splines, Kaihuai Qin
3131
# each matrix column represents a series of coeffs of increasing degree for a basis function
3232
basis_matrix_dict = {
3333
0: np.array([1]),
@@ -95,7 +95,7 @@ def from_existing(existing):
9595
:param existing: existing spline
9696
"""
9797
return BSplineCurve(
98-
ctrl_pts = deepcopy(existing.ctrl_pts),
98+
ctrl_pts = existing.ctrl_pts, # Deep copy in init function
9999
dim = existing.dim,
100100
degree = existing.degree,
101101
figax = (existing.fig, existing.ax))

0 commit comments

Comments
 (0)