def remove_cell_template(norm, features): if features['_fingers_grid']: # finger grid rh = int(round(features['finger_period_row'])) cw = int(round(features['finger_period_col'])) no_fingers = ndimage.uniform_filter(norm, size=(rh, cw)) features['im_no_fingers'] = no_fingers # remove busbars no_bbs = no_fingers.copy() pixel_ops.InterpolateBBs(no_bbs, np.array(features['_busbar_cols'], np.int32), features['busbar_width'] + 6) features['im_no_figners_bbs'] = no_bbs if False: view = ImageViewer(norm) ImageViewer(no_fingers) ImageViewer(no_bbs) view.show() else: # remove fingers f_len = features['finger_period'] f = np.ones((int(round(f_len)), 1), np.float32) / f_len no_lines = ndimage.correlate(norm, f) # sharpen F_LEN2 = int(round(1.5 * f_len)) f2 = np.ones((1, F_LEN2), np.float32) / F_LEN2 filtered = ndimage.correlate(norm, f2) filtered[filtered < 0.1] = 1.0 if False: view = ImageViewer(norm) ImageViewer(no_lines) ImageViewer(filtered) view.show() edges = norm / filtered no_fingers = edges * no_lines features['im_no_fingers'] = no_fingers if '_busbar_cols' in features: # remove busbars no_bbs = no_fingers.copy() pixel_ops.InterpolateBBs( no_bbs, np.array(features['_busbar_cols'], np.int32), features['busbar_width'] + 6) else: no_bbs = no_fingers features['im_no_figners_bbs'] = no_bbs if False: view = ImageViewer(norm) ImageViewer(no_fingers) ImageViewer(no_bbs) view.show()
def plir(im_sp, im_lp, im_pl, features, spline_plir, spline_plc): t_start = timeit.default_timer() pixel_ops.ApplyThresholdLT_F32(im_sp, im_sp, 1.0, 1.0) pixel_ops.ApplyThresholdLT_F32(im_lp, im_lp, 1.0, 1.0) pixel_ops.ApplyThresholdLT_F32(im_pl, im_pl, 1.0, 1.0) if im_sp.shape != im_lp.shape: print im_sp.shape, im_lp.shape assert False im_sp = im_sp.astype(np.float64) im_lp = im_lp.astype(np.float64) im_pl = im_pl.astype(np.float64) if False: view = ImageViewer(im_sp) ImageViewer(im_lp) ImageViewer(im_pl) view.show() sys.exit() # vertical registration c = np.argmax(im_sp.mean(axis=0)) profile_sp = im_sp[:, c - 10:c + 11].mean(axis=1) profile_lp = im_lp[:, c - 10:c + 11].mean(axis=1) shift_v = register(profile_sp, profile_lp, debug=False) if False: print c, shift_v view = ImageViewer(im_lp) ImageViewer(im_sp) ImageViewer(np.roll(im_sp, shift=shift_v, axis=0)) view.show() sys.exit() im_sp = np.roll(im_sp, shift=shift_v, axis=0) # compute plir (ratio of LP to SP) plir = im_lp / im_sp if False: t = stats.scoreatpercentile(plir, per=90) print plir.min(), t, plir.max() plir[plir > t] = t view = ImageViewer(im_lp) ImageViewer(im_sp) ImageViewer(plir) view.show() sys.exit() # Get cropping and rotation parameters (based on short pass) vals = im_sp[::2, ::2].flat vals = np.sort(vals) min_val = vals[int(0.025 * vals.shape[0])] max_val = vals[int(0.975 * vals.shape[0])] features['norm_range'] = max_val - min_val features['norm_lower'] = min_val im_normed_temp = (im_sp - min_val) / (max_val - min_val) rotated_temp = block_rotate(im_normed_temp, features) block_crop(rotated_temp, features) rotation = features['crop_rotation'] x1, x2, y1, y2 = features['_crop_bounds'] if False: cropped_temp = rotated_temp[y1:y2, x1:x2] view = ImageViewer(im_sp) ImageViewer(rotated_temp) ImageViewer(cropped_temp) view.show() if 'input_param_skip_features' in features and int( features['input_param_skip_features']) == 1: return True # rotate all images if abs(rotation) > 0.01: h, w = plir.shape rot_mat = cv2.getRotationMatrix2D((w // 2, h // 2), rotation, 1.0) plir_rotated = cv2.warpAffine(plir, rot_mat, (w, h), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REPLICATE) sp_rotated = cv2.warpAffine(im_sp, rot_mat, (w, h), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REPLICATE) lp_rotated = cv2.warpAffine(im_lp, rot_mat, (w, h), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REPLICATE) h, w = im_pl.shape rot_mat = cv2.getRotationMatrix2D((w // 2, h // 2), rotation, 1.0) nf_rotated = cv2.warpAffine(im_pl, rot_mat, (w, h), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REPLICATE) else: plir_rotated = plir sp_rotated = im_sp lp_rotated = im_lp nf_rotated = im_pl # find marker location features['marker_loc'] = find_marker(sp_rotated[y1:y2, x1:x2]) nf_to_sp_ratio = nf_rotated.shape[1] / float(sp_rotated.shape[1]) features['marker_loc'] *= nf_to_sp_ratio # crop plir image cropped_plir = plir_rotated[y1:y2, x1:x2] cropped_plir = np.ascontiguousarray(cropped_plir) cropped_sp = sp_rotated[y1:y2, x1:x2] cropped_lp = lp_rotated[y1:y2, x1:x2] if False: _, upper = ip.get_percentile(cropped_plir, 0.005) pixel_ops.ClipImageF64(cropped_plir, 0, upper) print cropped_plir.min(), cropped_plir.dtype view = ImageViewer(plir) ImageViewer(cropped_plir) ImageViewer(cropped_sp) view.show() sys.exit() # convert plir image to bulk image tau_bulk_plir = interpolate.splev(cropped_plir.flatten(), spline_plir).reshape(cropped_plir.shape) _, upper = ip.get_percentile(tau_bulk_plir, 0.0001) pixel_ops.ClipImageF64(tau_bulk_plir, 0.1, upper) if False: ImageViewer(im_sp) ImageViewer(im_lp) plt.figure() plt.imshow(cropped_plir) plt.colorbar() plt.figure() plt.imshow(tau_bulk_plir) plt.colorbar() plt.show() sys.exit() # zoom bulk image to make the same size as NF if im_pl.shape != im_sp.shape: size_ratio_h = im_pl.shape[0] / float(im_sp.shape[0]) size_ratio_w = im_pl.shape[1] / float(im_sp.shape[1]) x1 = int(round(x1 * size_ratio_w)) x2 = int(round(x2 * size_ratio_w)) y1 = int(round(y1 * size_ratio_h)) y2 = int(round(y2 * size_ratio_h)) # correct and crop plir image (using params from short pass) cropped_nf = nf_rotated[y1:y2, x1:x2] # upsize low res bulk tau_bulk_plir = ndimage.zoom(tau_bulk_plir, zoom=2.0, order=1) # make sure same size height = min(tau_bulk_plir.shape[0], cropped_nf.shape[0]) width = min(tau_bulk_plir.shape[1], cropped_nf.shape[1]) tau_bulk_plir = tau_bulk_plir[:height, :width] cropped_nf = cropped_nf[:height, :width] assert tau_bulk_plir.shape == cropped_nf.shape else: cropped_nf = nf_rotated[y1:y2, x1:x2] if False: view = ImageViewer(tau_bulk_plir) ImageViewer(cropped_nf) view.show() sys.exit() if parameters.PLIR_INTERPOLATE_MARKER_WIDTH > 0 and features[ 'marker_loc'] > 0: # interpolate marker print features['marker_loc'] locs = np.array([int(round(features['marker_loc']))], np.int32) cropped_nf = np.ascontiguousarray(cropped_nf, np.float32) pixel_ops.InterpolateBBs(cropped_nf, locs, parameters.PLIR_INTERPOLATE_MARKER_WIDTH) tau_bulk_plir = np.ascontiguousarray(tau_bulk_plir, np.float32) pixel_ops.InterpolateBBs(tau_bulk_plir, locs, parameters.PLIR_INTERPOLATE_MARKER_WIDTH) if False: view = ImageViewer(cropped_nf) ImageViewer(tau_bulk_plir) view.show() # correct for doping and transfer to bulk c_vals = fit_c_vals(cropped_nf, tau_bulk_plir, spline_plc) doping = ndimage.gaussian_filter1d(c_vals, sigma=2, mode="reflect") if False: ImageViewer(cropped_nf) plt.figure() plt.plot(c_vals) plt.plot(doping) plt.show() nf_dope = cropped_nf * np.r_[doping] nf_dope[nf_dope > spline_plc[0][-1]] = spline_plc[0][-1] tau_bulk_nf = interpolate.splev(nf_dope.flatten(), spline_plc).astype( np.float32).reshape(cropped_nf.shape) _, upper_p = ip.get_percentile(tau_bulk_nf, 0.0001) pixel_ops.ClipImage(tau_bulk_nf, 0.1, upper_p) features['_C_vals'] = doping.astype(np.float32) features['im_tau_bulk_f32'] = tau_bulk_nf features['im_tau_bulk_u8'] = (ip.scale_image(tau_bulk_nf) * 255).astype( np.uint8) features['im_cropped_nf_u8'] = (ip.scale_image(cropped_nf) * 255).astype( np.uint8) features['im_cropped_nf_u16'] = np.round(cropped_nf).astype(np.uint16) features['im_cropped_sp_u16'] = np.round(cropped_sp).astype(np.uint16) features['im_cropped_lp_u16'] = np.round(cropped_lp).astype(np.uint16) if False: print tau_bulk_nf.min(), tau_bulk_nf.max() _, upper_p = ip.get_percentile(tau_bulk_nf, 0.001) pixel_ops.ClipImage(tau_bulk_nf, 0.1, upper_p) # print interpolate.splev([0.0, 0.0245], spline_plc) #ImageViewer(cropped_nf * np.r_[doping]) #ImageViewer(tau_bulk_nf) plt.figure() plt.plot(tau_bulk_plir.mean(axis=0)) plt.plot(tau_bulk_nf.mean(axis=0)) # plt.figure() # plt.hist(tau_bulk_full.flat, bins=100) if False: plt.figure() plt.plot(doping) plt.plot(c_vals) plt.figure() pl = np.mean(cropped_nf, axis=0) plt.plot(pl, label="PL") plt.legend() plt.show() # compute runtime t_stop = timeit.default_timer() features['runtime'] = t_stop - t_start return True
def finger_shape(features): if 'DEBUG' in features: DEBUG = features['DEBUG'] else: DEBUG = False # use an image that has been normalised to [0, 1] im = features['_cropped_f32'] / features['hist_percentile_99.9'] if parameters.CELL_BB_MID_POINTS: locs = np.round((features['_busbar_cols'][:-1] + features['_busbar_cols'][1:]) / 2.0).astype(np.int32) pixel_ops.InterpolateBBs(im, locs, 3) im_finger = im[features['_peak_row_nums']] # firing = np.zeros_like(im_finger) if False: view = ImageViewer(im) ImageViewer(im_finger) plt.figure() plt.plot(im_finger.mean(axis=0)) view.show() sys.exit() TRAINING_MODE = False if TRAINING_MODE: import os fn = "finger_shape.csv" # bb_locs = features['_busbar_cols'] bb_locs = np.r_[0, features['_busbar_cols'], im.shape[1] - 1] with open(fn, 'a') as f: def on_click(event): tb = plt.get_current_fig_manager().toolbar if event.xdata is None: return if tb.mode != '': print 'Not in click mode - turn of pan or zoom' return if event.button == 1: classification = "good" elif event.button == 3: classification = "bad" else: return y = round(event.ydata) x = int(round(event.xdata)) i = np.searchsorted(bb_locs, x) left, right = bb_locs[i - 1], bb_locs[i] assert left < x < right vals = im_finger[y, left:right] if x < im_finger.shape[1] // 2: vals = vals[::-1] plt.figure() plt.plot(vals) plt.show() valstr = ','.join(["%0.02f" % (v) for v in vals]) f.write("%s,%s\n" % (classification, valstr)) fig = plt.figure() fig.canvas.mpl_connect('button_press_event', on_click) plt.imshow(im_finger, cmap=plt.cm.gray, interpolation='nearest') plt.show() return if len(features['_busbar_cols']) > 1: bb_locs = features['_busbar_cols'] else: # only 1 busbar, so add left and right edges bb_locs = np.r_[0, features['_busbar_cols'], im.shape[1] - 1] S = 15 # analyse each finger independently peak_broken = [] peak_fine = [] finger_rs = [] finger_maes = [] if False: locs = [] for bb in range(len(bb_locs) - 1): locs.append((bb_locs[bb] + bb_locs[bb + 1]) // 2) im_finger2 = im_finger.copy() pixel_ops.InterpolateBBs(im_finger2, np.array(locs, np.int32), 4) view = ImageViewer(im_finger) ImageViewer(im_finger2) view.show() im_finger = im_finger2 for bb in range(len(bb_locs) - 1): segment = im_finger[:, bb_locs[bb] + S:bb_locs[bb + 1] - S] if segment.shape[1] == 0: continue xs = np.linspace(-1.0, 1.0, num=segment.shape[1]) for y in range(5, segment.shape[0] - 5): # fit a quadratic curve bbb = segment[y, :] params = np.polyfit(xs, bbb, 2) f = np.poly1d(params) ys = f(xs) # calculate the mean absolute error between the actual pixel values and the fitted parabola mae = np.abs(ys - bbb).mean() / bbb.mean() sigmoid = expit((mae - 0.02) / 0.001) # save curevature & goodness of fit finger_rs.append(params[0] * -1) finger_maes.append(mae) if sigmoid > 0.7: peak_broken.append(bbb.max()) elif sigmoid < 0.3: peak_fine.append(bbb.max()) # if True and bb == 0 and y == 5: if False and sigmoid > 0.7: print mae, sigmoid print bb, y im_fin = im_finger.copy() im_fin[y - 2, bb_locs[bb] + S:bb_locs[bb + 1] - S] = 0 im_fin[y + 2, bb_locs[bb] + S:bb_locs[bb + 1] - S] = 0 ImageViewer(im_fin) plt.figure() plt.plot(xs, bbb, label="x-profile") plt.plot(xs, ys, label="Fitted parabola") plt.legend() plt.show() if len(finger_rs) > 0: features['resistance_finger'] = np.median(finger_rs) features['resistance_finger_error'] = np.median(finger_maes) else: features['resistance_finger'] = 0 features['resistance_finger_error'] = 0 if len(peak_broken) > 0 or len(peak_fine) > 0: range_min = np.array(peak_broken + peak_fine).min() range_max = np.array(peak_broken + peak_fine).max() range_vals = np.linspace(range_min, range_max, num=100) peak_broken = np.array(peak_broken) peak_fine = np.array(peak_fine) broken_percent = peak_broken.shape[0] * 100 / float(peak_broken.shape[0] + peak_fine.shape[0]) features['fingers_non_para'] = broken_percent # compute distribution of peak vals of bad fingers bad_fingers_dist = None bad_mode = None if len(peak_broken) > 5: f_bad_fingers = stats.gaussian_kde(peak_broken) bad_fingers_dist = f_bad_fingers(range_vals) bad_maxs = np.where((bad_fingers_dist > np.roll(bad_fingers_dist, 1)) & (bad_fingers_dist > np.roll(bad_fingers_dist, -1)) & (bad_fingers_dist > 2.0))[0] if len(bad_maxs) > 0: bad_mode = range_vals[bad_maxs[np.argmax(bad_fingers_dist[bad_maxs])]] # compute distribution of peak vals of good fingers good_fingers_dist = None good_maxs = [] good_mode, good_mode_i = None, None if len(peak_fine) > 5: f_good_fingers = stats.gaussian_kde(peak_fine) good_fingers_dist = f_good_fingers(range_vals) good_maxs = np.where((good_fingers_dist > np.roll(good_fingers_dist, 1)) & (good_fingers_dist > np.roll(good_fingers_dist, -1)) & (good_fingers_dist > 2))[0] if len(good_maxs) > 0: good_mode_i = good_maxs[np.argmax(good_fingers_dist[good_maxs])] good_mode = range_vals[good_mode_i] if False: ImageViewer(im_finger) plt.figure() if good_fingers_dist is not None: plt.plot(range_vals, good_fingers_dist, 'g') if bad_fingers_dist is not None: plt.plot(range_vals, bad_fingers_dist, 'b') plt.show() sys.exit() if broken_percent >= 70: if DEBUG: print "0" # lots of broken, use fixed threshold threshold = 0.7 elif broken_percent >= 33 and (good_mode is None or bad_mode < good_mode): if DEBUG: print "1" # significant broken and "non-broken" fingers are brighter than broken ones threshold = 0.7 elif len(good_maxs) >= 2: # 2+ peaks in good dist. # - perhaps some good fingers are being classified as bad if broken_percent < 30 and (bad_mode is None or good_mode < bad_mode): if DEBUG: print "2" # mostly good and broken fingers brighter # - use the highest peak i = good_mode_i while True: if (good_fingers_dist[i] < 0.5 or i == good_fingers_dist.shape[0] - 1 or (good_fingers_dist[i] < good_fingers_dist[i + 1] and good_fingers_dist[i] < 3)): break i += 1 threshold = range_vals[i] elif broken_percent < 20 and bad_mode is not None and bad_mode < good_mode: if DEBUG: print "2B" # mostly good but broken fingers darker # - use the highest peak threshold = (range_vals[good_maxs[-2]] + range_vals[good_maxs[-1]]) / 2.0 elif bad_mode is not None: if DEBUG: print "3" # quite a few bad, or broken fingers darker # - use first peak i = good_maxs[0] while True: if (good_fingers_dist[i] < 0.5 or i == good_fingers_dist.shape[0] - 1 or (good_fingers_dist[i] < good_fingers_dist[i + 1] and good_fingers_dist[i] < 3)): break i += 1 threshold = min(range_vals[i], bad_mode - 0.1) else: threshold = good_mode elif (broken_percent <= 33 >= 1 and (bad_mode is None or good_mode < bad_mode) or broken_percent < 10) and len(good_maxs): # - majority good fingers, single peak & broken fingers (if they exist) are brighter # - base the treshold on the distribution of good finger peaks if DEBUG: print "4" # find main mode in good dist i = good_maxs[0] while True: if (good_fingers_dist[i] < 0.5 or i == good_fingers_dist.shape[0] - 1 or (good_fingers_dist[i] < good_fingers_dist[i + 1] and good_fingers_dist[i] < 3)): break i += 1 threshold = min(range_vals[good_maxs[-1]] + 0.2, range_vals[i]) else: if broken_percent > 33: # roughly 50/50. broken fingers are brighter # - use middle between good & bad if DEBUG: print "5" threshold = (good_mode + bad_mode) / 2.0 else: if DEBUG: print "6" # majority good. assume the "bad" ones aren't actually bad if good_mode_i is not None: i = good_mode_i else: i = np.argmax(good_fingers_dist) while True: if (good_fingers_dist[i] < 0.5 or i == good_fingers_dist.shape[0] - 1 or (good_fingers_dist[i] < good_fingers_dist[i + 1] and good_fingers_dist[i] < 3)): break i += 1 threshold = range_vals[i] else: threshold = 1.0 threshold -= parameters.BRIGHT_AREA_SENSITIVITY if False: print "Percent broken: ", broken_percent print "Threshold:", threshold view = ImageViewer(im) plt.figure() m1, m2 = 0, 0 if good_fingers_dist is not None: plt.plot(range_vals, good_fingers_dist, 'g', label="Not broken") m1 = good_fingers_dist.max() if bad_fingers_dist is not None: plt.plot(range_vals, bad_fingers_dist, 'r', label="Broken") m2 = bad_fingers_dist.max() plt.vlines(threshold, 0, max(m1, m2)) plt.legend() view.show() # highlight areas brighter than threshold # features['bright_line_threshold'] = threshold if threshold < 1.0: bright_lines = (im[features['_peak_row_nums']] - threshold) / (1.0 - threshold) else: bright_lines = np.zeros_like(im_finger) bright_lines *= 0.5 pixel_ops.ClipImage(bright_lines, 0, 1) # don't want to highlight single lines, so apply vertical median filter rows_filtered = np.zeros_like(bright_lines) pixel_ops.FilterV(bright_lines, rows_filtered) rows_filtered[:2, :] = bright_lines[:2, :] rows_filtered[-2:, :] = bright_lines[-2:, :] if False: view = ImageViewer(im_finger) ImageViewer(bright_lines) ImageViewer(rows_filtered) view.show() sys.exit() bright_lines = rows_filtered # create a full size image of bright areas bright_area_full = np.zeros_like(im) pixel_ops.ExpandFingers(bright_area_full, bright_lines, features['_peak_row_nums']) bright_area_full = cv2.GaussianBlur(bright_area_full, sigmaX=3, ksize=(0, 0)) bright_u8 = (bright_area_full * 255).astype(np.uint8) if 'ov_bright_area_u8' in features: assert False # features['ov_bright_area_u8'] = np.maximum(bright_u8, features['ov_bright_area_u8']) else: features['ov_bright_area_u8'] = bright_u8 features['bright_area_strength'] = bright_lines.mean() * 100 # bright area metrics mask_bright = (bright_area_full > 0.1).astype(np.uint8) im_pl = features['_cropped_f32'] brightPL = pixel_ops.MaskMean_F32(im_pl, mask_bright, 1) darkPL = pixel_ops.MaskMean_F32(im_pl, mask_bright, 0) features['bright_area_mean_PL'] = brightPL features['bright_area_fraction'] = mask_bright.mean() features['bright_area_PL_intensity_ratio'] = brightPL / max(1, darkPL) # firing problems # firing_full = np.zeros_like(im) # pixel_ops.ExpandFingers(firing_full, firing, features['_peak_row_nums']) if False: view = ImageViewer(im_finger) ImageViewer(bright_area_full) # view = ImageViewer(firing_full) ImageViewer(features['ov_bright_area_u8']) view.show() sys.exit()
def dark_areas(features): # dark areas (not dark spots) im = features['im_norm'] h, w = im.shape row_nums = features['_peak_row_nums'] cell_mask = features['bl_cropped_u8'][row_nums, :] bb_locs = features['_busbar_cols'] # fill edges & corners foreground = im[row_nums].copy() edge = features['cell_edge_tb'] rr, cc = draw.circle_perimeter(features['wafer_middle_y'], features['wafer_middle_x'], int(round(features['wafer_radius'])) - edge) mask = (cc >= 0) & (cc < w) & np.in1d(rr, row_nums) lut = np.zeros(h, np.int32) lut[row_nums] = np.arange(len(row_nums)) rr = rr[mask] cc = cc[mask] rr = np.take(lut, rr) pixel_ops.FillCorners(foreground, rr.astype(np.int32), cc.astype(np.int32)) foreground[:, :edge] = np.c_[foreground[:, edge]] foreground[:, -edge:] = np.c_[foreground[:, -edge]] # create background # 1. make monotonic between edges & BBs mono_lr = np.empty_like(foreground) mono_rl = np.empty_like(foreground) pixel_ops.MakeMonotonicBBs(foreground, mono_lr, bb_locs) pixel_ops.MakeMonotonicBBs(np.ascontiguousarray(foreground[:, ::-1]), mono_rl, np.ascontiguousarray(w - bb_locs[::-1])) mono_rl = mono_rl[:, ::-1] mono = np.minimum(mono_lr, mono_rl) background = mono da1 = background - foreground # fill BBs and flatten background2 = background.copy() pixel_ops.InterpolateBBs(background2, features['_busbar_cols'], features['busbar_width']) cols = background2.mean(axis=0) background2 -= np.r_[cols] rows = background2.mean(axis=1) background2 -= np.c_[rows] da2 = -1 * background2 pixel_ops.ApplyThresholdLT_F32(da2, da2, 0.0, 0.0) if False: view = ImageViewer(foreground) ImageViewer(background) ImageViewer(background2) ImageViewer(da1) ImageViewer(da2) ImageViewer(da1 + da2) # plt.figure() # for x in range(0, background.shape[1], 50): # plt.plot(background[:, x], label="Col %d"%(x)) # plt.legend() view.show() sys.exit() dark_areas = da1 + da2 dark_areas -= (0.1 - parameters.DARK_AREA_SENSITIVITY) dark_areas[(cell_mask == 1) | (cell_mask == 8)] = 0 # corners pixel_ops.ClipImage(dark_areas, 0.0, 1.0) dark_areas_full = np.empty_like(im) pixel_ops.ExpandFingers(dark_areas_full, dark_areas, features['_peak_row_nums']) if False: pixel_ops.ApplyThresholdGT_F32(features['im_center_dist_im'], dark_areas_full, features['wafer_radius'], 0) print features['wafer_radius'] view = ImageViewer(dark_areas) ImageViewer(dark_areas_full) ImageViewer(features['im_center_dist_im']) view.show() dark_areas_full = cv2.GaussianBlur(dark_areas_full, ksize=(0, 0), sigmaX=1) # metrics mask_dark = (dark_areas_full > 0.2).astype(np.uint8) features['dark_area_strength'] = dark_areas_full.mean() * 100 im_pl = features['_cropped_f32'] darkPL = pixel_ops.MaskMean_F32(im_pl, mask_dark, 1) brightPL = pixel_ops.MaskMean_F32(im_pl, mask_dark, 0) features['dark_area_mean_PL'] = darkPL features['dark_area_fraction'] = mask_dark.mean() features['dark_area_PL_intensity_ratio'] = brightPL / max(1, darkPL) features['ov_dark_areas_u8'] = (dark_areas_full * 255).astype(np.uint8) if False: print features['dark_area_fraction'], features['dark_area_strength'] # plt.figure() # plt.plot(cols) # plt.plot(cols_mono) view = ImageViewer(im) ImageViewer(foreground) ImageViewer(dark_areas) ImageViewer(mask_dark) ImageViewer(dark_areas_full) view.show()
def feature_extraction(im, features, skip_crop=False): t_start = timeit.default_timer() # rotation & cropping rotated = cropping.correct_cell_rotation(im, features, already_cropped=skip_crop) cropped = cropping.crop_cell(rotated, im, features, width=None, already_cropped=skip_crop) features['_cropped_f32'] = cropped features['im_cropped_u16'] = cropped.astype(np.uint16) h, w = cropped.shape if False: view = ImageViewer(im) ImageViewer(rotated) ImageViewer(cropped) view.show() # find fingers, busbars, etc cell.cell_structure(cropped, features) if False: view = ImageViewer(im) ImageViewer(cropped) ImageViewer(features['bl_cropped_u8']) view.show() sys.exit() # normalise ip.histogram_percentiles(cropped, features, center_y=h // 2, center_x=w // 2, radius=features['wafer_radius']) cell.normalise(cropped, features) norm = features['im_norm'] if False: view = ImageViewer(cropped) ImageViewer(norm) view.show() sys.exit() # remove mini busbars if parameters.CELL_BB_MID_POINTS: locs = np.round((features['_busbar_cols'][:-1] + features['_busbar_cols'][1:]) / 2.0).astype(np.int32) norm_no_min = norm.copy() pixel_ops.InterpolateBBs(norm_no_min, locs, 3) if False: print locs view = ImageViewer(norm) ImageViewer(norm_no_min) view.show() sys.exit() norm = norm_no_min features['im_norm'] = norm_no_min # full-size cell with no fingers/busbars cell.remove_cell_template(norm, features) if False: view = ImageViewer(norm) # ImageViewer(im_peaks) ImageViewer(features['im_no_fingers']) ImageViewer(features['im_no_figners_bbs']) view.show() sys.exit() if 'input_param_skip_features' not in features or int(features['input_param_skip_features']) != 1: # find cell features wafer_features(features) cell.mono_cracks(features) finger_defects(features) firing_defects(features) finger_shape(features) dark_areas(features) dark_spots(features) if 'input_param_no_post_processing' not in features or int(features['input_param_no_post_processing']) != 1: feature_combination(features) finger_defect_features(features) if False: # disable until we can do more tuning with Hunter and Juergen # - also should be merged with finger_shape emitter_gridline_r(norm, features) # undo rotation if parameters.ORIGINAL_ORIENTATION and features['cell_rotated']: for feature in features.keys(): if ((feature.startswith('im_') or feature.startswith('mask_') or feature.startswith('map_') or feature.startswith('ov_') or feature.startswith('bl_') or feature.startswith('mk_')) and features[feature].ndim == 2): features[feature] = features[feature].T[:, ::-1] # compute runtime t_stop = timeit.default_timer() features['runtime'] = t_stop - t_start