def test_inertia_tensor_2d(): image = np.zeros((40, 40)) image[15:25, 5:35] = 1 # big horizontal rectangle (aligned with axis 1) T = inertia_tensor(image) assert T[0, 0] > T[1, 1] np.testing.assert_allclose(T[0, 1], 0) v0, v1 = inertia_tensor_eigvals(image, T=T) np.testing.assert_allclose(np.sqrt(v0/v1), 3, rtol=0.01, atol=0.05)
def inertia_tensor(self): ''' Compute the inertia tensor of the image and retrun the eigenvalue and eigenvector. :return eigval: eigenvalue :return eigvec: eigenvector ''' inertia = skim.inertia_tensor(self.field) eigval, eigvec = np.linalg.eig(inertia) return eigval / self.res, eigvec
def get_inertia(mask, mu=None): """compute inertia tensor and eigenvalues from mask, if moments are give the function is much faster""" if mu is None: mu = measure.moments(mask) inertia_tensor = measure.inertia_tensor(mask, mu) inertia_eigen = measure.inertia_tensor_eigvals(mask, mu=mu, T=inertia_tensor) return inertia_tensor, inertia_eigen
def test_inertia_tensor_3d(): image = draw.ellipsoid(10, 5, 3) T0 = inertia_tensor(image) eig0, V0 = np.linalg.eig(T0) # principal axis of ellipse = eigenvector of smallest eigenvalue v0 = V0[:, np.argmin(eig0)] assert np.allclose(v0, [1, 0, 0]) or np.allclose(-v0, [1, 0, 0]) imrot = ndi.rotate(image.astype(float), 30, axes=(0, 1), order=1) Tr = inertia_tensor(imrot) eigr, Vr = np.linalg.eig(Tr) vr = Vr[:, np.argmin(eigr)] # Check that axis has rotated by expected amount pi, cos, sin = np.pi, np.cos, np.sin R = np.array([[cos(pi / 6), -sin(pi / 6), 0], [sin(pi / 6), cos(pi / 6), 0], [0, 0, 1]]) expected_vr = R @ v0 assert (np.allclose(vr, expected_vr, atol=1e-3, rtol=0.01) or np.allclose(-vr, expected_vr, atol=1e-3, rtol=0.01))
def test_inertia_tensor_3d(): image = draw.ellipsoid(10, 5, 3) T0 = inertia_tensor(image) eig0, V0 = np.linalg.eig(T0) # principal axis of ellipse = eigenvector of smallest eigenvalue v0 = V0[:, np.argmin(eig0)] assert np.allclose(v0, [1, 0, 0]) or np.allclose(-v0, [1, 0, 0]) imrot = ndi.rotate(image.astype(float), 30, axes=(0, 1), order=1) Tr = inertia_tensor(imrot) eigr, Vr = np.linalg.eig(Tr) vr = Vr[:, np.argmin(eigr)] # Check that axis has rotated by expected amount pi, cos, sin = np.pi, np.cos, np.sin R = np.array([[ cos(pi/6), -sin(pi/6), 0], [ sin(pi/6), cos(pi/6), 0], [ 0, 0, 1]]) expected_vr = R @ v0 assert (np.allclose(vr, expected_vr, atol=1e-3, rtol=0.01) or np.allclose(-vr, expected_vr, atol=1e-3, rtol=0.01))
def test_inertia_tensor_2d(dtype): image = np.zeros((40, 40), dtype=dtype) image[15:25, 5:35] = 1 # big horizontal rectangle (aligned with axis 1) expected_dtype = _supported_float_type(image.dtype) T = inertia_tensor(image) assert T.dtype == expected_dtype assert T[0, 0] > T[1, 1] np.testing.assert_allclose(T[0, 1], 0) v0, v1 = inertia_tensor_eigvals(image, T=T) assert v0.dtype == expected_dtype assert v1.dtype == expected_dtype np.testing.assert_allclose(np.sqrt(v0 / v1), 3, rtol=0.01, atol=0.05)
def detect_chars_pos_and_img(frame, robot_pos): """ Detect where all the characters are in the frame and returns the list of it. Frame is single channel image of the blue and black values (characters on the area). """ # Morphology to make the equal and divide one shape kernel = np.zeros((9, 9), np.uint8) cv.circle(img=kernel, center=(4, 4), radius=4, color=255, thickness=-1) dilated_img = cv.morphologyEx(frame, cv.MORPH_CLOSE, kernel, iterations=1) # Find the contours of images contours, _ = cv.findContours(image=dilated_img, mode=cv.RETR_EXTERNAL, method=cv.CHAIN_APPROX_SIMPLE) chars_pos = [] chars_img = [] for contour in contours: # Find bounding box for each contour x, y, w, h = cv.boundingRect(contour) # Verify with the box is big enough and not close to the robot r = range(2, 60) R = range(15, 60) robot_pos_threshold = 50 robot_dist = norm((x + w / 2 - robot_pos[0], y + h / 2 - robot_pos[1])) if np.min([w, h]) in r and np.max( [w, h]) in R and robot_dist > robot_pos_threshold: # Extract image extracted_img = frame[y:y + h, x:x + w] # Compute angle of rotation mu = inertia_tensor(extracted_img) alpha = np.degrees(1 / 2 * np.arctan2(2 * mu[0][1], (mu[1][1] - mu[0][0]))) # Rotate image to align vertically rotation_matrix = cv.getRotationMatrix2D((int(w / 2), int(h / 2)), alpha, 1) rotated_img = cv.warpAffine( extracted_img, rotation_matrix, (np.max([extracted_img.shape[1], extracted_img.shape[0]]), np.max([extracted_img.shape[1], extracted_img.shape[0]]))) # Normalize image for the CNN normalized_img = normalize_img(rotated_img) # Add position of char to the list chars_pos.append((x + w / 2, y + h / 2)) # Add char image to the list chars_img.append(normalized_img) return chars_pos, chars_img
def moments_features(image): """calculates the set of moments for each channel Calculates the intertia tensor, intertia tensor eigenvalues, as well as the moments of the image (https://en.wikipedia.org/wiki/Image_moment) Parameters ---------- image : 3D array, shape (M, N, C) The input image with multiple channels. Returns ------- features : dict dictionary including percentiles, moments and sum per channel """ # storing the feature values features = dict() for ch in range(image.shape[2]): hu_moments = moments_hu(image[:, :, ch]) for i in range(len(hu_moments)): features["moments_hu_" + str(i + 1) + "_Ch" + str(ch + 1)] = hu_moments[i] inertia_tensor_calculated = inertia_tensor(image[:, :, ch]).ravel() features["inertia_tensor_1_ch" + str(ch + 1)] = inertia_tensor_calculated[0] features["inertia_tensor_2_ch" + str(ch + 1)] = inertia_tensor_calculated[1] features["inertia_tensor_3_ch" + str(ch + 1)] = inertia_tensor_calculated[3] inertia_tensor_eigvalues = inertia_tensor_eigvals(image[:, :, ch]) features["inertia_tensor_eigvalues_1_ch" + str(ch + 1)] = inertia_tensor_eigvalues[0] features["inertia_tensor_eigvalues_2_ch" + str(ch + 1)] = inertia_tensor_eigvalues[1] the_moments = moments(image[:, :, ch], order=5).ravel() for i in range(len(the_moments)): features["moments_" + str(i + 1) + "_Ch" + str(ch + 1)] = the_moments[i] return features