def unbound_traits(trait_list): ''' this method takes a list of traits and converts them as follow: ray -> line segment -> line line -> line arc -> circle circle -> circle ''' for idx, trait in enumerate(trait_list): if isinstance(trait, (trts.SegmentModified, trts.RayModified)): # if the trait is (ray v segment) convert to line trait = trts.LineModified(args=(trait.obj.p1, trait.obj.p2)) elif isinstance(trait, trts.ArcModified): # if the trait is (arc) convert to circle trait = trts.Circle(args=(trait.obj.center, trait.obj.radius)) else: # the trait is either line or circle # no need to adjust the trait pass # insertig the corrected trait back in the list trait_list[idx] = trait return trait_list
def load_traits_from_file(self): if self.data['image_name'] is not '': dir_suggestion = self.data['image_name'].split('.')[0] file_name = PySide.QtGui.QFileDialog.getOpenFileName( None, 'Open File', dir_suggestion)[0] else: file_name = PySide.QtGui.QFileDialog.getOpenFileName()[0] if file_name is u'': print('\t WARNING: no file was selected. file load aborted...') return None file_ext = file_name.split('.')[-1] # method exits if the file extension is not supported if not (file_ext in ['yaml', 'YAML', 'yml', 'YML', 'svg', 'SVG']): print('\t WARNING: only yaml and svg files are supported') return None # convert svg to yaml and load the yaml file if file_ext in ['svg', 'SVG']: file_name = arr_utils.svg_to_ymal( file_name, convert_segment_2_infinite_line=False) print( '\t NOTE: svg file converted to yaml, and the yaml file will be loaded' ) print('todo: arrangement has a yaml loader, use that instead?') stream = open(file_name, 'r') data = yaml.load(stream) traits = [] if 'lines' in data.keys(): for l in data['lines']: if len(l) == 4: #[x1,y1,x2,y2] traits += [ trts.LineModified(args=(sym.Point(l[0], l[1]), sym.Point(l[2], l[3]))) ] elif len(l) == 3: #[x1,y1,slope] traits += [ trts.LineModified(args=(sym.Point(l[0], l[1]), l[2])) ] if 'segments' in data.keys(): for s in data['segments']: traits += [ trts.SegmentModified(args=(sym.Point(s[0], s[1]), sym.Point(s[2], s[3]))) ] if 'rays' in data.keys(): for r in data['rays']: traits += [ trts.RayModified(args=(sym.Point(r[0], r[1]), sym.Point(r[2], r[3]))) ] if 'circles' in data.keys(): for c in data['circles']: traits += [ trts.CircleModified(args=(sym.Point(c[0], c[1]), c[2])) ] if 'arcs' in data.keys(): for a in data['arcs']: traits += [ trts.ArcModified(args=(sym.Point(a[0], a[1]), a[2], (a[3], a[4]))) ] # copying loaded data into self.trait_list if self.ui.radioButton_load_traits_overwrite.isChecked(): self.trait_list = traits else: self.trait_list.extend(traits) # updating trait list listWidget self.update_trait_list_listWidget() # updating the canvas self.traits_visualization_canvas.clear_axes() self.plot_traits_visualization_canvas()
def find_lines_with_radiography(self): '''''' ### get the appropriate input image if self.ui.radioButton_radiography_source_origin.isChecked(): # using original image image = self.data['image'] elif self.ui.radioButton_radiography_source_binary.isChecked(): # thresholding to binary string = self.ui.textEdit_binary_thresholding.toPlainText() [thr1, thr2] = [float(param) for param in string.split(',')] if [thr1, thr2] != self.img_prc['binary thresholding']: self.img_prc['binary thresholding'] = [thr1, thr2] self.update_binary_image() image = self.data['binary'] elif self.ui.radioButton_radiography_source_edge.isChecked(): # using edge image string = self.ui.textEdit_canny_setting.toPlainText() [thr1, thr2, apt_size] = [float(param) for param in string.split(',')] if [thr1, thr2, apt_size] != self.img_prc['canny setting']: self.update_edge_image() image = self.data['edges'] if len(self.data['dominant_orientation']) > 0: ### fetching setting for sinogram peak detection string = self.ui.textEdit_sinogram_peak_detection_setting.toPlainText( ) [refWin, minDist, minVal] = [float(param) for param in string.split(',')] ### radiography # flipud: why? I'm sure it won't work otherwise, but dont know why # It should happen in both "find_dominant_orientations" & "find_grid_lines" image = np.flipud(image) imgcenter = ( image.shape[1] / 2, # cols == x image.shape[0] / 2) # rows == y orientations = self.data['dominant_orientation'] sinog_angles = orientations - np.pi / 2 # in radian sinograms = skimage.transform.radon(image, theta=sinog_angles * 180 / np.pi) #, circle=True) sinogram_center = len(sinograms.T[0]) / 2 # ########## debug-mode # row, col = 1,1 # fig, axes = plt.subplots(row, col, figsize=(20,12)) # for singo in sinograms.T: # axes.plot(singo) # fig.show() # ########## lines = [] for (orientation, sinog_angle, sinogram) in zip(orientations, sinog_angles, sinograms.T): # Find peaks in sinogram: peakind = utilities.FindPeaks(sinogram, CWT=False, cwt_range=(1, 8, 1), Refine_win=int(refWin), MinPeakDist=int(minDist), MinPeakVal=minVal, Polar=False) # line's distance to the center of the image dist = np.array(peakind) - sinogram_center pts_0 = [(imgcenter[0] + d * np.cos(sinog_angle), imgcenter[1] + d * np.sin(sinog_angle)) for d in dist] pts_1 = [(point[0] + np.cos(orientation), point[1] + np.sin(orientation)) for point in pts_0] lines += [ trts.LineModified(args=(sym.Point(p0[0], p0[1]), sym.Point(p1[0], p1[1]))) for (p0, p1) in zip(pts_0, pts_1) ] self.trait_buffer = lines # self.trait_buffer += lines self.plot_traits_visualization_canvas() print('\t found {:d} lines'.format(len(lines))) else: print( '\t WARNING: no dominant orientation is available, so... goodluck' )
def construct_trait_from_annotation(self): ''' ''' # not enough point for any trait, unless I add points as trait (later) if len(self.annotation) < 2: # if only one point, make a line from p0 and orientation if len(self.data['dominant_orientation']) == 1: if self.ui.radioButton_man_annotate_line.isChecked(): p0 = self.annotation[-1] p1 = [ p0[0] + np.cos(self.data['dominant_orientation'][0]), p0[1] + np.sin(self.data['dominant_orientation'][0]) ] # print (p0,self.data['dominant_orientation'][0],p1 ) l_trait = trts.LineModified(args=(sym.Point(p0[0], p0[1]), sym.Point(p1[0], p1[1]))) self.trait_buffer.append(l_trait) self.traits_visualization_canvas.draw_trait_line( l_trait, 'r', '--') self.reset_trait_annotation() # print ('\t WARNING: not enough point for the selected trait class') return if self.ui.radioButton_man_annotate_line.isChecked(): # considering only the last two elements of the annotation list p0, p1 = self.annotation[-2], self.annotation[-1] l_trait = trts.LineModified(args=(sym.Point(p0[0], p0[1]), sym.Point(p1[0], p1[1]))) self.trait_buffer.append(l_trait) self.traits_visualization_canvas.draw_trait_line(l_trait) elif self.ui.radioButton_man_annotate_segment.isChecked(): # considering only the last two elements of the annotation list p0, p1 = self.annotation[-2], self.annotation[-1] s_trait = trts.SegmentModified(args=(sym.Point(p0[0], p0[1]), sym.Point(p1[0], p1[1]))) self.trait_buffer.append(s_trait) self.traits_visualization_canvas.draw_trait_segment(s_trait) elif self.ui.radioButton_man_annotate_ray.isChecked(): # considering only the last two elements of the annotation list p0, p1 = self.annotation[-2], self.annotation[-1] r_trait = trts.RayModified(args=(sym.Point(p0[0], p0[1]), sym.Point(p1[0], p1[1]))) self.trait_buffer.append(r_trait) self.traits_visualization_canvas.draw_trait_ray(r_trait) elif self.ui.radioButton_man_annotate_circle.isChecked(): if len(self.annotation) == 2: # if 2 points are given, the 1st is the center and 2nd is on the perimeter [xc, yc], [x1, y1] = self.annotation[0], self.annotation[1] rc = np.sqrt((xc - x1)**2 + (yc - y1)**2) elif len(self.annotation) > 2: # if 3 points are given, they are all considered on the perimeter # http://mathworld.wolfram.com/Circle.html [x1, y1], [x2, y2], [x3, y3] = self.annotation[ -3], self.annotation[-2], self.annotation[-1] a = np.array([[x1, y1, 1], [x2, y2, 1], [x3, y3, 1]]) d = np.array([[x1**2 + y1**2, y1, 1], [x2**2 + y2**2, y2, 1], [x3**2 + y3**2, y3, 1]]) e = np.array([[x1**2 + y1**2, x1, 1], [x2**2 + y2**2, x2, 1], [x3**2 + y3**2, x3, 1]]) f = np.array([[x1**2 + y1**2, x1, y1], [x2**2 + y2**2, x2, y2], [x3**2 + y3**2, x3, y3]]) a, d, e, f = det(a), -det(d), det(e), -det(f) xc, yc = -d / (2 * a), -e / (2 * a) rc = np.sqrt(((d**2 + e**2) / (4 * (a**2))) - (f / a)) c_trait = trts.CircleModified(args=(sym.Point(xc, yc), rc)) self.trait_buffer.append(c_trait) self.traits_visualization_canvas.draw_trait_circle(c_trait) elif self.ui.radioButton_man_annotate_arc.isChecked(): if len(self.annotation) <= 2: print( '\t WARNING: need at least and only 3 points to estimate an arc' ) else: [x1, y1], [x2, y2], [ x3, y3 ] = self.annotation[0], self.annotation[1], self.annotation[2] a = np.array([[x1, y1, 1], [x2, y2, 1], [x3, y3, 1]]) d = np.array([[x1**2 + y1**2, y1, 1], [x2**2 + y2**2, y2, 1], [x3**2 + y3**2, y3, 1]]) e = np.array([[x1**2 + y1**2, x1, 1], [x2**2 + y2**2, x2, 1], [x3**2 + y3**2, x3, 1]]) f = np.array([[x1**2 + y1**2, x1, y1], [x2**2 + y2**2, x2, y2], [x3**2 + y3**2, x3, y3]]) a, d, e, f = det(a), -det(d), det(e), -det(f) xc, yc = -d / (2 * a), -e / (2 * a) rc = np.sqrt(((d**2 + e**2) / (4 * (a**2))) - (f / a)) # screw_up : t1,t2 \in [-pi,pi] # in CCW order, the 1st pt is start, 2nd pt is on the perimeter and 3rd pt is the end # but ArcModified will modify the theta values anyway, so a good chance of screw_up here # so I will impose the restriction on the user to maintain the order and I will correct # the values here so that t1< t2 t1, t2 = np.arctan2(y1 - yc, x1 - xc), np.arctan2(y3 - yc, x3 - xc) if t1 > t2: t2 += 2 * np.pi # or t1 -= 2*np.pi ? a_trait = trts.ArcModified(args=(sym.Point(xc, yc), rc, (t1, t2))) self.trait_buffer.append(a_trait) self.traits_visualization_canvas.draw_trait_circle(a_trait) self.reset_trait_annotation()
def load_traits_from_file(self): file_name = PySide.QtGui.QFileDialog.getOpenFileName()[0] file_ext = file_name.split('.')[-1] # method exits if the file extension is not supported if not (file_ext in ['yaml', 'YAML', 'yml', 'YML', 'svg', 'SVG']): print('\t WARNING: only yaml and svg files are supported') return None # convert svg to yaml and load the yaml file if file_ext in ['svg', 'SVG']: file_name = mSGVp.svg_to_ymal( file_name, convert_segment_2_infinite_line=False) print( '\t NOTE: svg file converted to yaml, and the yaml file will be loaded' ) stream = open(file_name, 'r') data = yaml.load(stream) traits = [] if 'lines' in data.keys(): for l in data['lines']: if len(l) == 4: #[x1,y1,x2,y2] traits += [ trts.LineModified(args=(sym.Point(l[0], l[1]), sym.Point(l[2], l[3]))) ] elif len(l) == 3: #[x1,y1,slope] traits += [ trts.LineModified(args=(sym.Point(l[0], l[1]), l[2])) ] if 'segments' in data.keys(): for s in data['segments']: traits += [ trts.SegmentModified(args=(sym.Point(s[0], s[1]), sym.Point(s[2], s[3]))) ] if 'rays' in data.keys(): for r in data['rays']: traits += [ trts.RayModified(args=(sym.Point(r[0], r[1]), sym.Point(r[2], r[3]))) ] if 'circles' in data.keys(): for c in data['circles']: traits += [ trts.CircleModified(args=(sym.Point(c[0], c[1]), c[2])) ] if 'arcs' in data.keys(): for a in data['arcs']: traits += [ trts.ArcModified(args=(sym.Point(a[0], a[1]), a[2], (a[3], a[4]))) ] # copying loaded data into self.trait_list if self.ui.radioButton_load_traits_overwrite.isChecked(): self.trait_list = traits else: self.trait_list.extend(traits) # updating the canvas with traits self.plot_traits()