def _process(self, image, cnt_3d): if len(cnt_3d) > 0: cnt = to_2D_contour(cnt_3d) # Determine the bounding rectangle of all contours x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) image_height, image_width = image.shape[0], image.shape[1] # subtract the offset to move the bottom-left of the contour to [0,0] cnt_3d = [ np.subtract(c, [x, y, 0], dtype=np.int32) for c in cnt_3d ] preview_image = np.zeros(image.shape, dtype="uint8") preview_image.fill(255) preview_cnt = contour_into_image(to_2D_contour(cnt_3d), preview_image) x, y, w, h = cv2.boundingRect(np.concatenate(preview_cnt)) # draw the coordinate axes # x-axis cv2.line(preview_image, (x, y + h), (x + w, y + h), (255, 0, 0), 1) # y-axis cv2.line(preview_image, (x, y), (x, y + h), (0, 0, 255), 1) # draw the contour itself cv2.drawContours(preview_image, preview_cnt, -1, (60, 169, 242), 1) image = preview_image return image, cnt_3d
def _process(self, image, cnt_3d): if len(cnt_3d) > 0: cnt = to_2D_contour(cnt_3d) # Determine the bounding rectangle of all contours x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) image_height, image_width = image.shape[0], image.shape[1] # the offset to move the center of the contour to [0,0] offset_x = int(w / 2 + x) offset_y = int(h / 2 + y) cnt_3d = [np.subtract(c, [offset_x, offset_y, 0], dtype=np.int32) for c in cnt_3d] preview_image = np.zeros(image.shape, dtype="uint8") preview_image.fill(255) # generate a preview contour # preview_cnt = contour_into_image(to_2D_contour(cnt_3d), preview_image) # draw the coordinate system of the centered drawing contour x, y, w, h = cv2.boundingRect(np.concatenate(preview_cnt)) cv2.drawContours(preview_image, preview_cnt, -1, (60, 169, 242), 1) # horizontal cv2.line(preview_image, (x + int(w / 2), y + int(h / 2)), (x + w, y + int(h / 2)), (255, 0, 0), 1) # vertical cv2.line(preview_image, (x + int(w / 2), y), (x + int(w / 2), y + int(h / 2)), (0, 0, 255), 1) image = preview_image return image, cnt_3d
def processed(self, image, cnt): self.cnt3D = cnt if len(cnt) == 0: return # flip them upside down (gcode coordinate system vs. openCV coordinate system) cnt2D = to_2D_contour(cnt) x, y, w, h = cv2.boundingRect(np.concatenate(cnt2D)) transform_y = lambda y_coord: (-(y_coord - y) + (y + h)) cnt = ([ np.array([[p[0], transform_y(p[1]), p[2]] for p in c]) for c in cnt ]) itm_cnt = len(self.glWidget.items) idx = itm_cnt - 1 while idx >= 0: if type(self.glWidget.items[idx]) == gl.GLLinePlotItem: del self.glWidget.items[idx] idx -= 1 feed_rate = self.filter.feed_rate clearance = self.filter.clearance # Travel Toolpaths first_up = [0, 0, clearance] first_down = [0, 0, 0] plt = gl.GLLinePlotItem(pos=np.array([[0, 0, 0], [50, 0, 0]]), width=4, antialias=True, color="0000ff") self.glWidget.addItem(plt) plt = gl.GLLinePlotItem(pos=np.array([[0, 0, 0], [0, 50, 0]]), width=4, antialias=True, color="FF0000") self.glWidget.addItem(plt) # Carving Toolpaths for c in cnt: c = c / 1000 plt = gl.GLLinePlotItem(pos=c, width=2, antialias=True, color="ECB151") self.glWidget.addItem(plt) # Tool Movement to start next_down = c[:1][0].tolist() # first element next_up = [next_down[0], next_down[1], clearance] # first element path = np.array([first_down, first_up, next_up, next_down]) plt = gl.GLLinePlotItem(pos=path, width=1, antialias=True, color="3f3f3f3A") self.glWidget.addItem(plt) first_down = c[-1:][0].tolist() first_up = [first_down[0], first_down[1], clearance]
def _process(self, image, cnt): try: single_channel = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) generated_cnt = [] row_index = 0 # [micro m] normalized_depth = self.depth_in_micro_m / 255 for row in single_channel: rle_row = [rle for rle in self.rle(row) if rle[0] < 250] last_end = None last_contour = None for rle in rle_row: # gray => depth in [micro m] # 255 => 0 [micro m] # white means no cutting # 0 => self.depth_in_micro_m [micro m] # black is full depth depth = -(self.depth_in_micro_m - (normalized_depth * rle[0])) gray_start = rle[1] gray_end = rle[2] + gray_start if gray_start == last_end: last_contour = last_contour+[ [gray_start, row_index, depth], [gray_end, row_index, depth] ] else: if not last_contour is None: generated_cnt.append(np.array(last_contour, dtype=np.int32)) last_contour = [ [gray_start, row_index, depth], [gray_end, row_index, depth] ] last_end = gray_end if not last_contour is None: generated_cnt.append(np.array(last_contour, dtype=np.int32)) row_index += 1 # generate a preview image # preview_image = np.zeros(image.shape, dtype="uint8") preview_image.fill(255) # generate a preview contour # preview_cnt = contour_into_image(to_2D_contour(generated_cnt), preview_image) cv2.drawContours(preview_image, preview_cnt, -1, (60, 169, 242), 1) # draw the carving depth cv2.putText(preview_image, "Carving Depth {:.2f} mm".format(self.depth_in_micro_m / 1000), (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 4) image = preview_image return image, generated_cnt except Exception as exc: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno) print(type(self), exc)
def _process(self, image, cnt_3d): try: if len(cnt_3d) > 0: cnt = to_2D_contour(cnt_3d) x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) image_height, image_width = image.shape[0], image.shape[1] # the offset to move the center of the contour to [0,0] cx = int(w / 2 + x) cy = int(h / 2 + y) a = math.radians(self.angle_in_degree) ca = math.cos(a) sa = math.sin(a) rotate_point = lambda p: [ int(((p[0] - cx) * ca) - ((p[1] - cy) * sa) + cx), int(((p[0] - cx) * sa) + ((p[1] - cy) * ca) + cy), p[2] ] rotate_cnt = lambda c: np.array([rotate_point(p) for p in c]) cnt_3d = [rotate_cnt(c) for c in cnt_3d] preview_image = np.zeros(image.shape, dtype="uint8") preview_image.fill(255) # generate a preview contour # preview_cnt = contour_into_image(to_2D_contour(cnt_3d), preview_image) # draw the coordinate system of the centered drawing contour x, y, w, h = cv2.boundingRect(np.concatenate(preview_cnt)) cv2.drawContours(preview_image, preview_cnt, -1, (60, 169, 242), 1) # horizontal cv2.line(preview_image, (x + int(w / 2), y + int(h / 2)), (x + w, y + int(h / 2)), (255, 0, 0), 1) # vertical cv2.line(preview_image, (x + int(w / 2), y), (x + int(w / 2), y + int(h / 2)), (0, 0, 255), 1) image = newimage except Exception as exc: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno) print(type(self), exc) return image, cnt_3d
def gcode(self, cnt_3d): cnt = to_2D_contour(cnt_3d) clearance = self.conf_file.get_float(key="clearance", section=self.conf_section) feed_rate = self.conf_file.get_float(key="feed_rate", section=self.conf_section) code = GCode() code.feed_rate = feed_rate code.rapid_rate = feed_rate * 2 code.clearance = clearance if cnt_3d and len(cnt_3d) > 0: # Determine the bounding rectangle x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) # scale contour from [micro m] to [mm] scale_factor = 0.001 # transform all coordinates and generate gcode # for this we must apply: # - the scale factor # - flip them upside down (gcode coordinate system vs. openCV coordinate system) # transform_y = lambda y_coord: (-(y_coord - y) + (y + h)) code.raise_mill() code.feed_rapid({"x": 0, "y": 0}) code.start_spindle() for c in cnt_3d: i = 0 while i < len(c): p = c[i] grbl_x = '{:06.4f}'.format(p[0] * scale_factor) grbl_y = '{:06.4f}'.format( (transform_y(p[1])) * scale_factor) grbl_z = '{:06.4f}'.format(p[2] * scale_factor) position_save = {"x": grbl_x, "y": grbl_y} position_carving = {"x": grbl_x, "y": grbl_y, "z": grbl_z} if i == 0: code.feed_rapid(position_save) # move close to the surface code.drop_mill() # carve slowly into the workpiece until the bit has reached the final depth code.feed_linear({"z": grbl_z}) else: # move to the new x/y/z coordinate code.feed_linear(position_carving) i += 1 code.feed_linear({"z": 0}) code.raise_mill() code.stop_spindle() code.feed_rapid({"x": 0, "y": 0}) return code
def _process(self, image, cnt_3d): if len(cnt_3d) > 0: cnt = to_2D_contour(cnt_3d) # Determine the bounding rectangle of all contours x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) image_height, image_width = image.shape[0], image.shape[1] shift_x = int((x + (w / 2)) - image_width / 2) shift_y = int((y + (h / 2)) - image_height / 2) cnt_3d = [ np.subtract(c, [shift_x, shift_y, 0], dtype=np.int32) for c in cnt_3d ] cnt = to_2D_contour(cnt_3d) newimage = np.zeros(image.shape, dtype="uint8") newimage.fill(255) cv2.drawContours(newimage, cnt, -1, (60, 169, 242), 1) image = newimage return image, cnt_3d
def process(self, image, cnt_3d): if len(cnt_3d)>0: cnt = to_2D_contour(cnt_3d) # Determine the bounding rectangle of all contours x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) image_height, image_width = image.shape[0], image.shape[1] # the offset to move the center of the contour to [0,0] offset_x = x offset_y = y newimage = np.zeros(image.shape, dtype="uint8") newimage.fill(255) cnt_3d = [np.subtract(c, [offset_x, offset_y, 0], dtype=np.int32) for c in cnt_3d] drawing_cnt = to_2D_contour(cnt_3d) w2=image_width/2 h2=image_height/2 for c in drawing_cnt: i = 0 while i < len(c): p = c[i] p[0] = p[0] + w2 - w/2 p[1] = p[1] + h2 - h/2 i+=1 x, y, w, h = cv2.boundingRect(np.concatenate(drawing_cnt)) # draw the width dimension # horizontal cv2.line(newimage, (x,y+h),(x+w,y+h), (255, 0, 0), 1) # vertical cv2.line(newimage, (x,y),(x,y+h), (0, 0, 255), 1) cv2.drawContours(newimage, drawing_cnt, -1, (60,169,242), 1) image = newimage return image, cnt_3d
def process(self, image, cnt_3d): if len(cnt_3d) > 0: for c in cnt_3d: for p in c: p[2] = -self.depth_in_micro_m cnt = to_2D_contour(cnt_3d) newimage = np.zeros(image.shape, dtype="uint8") newimage.fill(255) # create a new cnt for the drawing on the image. The cnt should cover 4/5 of the overal image # image_height, image_width = image.shape[0], image.shape[1] drawing_cnt = copy.deepcopy(cnt) x, y, w, h = cv2.boundingRect(np.concatenate(drawing_cnt)) drawing_factor_w = (image_width / w) * 0.8 drawing_factor_h = (image_height / h) * 0.8 # ensure that the drawing fits into the preview image drawing_factor = drawing_factor_w if drawing_factor_w < drawing_factor_h else drawing_factor_h offset_x = (w / 2 + x) * drawing_factor offset_y = (h / 2 + y) * drawing_factor for c in drawing_cnt: i = 0 while i < len(c): p = c[i] p[0] = (p[0] * drawing_factor) + (image_width / 2) - offset_x p[1] = (p[1] * drawing_factor) + (image_height / 2) - offset_y i += 1 cv2.drawContours(newimage, drawing_cnt, -1, (60, 169, 242), 1) cv2.rectangle(newimage, (x, y), (x + w, y + h), (0, 255, 0), 1) # draw the carving depth cv2.putText( newimage, "Carving Depth {:.2f} mm".format(self.depth_in_micro_m / 1000), (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 4) image = newimage return image, cnt_3d
def process(self, image, cnt_3d): if len(cnt_3d) > 0: cnt = to_2D_contour(cnt_3d) # Determine the bounding rectangle of all contours x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) image_height, image_width = image.shape[0], image.shape[1] # the offset to move the center of the contour to [0,0] offset_x = int(w / 2 + x) offset_y = int(h / 2 + y) cnt_3d = [ np.subtract(c, [offset_x, offset_y, 0], dtype=np.int32) for c in cnt_3d ] # shift the contour to the center. Only required for the drawing # w2 = int(image_width / 2) - offset_x h2 = int(image_height / 2) - offset_y drawing_cnt = [ np.subtract(c, [-w2, -h2], dtype=np.int32) for c in cnt ] newimage = np.zeros(image.shape, dtype="uint8") newimage.fill(255) # draw the coordinate system of the centered drawing contour x, y, w, h = cv2.boundingRect(np.concatenate(drawing_cnt)) cv2.drawContours(newimage, drawing_cnt, -1, (60, 169, 242), 1) # horizontal cv2.line(newimage, (x + int(w / 2), y + int(h / 2)), (x + w, y + int(h / 2)), (255, 0, 0), 1) # vertical cv2.line(newimage, (x + int(w / 2), y), (x + int(w / 2), y + int(h / 2)), (0, 0, 255), 1) image = newimage return image, cnt_3d
def _process(self, image, cnt_3d): if len(cnt_3d) > 0: for c in cnt_3d: for p in c: p[2] = -self.depth_in_micro_m cnt = to_2D_contour(cnt_3d) preview_image = np.zeros(image.shape, dtype="uint8") preview_image.fill(255) # create a new cnt for the drawing on the image. The cnt should cover 4/5 of the overall image preview_cnt = contour_into_image(cnt, preview_image) cv2.drawContours(preview_image, preview_cnt, -1, (60, 169, 242), 1) # draw the carving depth cv2.putText( preview_image, "Carving Depth {:.2f} mm".format(self.depth_in_micro_m / 1000), (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 4) image = preview_image return image, cnt_3d
def _process(self, image, cnt_3d): if len(cnt_3d) > 0: def gauss_kernel(kernlen=21, nsig=3): x = np.linspace(-nsig, nsig, kernlen) kern1d = np.diff(st.norm.cdf(x)) return kern1d / kern1d.sum() # repeat and insert the first and last value in the array n-times # (expand the array at the beginning and end). Required for convolve function. # add_padding = lambda array, n: np.insert( np.insert(array, 0, np.full(n, array[0])), -1, np.full(n, array[-1])) box = gauss_kernel(self.window) padding = int(self.window / 2) smoothed_cnt = [] for c in cnt_3d: x, y, z = c.T if len(z) > 0: if len(z) > self.window: x_new = np.convolve(add_padding(x, padding), box, mode="valid") y_new = np.convolve(add_padding(y, padding), box, mode="valid") z_new = np.convolve(add_padding(z, padding), box, mode="valid") # replace the starting points and end points of the CNC contour with the original points. # We don't want modify the start / end of an contour. The reason for that is, that this is normaly # cut-into movement into the stock without any tolerances. So - don't modify them. # # Replace the START Points with the original one x_new[0:padding] = x[0:padding] y_new[0:padding] = y[0:padding] z_new[0:padding] = z[0:padding] # Replace the END Points with the original one x_new[-padding:] = x[-padding:] y_new[-padding:] = y[-padding:] z_new[-padding:] = z[-padding:] smoothed_cnt.append( np.asarray([[int(i[0]), int(i[1]), int(i[2])] for i in zip(x_new, y_new, z_new)])) else: smoothed_cnt.append(c) # generate a preview image # preview_image = np.zeros(image.shape, dtype="uint8") preview_image.fill(255) # generate a preview contour # preview_cnt = contour_into_image(to_2D_contour(smoothed_cnt), preview_image) # draw the centered contour cv2.drawContours(preview_image, preview_cnt, -1, (60, 169, 242), 1) image = preview_image cnt_3d = smoothed_cnt return image, cnt_3d
def process(self, image, cnt_3d): if len(cnt_3d) > 0: cnt = to_2D_contour(cnt_3d) display_factor = 0.001 if self.display_unit == "mm" else 0.0001 # Determine the origin bounding rectangle x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) # Ensure that width of the contour is the same as the width_in_mm. # Scale the contour to the required width. scaled_factor = self.width_in_micro_m / w scaled_cnt = [ np.multiply(c.astype(np.float), [scaled_factor, scaled_factor, 1]).astype(np.int32) for c in cnt_3d ] # create a new cnt for the drawing on the image. The cnt should cover 4/5 of the overall image # height_in_micro_m = self.width_in_micro_m / w * h image_height, image_width = image.shape[0], image.shape[1] drawing_factor_w = (image_width / w) * 0.8 drawing_factor_h = (image_height / h) * 0.8 # ensure that the drawing fits into the preview image drawing_factor = drawing_factor_w if drawing_factor_w < drawing_factor_h else drawing_factor_h offset_x = (image_width / 2) - (w / 2 + x) * drawing_factor offset_y = (image_height / 2) - (h / 2 + y) * drawing_factor drawing_cnt = [ np.add( np.multiply(c.astype(np.float), [drawing_factor, drawing_factor]), [offset_x, offset_y]).astype(np.int32) for c in cnt ] # generate a preview image # newimage = np.zeros(image.shape, dtype="uint8") newimage.fill(255) # determine the drawing bounding box x, y, w, h = cv2.boundingRect(np.concatenate(drawing_cnt)) # draw the centered contour cv2.drawContours(newimage, drawing_cnt, -1, (60, 169, 242), 1) cv2.rectangle(newimage, (x, y), (x + w, y + h), (0, 255, 0), 2) # draw the width dimension cv2.line(newimage, (x, y + int(h / 2)), (x + w, y + int(h / 2)), (255, 0, 0), 2) cv2.circle(newimage, (x, y + int(h / 2)), 15, (255, 0, 0), -1) cv2.circle(newimage, (x + w, y + int(h / 2)), 15, (255, 0, 0), -1) cv2.putText( newimage, "{:.1f} {}".format(self.width_in_micro_m * display_factor, self.display_unit), (x + 20, y + int(h / 2) - 30), cv2.FONT_HERSHEY_SIMPLEX, 1.65, (255, 0, 0), 4) # draw the height dimension cv2.line(newimage, (x + int(w / 2), y), (x + int(w / 2), y + h), (255, 0, 0), 2) cv2.circle(newimage, (x + int(w / 2), y), 15, (255, 0, 0), -1) cv2.circle(newimage, (x + int(w / 2), y + h), 15, (255, 0, 0), -1) cv2.putText( newimage, "{:.1f} {}".format(height_in_micro_m * display_factor, self.display_unit), (x + int(w / 2) + 20, y + 50), cv2.FONT_HERSHEY_SIMPLEX, 1.65, (255, 0, 0), 4) image = newimage cnt_3d = scaled_cnt return image, cnt_3d
def _process(self, image, cnt): try: PADDING = 2 # add padding to the image to avoid that we run out of index in the np.amax calculation image = cv2.copyMakeBorder(image, PADDING, PADDING, PADDING, PADDING, cv2.BORDER_CONSTANT, None, [255, 255, 255]) image_height, image_width = image.shape[0], image.shape[1] # generate the skeleton of the "BLACK" area and returns an image in which the # "white" part is the skeleton. # image_skeleton = image.copy( ) # deepcopy to protect the original image image_skeleton = cv2.threshold(image_skeleton, 127, 255, cv2.THRESH_BINARY_INV)[1] image_skeleton, _, _ = cv2.split(image_skeleton) #image_skeleton = 255 - cv2.ximgproc.thinning(image_skeleton, cv2.ximgproc.THINNING_GUOHALL) image_skeleton = cv2.ximgproc.thinning( image_skeleton, cv2.ximgproc.THINNING_ZHANGSUEN) # calculate the watershed distance. This is a distance calculation of the original image # image_watershed = 255 - cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) image_watershed = cv2.distanceTransform(image_watershed, cv2.DIST_L2, 5) image_watershed = cv2.convertScaleAbs(image_watershed) image_watershed = cv2.normalize(image_watershed, None, 255, 0, cv2.NORM_MINMAX, cv2.CV_8UC1) # calculate the mask and use just the pixel and the intensity for the carving depth # now we have just the skeleton image with the distance information (carving depth) image_carvingpath = cv2.bitwise_and(image_watershed, image_skeleton) # CHAIN_APPROX_NONE is important to get each and every pixel in the contour and not the reduced one. # cnt, hierarchy = cv2.findContours(image_skeleton, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) cnt = normalize_contour(cnt) x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) preview_image = np.zeros(image.shape, dtype="uint8") preview_image.fill(255) generated_cnt = ensure_3D_contour(cnt) dots_in_width = int(self.width_in_micro_m / min(self.cutter_bit_diameter_in_micro_m, self.max_diameter_in_micro_m)) max_diameter_in_pixel = (image_width / dots_in_width) carving_depth = lambda gray: -( self.max_diameter_in_micro_m / 255 * (gray)) / (math.tan( math.radians(self.cutter_bit_angle / 2)) * 2) circle_radius = lambda gray: int(((max_diameter_in_pixel / 255) * (gray)) / 2) for c in generated_cnt: i = 0 while i < len(c): p = c[i] row = p[1] col = p[0] neighbours = image_carvingpath[row - 2:row + 2, col - 2:col + 2] max = np.amax(neighbours) p[2] = carving_depth(max) cv2.circle(preview_image, (col, row), circle_radius(max), (60, 169, 242), -1) i = i + 1 cv2.drawContours(preview_image, to_2D_contour(generated_cnt), -1, (0, 49, 252), 1) display_factor = 0.001 if self.display_unit == "mm" else 0.0001 # draw the width dimension cv2.line(preview_image, (x, y + int(h / 2)), (x + w, y + int(h / 2)), (255, 0, 0), 1) cv2.circle(preview_image, (x, y + int(h / 2)), 5, (255, 0, 0), -1) cv2.circle(preview_image, (x + w, y + int(h / 2)), 5, (255, 0, 0), -1) cv2.putText( preview_image, "{:.1f} {}".format(self.width_in_micro_m * display_factor, self.display_unit), (x + 20, y + int(h / 2) - 30), cv2.FONT_HERSHEY_SIMPLEX, 1.65, (255, 0, 0), 4) # draw the height dimension height_in_micro_m = self.width_in_micro_m / w * h cv2.line(preview_image, (x + int(w / 2), y), (x + int(w / 2), y + h), (255, 0, 0), 1) cv2.circle(preview_image, (x + int(w / 2), y), 5, (255, 0, 0), -1) cv2.circle(preview_image, (x + int(w / 2), y + h), 5, (255, 0, 0), -1) cv2.putText( preview_image, "{:.1f} {}".format(height_in_micro_m * display_factor, self.display_unit), (x + int(w / 2) + 20, y + 50), cv2.FONT_HERSHEY_SIMPLEX, 1.65, (255, 0, 0), 4) # Ensure that width of the contour is the same as the width_in_mm. # Scale the contour to the required width. scale_factor = self.width_in_micro_m / w generated_cnt = [ np.multiply(c.astype(np.float), [scale_factor, scale_factor, 1]).astype(np.int32) for c in generated_cnt ] preview_image = preview_image[PADDING:-PADDING, PADDING:-PADDING] return preview_image, generated_cnt except Exception as exc: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno) print(type(self), exc)
def _process(self, image, cnt_3d): if len(cnt_3d) > 0: cnt = to_2D_contour(cnt_3d) display_factor = 0.001 if self.display_unit == "mm" else 0.0001 # Determine the origin bounding rectangle x, y, w, h = cv2.boundingRect(np.concatenate(cnt)) # Ensure that width of the contour is the same as the width_in_mm. # Scale the contour to the required width. scaled_factor = self.width_in_micro_m / w scaled_cnt = [ np.multiply(c.astype(np.float), [scaled_factor, scaled_factor, 1]).astype(np.int32) for c in cnt_3d ] # generate a preview image # preview_image = np.zeros(image.shape, dtype="uint8") preview_image.fill(255) # generate a preview contour # preview_cnt = contour_into_image(to_2D_contour(scaled_cnt), preview_image) # determine the drawing bounding box x, y, w, h = cv2.boundingRect(np.concatenate(preview_cnt)) # draw the centered contour cv2.drawContours(preview_image, preview_cnt, -1, (60, 169, 242), 1) # draw the width dimension cv2.line(preview_image, (x, y + int(h / 2)), (x + w, y + int(h / 2)), (255, 0, 0), 1) cv2.circle(preview_image, (x, y + int(h / 2)), 5, (255, 0, 0), -1) cv2.circle(preview_image, (x + w, y + int(h / 2)), 5, (255, 0, 0), -1) cv2.putText( preview_image, "{:.1f} {}".format(self.width_in_micro_m * display_factor, self.display_unit), (x + 20, y + int(h / 2) - 30), cv2.FONT_HERSHEY_SIMPLEX, 1.65, (255, 0, 0), 4) # draw the height dimension height_in_micro_m = self.width_in_micro_m / w * h cv2.line(preview_image, (x + int(w / 2), y), (x + int(w / 2), y + h), (255, 0, 0), 1) cv2.circle(preview_image, (x + int(w / 2), y), 5, (255, 0, 0), -1) cv2.circle(preview_image, (x + int(w / 2), y + h), 5, (255, 0, 0), -1) cv2.putText( preview_image, "{:.1f} {}".format(height_in_micro_m * display_factor, self.display_unit), (x + int(w / 2) + 20, y + 50), cv2.FONT_HERSHEY_SIMPLEX, 1.65, (255, 0, 0), 4) image = preview_image cnt_3d = scaled_cnt return image, cnt_3d