Skip to content

Commit 7f4b788

Browse files
committed
plane detector - simplify
1 parent aae1c9d commit 7f4b788

File tree

2 files changed

+78
-173
lines changed

2 files changed

+78
-173
lines changed

wrappers/python/applications/planes/src/plane_detector.py

Lines changed: 37 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
import cv2 as cv
2323

2424

25-
#from scipy import interpolate
26-
2725
# importing common Use modules
2826
sys.path.append(r'wrappers\python\applications\utils\src')
2927
from logger import log
@@ -53,7 +51,6 @@ def __init__(self, detect_type = 'p'):
5351
self.plane_center = None # tvec
5452
#self.corner_ind = [0, 10, 40, 50] # corner of the rectnagle for the projection
5553
self.rect_3d = None # roi but projected on 3D
56-
5754

5855
# params
5956
self.MIN_SPLIT_SIZE = 32
@@ -62,6 +59,17 @@ def __init__(self, detect_type = 'p'):
6259
# help variable
6360
self.ang_vec = np.zeros((3,1)) # help variable
6461

62+
def init_image(self, img = None):
63+
"load image"
64+
if img is None:
65+
log.info('No image provided')
66+
return False
67+
68+
self.img = img
69+
h,w = img.shape[:2]
70+
self.frame_size = (w,h)
71+
return True
72+
6573
def init_roi(self, test_type = 1):
6674
"load the test case"
6775
roi = [0,0,self.frame_size[0],self.frame_size[1]]
@@ -152,33 +160,6 @@ def compute_img3d(self, img = None):
152160
self.img_xyz = imgXYZ
153161
return imgXYZ
154162

155-
def detect_pose_in_chessboard(self):
156-
# chess board pose extimation
157-
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
158-
objp = np.zeros((6*7,3), np.float32)
159-
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
160-
axis = np.float32([[3,0,0], [0,3,0], [0,0,-3]]).reshape(-1,3)
161-
if len(self.img.shape) > 2:
162-
gray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
163-
else:
164-
gray = self.img
165-
flags_cv = cv.CALIB_CB_ADAPTIVE_THRESH + cv.CALIB_CB_FAST_CHECK #+ cv.CALIB_CB_NORMALIZE_IMAGE
166-
ret, corners = cv.findChessboardCorners(gray, (7,6), flags = flags_cv)
167-
#ret, corners = cv.findChessboardCornersSB(gray, (7,6))
168-
if ret == True:
169-
corners = cv.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
170-
else:
171-
print('Failed to find points')
172-
return np.zeros((1,7))
173-
# Find the rotation and translation vectors.
174-
ret,rvecs, tvecs = cv.solvePnP(objp, corners, self.cam_matrix, self.cam_distort)
175-
# transfer to pose
176-
R, _ = cv.Rodrigues(rvecs)
177-
avec = rotationMatrixToEulerAngles(R)
178-
pose = np.hstack((tvecs.flatten(), avec.flatten(), 3))
179-
print('Chess pose : ', pose)
180-
return [pose]
181-
182163
def check_error(self, xyz1_mtrx, vnorm):
183164
"checking the error norm"
184165
err = np.dot(xyz1_mtrx, vnorm)
@@ -219,8 +200,6 @@ def convert_roi_to_points(self, img_roi, point_num = 30, step_size = 0):
219200
step_size = np.maximum(1, np.int32(valid_point_num/point_num))
220201
ii = ii[::step_size]
221202

222-
223-
224203
# plane params - using only valid
225204
z = img_roi[ii]
226205
xyz_matrix = self.matrix_dir[ii,:]
@@ -246,27 +225,6 @@ def convert_roi_to_points(self, img_roi, point_num = 30, step_size = 0):
246225
#self.plane_center = xyz_center.flatten()
247226

248227
return xyz_matrix
249-
250-
def convert_roi_params_to_pose(self, roi_params):
251-
"converting params to the pose vector"
252-
tvec = roi_params['tvec'].reshape((1,-1))
253-
vnorm = roi_params['vnorm'] # 4x1 vector
254-
#rvec = vnorm[:3].reshape((1,-1))
255-
#rvec = rvec/np.linalg.norm(rvec)
256-
257-
rvec = vnorm.flatten() #reshape((-1,1))
258-
#rvec[3] = 0 # kill DC
259-
rvec = rvec/np.linalg.norm(rvec)
260-
261-
#R = Rot.from_quat(rvec).as_matrix()
262-
#R = Rot.from_rotvec(rvec).as_matrix()
263-
#avec = Rot.from_matrix(R).as_euler('zyx',degrees=True)
264-
#self.ang_vec= avec
265-
266-
levl = 0.1*tvec[0,2]
267-
pose_norm = np.hstack((tvec, rvec.reshape((1,-1)),[[levl]]))
268-
#log.info('roi to pose')
269-
return pose_norm #.flatten()
270228

271229
def convert_plane_params(self, plane_equation):
272230
"convert plane params to rvec"
@@ -279,7 +237,7 @@ def convert_plane_params(self, plane_equation):
279237
normal = plane_equation #np.array([plane_equation[0], plane_equation[1], plane_equation[2]])
280238
normal_norm = np.linalg.norm(normal)
281239
if normal_norm == 0:
282-
print("Error: Zero norm for plane normal vector.")
240+
log.error("Error: Zero norm for plane normal vector.")
283241
return None
284242
normal = normal / normal_norm
285243

@@ -300,13 +258,19 @@ def convert_plane_params(self, plane_equation):
300258

301259
return rvec
302260

303-
def convert_plane_to_rvec(self, normal):
304-
# Convert plane normal to rotation vector
305-
z_axis = np.array([0, 0, 1])
306-
rotation_matrix = cv.Rodrigues(np.cross(z_axis, normal))[0]
307-
rvec, _ = cv.Rodrigues(rotation_matrix)
308-
309-
return rvec
261+
def convert_plane_params_to_pose(self, plane_params = None, plane_center = None):
262+
"converting params of the plane to the pose vector"
263+
264+
plane_params = self.plane_params if plane_params is None else plane_params[:3].flatten()
265+
plane_center = self.plane_center if plane_center is None else plane_center[:3].flatten()
266+
267+
tvec = plane_center.reshape((1,-1))
268+
rvec = plane_params.reshape((1,-1)) #reshape((-1,1))
269+
rvec = rvec/np.linalg.norm(rvec.flatten())
270+
271+
pose_norm = np.hstack((tvec, rvec))
272+
#log.info('roi to pose')
273+
return pose_norm #.flatten()
310274

311275
def fit_plane_init(self):
312276
"prepares data for real time fit a*x+b*y+c = z"
@@ -395,30 +359,6 @@ def fit_plane_svd(self, img_roi):
395359
#log.info(f'Plane : {self.plane_params}, error {img_std:.3f}, step {step_size}')
396360

397361
return img_mean, img_std
398-
399-
def fit_plane(self, roi):
400-
"computes normal for the specifric roi and evaluates error"
401-
402-
# roi converted to points with step size on the grid
403-
xyz_matrix = self.convert_roi_to_points(roi, step_size = 0)
404-
405-
# using svd to make the fit
406-
tvec = xyz_matrix[:,:3].mean(axis=0)
407-
xyz1_matrix = xyz_matrix - tvec
408-
U, S, Vh = np.linalg.svd(xyz_matrix, full_matrices=True)
409-
ii = np.argmin(S)
410-
vnorm = Vh[ii,:]
411-
412-
# keep orientation
413-
vnorm = vnorm*np.sign(vnorm[2])
414-
415-
# checking error
416-
err_std = self.check_error(xyz_matrix, vnorm)
417-
log.info('Fit error : %s' %str(err_std))
418-
419-
# forming output
420-
roi_params = {'roi':roi, 'error': err_std, 'tvec': tvec, 'vnorm':vnorm }
421-
return roi_params
422362

423363
def fit_plane_with_outliers(self, img_roi):
424364
"computes normal for the specifric roi and evaluates error. Do it twice to reject outliers"
@@ -603,12 +543,10 @@ def find_planes(self, img):
603543
"finds planes using different algo"
604544

605545
img_roi = self.preprocess(img)
606-
detect_type = self.detect_type.upper()
546+
detect_type = self.detect_type.upper()
607547

608-
img_mean, img_std = 0,0
609-
if detect_type == 'T':
610-
img_mean, img_std = self.fit_plane(img_roi)
611-
elif detect_type == 'P':
548+
img_mean, img_std = 0,0
549+
if detect_type == 'P':
612550
img_mean, img_std = self.fit_plane_svd(img_roi)
613551
elif detect_type == 'O':
614552
img_mean, img_std = self.fit_plane_with_outliers(img_roi)
@@ -621,16 +559,15 @@ def find_planes(self, img):
621559
return True
622560

623561
def process_frame(self, img):
624-
"process the entire image image"
625-
626-
img_roi = self.preprocess(img)
627-
img3d = self.init_img3d(img_roi)
628-
imgXYZ = self.compute_img3d(img_roi)
629-
roip = self.fit_plane_with_outliers()
630-
631-
pose = self.convert_roi_params_to_pose(roip)
632-
self.show_image_with_axis(img_roi, pose)
633-
return self.rect
562+
"process the entire image and find the planes"
563+
564+
img_roi = self.preprocess(img)
565+
img3d = self.init_img3d(img_roi)
566+
imgXYZ = self.compute_img3d(img_roi)
567+
roim,rois = self.fit_plane_with_outliers(img_roi)
568+
pose = self.convert_plane_params_to_pose()
569+
570+
return pose
634571

635572
if __name__ == '__main__':
636573
#print(__doc__)

0 commit comments

Comments
 (0)