def store_lines(store, lines, segments): """ combine the lines and segments and store the Args: store (VideoAnalysisResultsStore) the results object to be filled lines ([[string]]) the data rows of the lines csv file segments ([[string]]) the data rows of the lines_segments csv file """ for row in lines: note = row["Note"] region_index = int(row["Region Index"]) line = Line(note) store.add_line(region_index, line) for row in segments: frame = int(row["Frame"]) start_x = int(row["Start x"]) start_y = int(row["Start y"]) end_x = int(row["End x"]) end_y = int(row["End y"]) line_segment = ImageLineSegment(ImagePoint(start_x, start_y), ImagePoint(end_x, end_y)) line_index = int(row["Line Index"]) store.lines[line_index].add_line_segment(frame, line_segment)
def test_dist_to_line(self): """ test the is_vertical function """ start = ImagePoint(100, 200) end0 = ImagePoint(200, 300) end1 = ImagePoint(100, 300) line = ImageLineSegment(start, end0) v_line = ImageLineSegment(start, end1) test_point = ImagePoint(100, 100) flag_l, closest_l = line.is_closest_point_on_segment(test_point) flag_vl, closest_vl = v_line.is_closest_point_on_segment(test_point) d_l = closest_l.distance_from(test_point) d_vl = closest_vl.distance_from(test_point) self.assertFalse(flag_l, "claimed test point in line segment") self.assertFalse(flag_vl, "claimed test point in vertical line segment") self.assertAlmostEqual(d_l, 70.7107, msg="distance to line failed on non-vertical line", delta=0.0001) self.assertAlmostEqual(d_vl, 0.0, msg="distance to line failed on vertical line", delta=0.0001)
def make_lines(self): line_seg1 = ImageLineSegment(ImagePoint(100, 200), ImagePoint(250, 200)) line_seg2 = ImageLineSegment(ImagePoint(200, 150), ImagePoint(200, 300)) line_seg1a = ImageLineSegment(ImagePoint(100, 225), ImagePoint(250, 225)) line_seg2a = ImageLineSegment(ImagePoint(175, 150), ImagePoint(175, 300)) self._lines = [] self._lines.append(Line("test00")) self._lines.append(Line("test01")) self._lines.append(Line("test02")) self._lines[0].add_line(67, line_seg1) self._lines[1].add_line(67, line_seg1) self._lines[1].add_line(122, line_seg1a) self._lines[2].add_line(254, line_seg2) self._lines[2].add_line(123, line_seg2a) self._lines[2].add_line(345, line_seg2a)
def make_crystal1(): """ factory function to produce a test crystals """ line1 = ImageLineSegment(ImagePoint(50, 150), ImagePoint(150, 50), "01") line2 = ImageLineSegment(ImagePoint(50, 50), ImagePoint(150, 150), "02") tmp_crystal = Crystal() tmp_crystal.add_faces([line1, line2], 250) return tmp_crystal
def test_vertical(self): """ test the is_vertical function """ start = ImagePoint(100, 200) end0 = ImagePoint(200, 300) end1 = ImagePoint(100, 300) non_vert_line = ImageLineSegment(start, end0) vert_line = ImageLineSegment(start, end1) self.assertFalse(non_vert_line.is_vertical, "non-vertical line reports vertical") self.assertTrue(vert_line.is_vertical, "vertical line reports non-vertical")
def test_lines_moving(self, position, radius): """ find if a line segment lies within radius of the a given point when the moving existing lines selecte Args: position (QPoint) the target point radius (int) the distance in pixels around the selected pixel that is significant Returns if line found a tuple (LineSegment, None) else None """ frames = [] distances = [] for key in self._display_line.keys(): line_seg = self._display_line[key].scale(self._current_zoom) dist_to_line = line_seg.distance_point_to_line(position) if dist_to_line < radius: point = ImagePoint(position.x(), position.y()) close_points = line_seg.is_closest_point_on_segment(point) if close_points[0]: frames.append(key) distances.append(dist_to_line) if len(frames) == 1: return (self._display_line[frames[0]], None) if len(frames) > 1: key = frames[np.argmin(distances)] return (self._display_line[key], None) return None
def test_lines(self, position, radius): """ find if a line segment lies within radius of the a given point Args: position (QPoint) the target point radius (int) the distance in pixels around the selected pixel that is significant Returns if line found a tuple (<line array index>, None) else None """ lines = [] distances = [] for i in range(len(self._lines_base)): line = self._lines_base[i].scale(self._current_zoom) dist_to_line = line.distance_point_to_line(position) if dist_to_line < radius: point = ImagePoint(position.x(), position.y()) close_points = line.is_closest_point_on_segment(point) if close_points[0]: lines.append(i) distances.append(dist_to_line) if len(lines) == 1: return (lines[0], None) if len(lines) > 1: return (lines[np.argmin(distances)], None) return None
def normal_line(self): """ find the normal to the line segment, given by (start, (-delta_y, delta_x)) Returns: the normal line (ImageLineSegment) """ end = ImagePoint(-self.delta_y, self.delta_x) return ImageLineSegment(self.start, end)
def shift(self, shift_vector): """ make shifted copy of this line segment Args: zoom (ImagePoint) the shift vector Returns: shifted copy of line segment (ImageLineSegment) """ start_x = np.uint32(self.start.x + shift_vector.x) start_y = np.uint32(self.start.y + shift_vector.y) end_x = np.uint32(self.end.x + shift_vector.x) end_y = np.uint32(self.end.y + shift_vector.y) start = ImagePoint(start_x, start_y) end = ImagePoint(end_x, end_y) return ImageLineSegment(start, end)
def make_line(self): """ make the current line allowing for the label's zoom factor, the line will be in coordinates of the original pixmap Returns: None """ zoom = self._current_zoom start_x = np.float64(self._start.x()) / zoom start_x = np.uint32(np.round(start_x)) start_y = np.float64(self._start.y()) / zoom start_y = np.uint32(np.round(start_y)) end_x = np.float64(self._end.x()) / zoom end_x = np.uint32(np.round(end_x)) end_y = np.float64(self._end.y()) / zoom end_y = np.uint32(np.round(end_y)) self._current_line = ImageLineSegment(ImagePoint(start_x, start_y), ImagePoint(end_x, end_y))
def scale(self, zoom): """ make scaled copy of this line segment Args: zoom (number) the scale factor. Returns: scaled copy of line segment (ImageLineSegment) """ start_x = np.uint32(np.round(self.start.x * zoom)) start_y = np.uint32(np.round(self.start.y * zoom)) end_x = np.uint32(np.round(self.end.x * zoom)) end_y = np.uint32(np.round(self.end.y * zoom)) start = ImagePoint(start_x, start_y) end = ImagePoint(end_x, end_y) return ImageLineSegment(start, end)
def shift_line_segment(self, event): """ move the the currently chosen line Args: event (QEvent) the event holding coordinates and source data Returns: None """ shift_qt = event.pos() - self._start shift_vec = ImagePoint(shift_qt.x(), shift_qt.y()).scale(1.0 / self._current_zoom) self._current_line = self._moving_line_segment.shift(shift_vec) self.redisplay()
def make_crystal2(): """ factory function to produce a test crystal """ line1 = ImageLineSegment(ImagePoint(100, 200), ImagePoint(250, 200), "01") line2 = ImageLineSegment(ImagePoint(200, 150), ImagePoint(200, 300), "02") line1a = ImageLineSegment(ImagePoint(100, 225), ImagePoint(250, 225), "01") line2a = ImageLineSegment(ImagePoint(175, 150), ImagePoint(175, 300), "02") tmp_crystal = Crystal(notes="very blured") tmp_crystal.add_faces([line1, line2], 250) tmp_crystal.add_faces([line1a, line2a], 500) return tmp_crystal
def move_chosen_line_end(self, event): """ move the end of the currently chosen line Args: event (QEvent) the event holding coordinates and source data Returns: None """ point = ImagePoint(event.x(), event.y()).scale(1.0 / self._current_zoom) if self._adjust_line == AdjustingState.START: self._current_line = self._lines_base[ self._adjust_index].new_start(point) else: self._current_line = self._lines_base[self._adjust_index].new_end( point) self.redisplay()