def test_sobel_horiz_1(): a = np.linspace(0,255,40000).astype(np.float32) a.shape=200,200 imA=fi.asfastimage(a) result = np.asarray(imA.sobel_horiz(imA.size)) b = np.ones_like(a) imB=fi.asfastimage(b) imA.sobel_horiz(imA.size,dest=imB) assert np.allclose(result,b)
def play_func(loaded_trx, im_pts_segs_q, playing ): playing.set() try: n_frames = loaded_trx['n_frames'] all_vals = loaded_trx['all_vals'] fmf = loaded_trx['fmf'] bg_image = loaded_trx['bg_image'] tracker = loaded_trx['tracker'] cam_id = loaded_trx['cam_id'] format = loaded_trx['format'] fibg = FastImage.asfastimage(bg_image) smallframe_size = None fmf.seek(0) #for fno in range(671,672):#n_frames): for fno in range(n_frames): # reconstruct original frame ################# posx, posy, orientation, windowx, windowy, data_timestamp = all_vals[fno][:6] smallframe,fmf_timestamp = fmf.get_frame(fno) fismall = FastImage.asfastimage(smallframe) assert fmf_timestamp == data_timestamp timestamp = fmf_timestamp if 0: fullsize_image = fibg.get_8u_copy(fibg.size) software_roi = fullsize_image.roi( windowx, windowy, fismall.size ) fismall.get_8u_copy_put( software_roi, fismall.size ) else: fullsize_image = bg_image.copy() fullsize_image[ windowy:windowy+smallframe.shape[0], windowx:windowx+smallframe.shape[1]] = smallframe fullsize_image = FastImage.asfastimage(fullsize_image) # process with flytrax ################# buf_offset=0,0 framenumber=fno points,linesegs = tracker.process_frame(cam_id, fullsize_image, buf_offset, timestamp, framenumber) tup = fullsize_image, points, linesegs im_pts_segs_q.put( tup ) #time.sleep(1e-2) finally: playing.clear()
def test_get_8u_copy(): a = np.linspace(0,255,40000).astype(np.float32) a.shape=200,200 imA=fi.asfastimage(a) imB=imA.get_8u_copy(imA.size) b_test = np.asarray(imB) diff = a-b_test assert np.all(abs(diff)<1.0)
def test_from_nx1(self): A = np.array(32.2,np.float32) sz = fi.Size(33,323) arA = np.array(A,np.float32)*np.ones((sz.h, sz.w),np.float32) imA=fi.asfastimage(arA) arA[1,3:40] = 3024.03 self.assert_( np.allclose(arA, np.asarray(imA)))
def test_conversion_step(): sz = fi.Size(660,480) cls_dtype_nbytes = [ (fi.FastImage8u, np.uint8, 1), (fi.FastImage32f, np.float32, 4), ] for cls, dtype, nbytes in cls_dtype_nbytes: imA=cls(sz) npB = np.empty( (sz.h,imA._step//nbytes), dtype=dtype ) npB = npB[:,:sz.w] imB = fi.asfastimage( npB ) assert imA._step == imB._step assert imA.size == imB.size
def process_frame(self,cam_id,buf,buf_offset,timestamp,framenumber): if self.pixel_format[cam_id]=='YUV422': buf = imops.yuv422_to_mono8( numpy.asarray(buf) ) # convert elif not (self.pixel_format[cam_id].startswith('MONO8') or self.pixel_format[cam_id].startswith('RAW8')): warnings.warn("flytrax plugin incompatible with data format") return [], [] bunch = self.bunches[cam_id] do_bg_maint = False clear_and_take_bg_image = self.clear_and_take_bg_image[cam_id] # this is called in realtime thread fibuf = FastImage.asfastimage(buf) # FastImage view of image data (hardware ROI) l,b = buf_offset lbrt = l, b, l+fibuf.size.w-1, b+fibuf.size.h-1 running_mean_im = bunch.running_mean_im_full.roi(l, b, fibuf.size) # set ROI view running_sumsqf = bunch.running_sumsqf_full.roi(l, b, fibuf.size) # set ROI view new_clear_threshold = self.new_clear_threshold[cam_id] new_diff_threshold = self.new_diff_threshold[cam_id] new_roi2_radius = self.new_roi2_radius[cam_id] realtime_analyzer = self.realtime_analyzer[cam_id] realtime_analyzer.roi = lbrt # hardware ROI max_frame_size = self.max_frame_size[cam_id] display_active = self.display_active[cam_id] use_roi2 = True use_cmp = False # use variance-based background subtraction/analysis draw_points = [] draw_linesegs = [] running_mean8u_im_full = realtime_analyzer.get_image_view('mean') running_mean8u_im = running_mean8u_im_full.roi(l, b, fibuf.size) if (bunch.initial_take_bg_state is not None or clear_and_take_bg_image.isSet()): src_fullframe_fi = fibuf.get_8u_copy(max_frame_size) if bunch.initial_take_bg_state is not None: assert bunch.initial_take_bg_state == 'gather' n_initial_take = 5 bunch.initial_take_frames.append( numpy.array(src_fullframe_fi) ) # copied above if len( bunch.initial_take_frames ) >= n_initial_take: initial_take_frames = numpy.array( bunch.initial_take_frames, dtype=numpy.float32 ) mean_frame = numpy.mean( initial_take_frames, axis=0) sumsqf_frame = numpy.sum(initial_take_frames**2, axis=0)/len( initial_take_frames ) numpy.asarray(running_mean_im)[:,:] = mean_frame numpy.asarray(running_sumsqf)[:,:] = sumsqf_frame # we're done with initial transient, set stuff do_bg_maint = True bunch.initial_take_bg_state = None bunch.initial_take_frames = [] if clear_and_take_bg_image.isSet(): bunch.initial_take_bg_state = 'gather' bunch.initial_take_frames = [] with self.bg_update_lock: bunch.last_running_mean_im = None clear_and_take_bg_image.clear() if 1: self.ticks_since_last_update[cam_id] += 1 update_interval = self.ongoing_bg_image_update_interval[cam_id].get() if self.ticks_since_last_update[cam_id]%update_interval == 0: do_bg_maint = True if do_bg_maint: hw_roi_frame = fibuf cur_fisize = hw_roi_frame.size bg_frame_alpha = 1.0/bunch.inverse_alpha.get_nowait() n_sigma = bunch.n_sigma.get_nowait() bright_non_gaussian_cutoff = 255 bright_non_gaussian_replacement = 255 compareframe8u_full = realtime_analyzer.get_image_view('cmp') compareframe8u = compareframe8u_full.roi(l, b, fibuf.size) fastframef32_tmp = bunch.fastframef32_tmp_full.roi(l, b, fibuf.size) mean2 = bunch.mean2_full.roi(l, b, fibuf.size) std2 = bunch.std2_full.roi(l, b, fibuf.size) running_stdframe = bunch.running_stdframe_full.roi(l, b, fibuf.size) noisy_pixels_mask = bunch.noisy_pixels_mask_full.roi(l, b, fibuf.size) realtime_image_analysis.do_bg_maint( running_mean_im,#in hw_roi_frame,#in cur_fisize,#in bg_frame_alpha, #in running_mean8u_im, fastframef32_tmp, running_sumsqf, #in mean2, std2, running_stdframe, n_sigma,#in compareframe8u, bright_non_gaussian_cutoff,#in noisy_pixels_mask,#in bright_non_gaussian_replacement,#in bench=0 ) #debug=0) #chainbuf.real_std_est= tmpresult bg_changed = True bg_frame_number = 0 with self.bg_update_lock: bunch.last_running_mean_im = running_mean_im # XXX should copy? bunch.last_running_sumsqf_image = running_sumsqf # XXX should copy? bunch.last_bgcmp_image_timestamp = timestamp if new_clear_threshold.isSet(): nv = self.clear_threshold_value[cam_id] realtime_analyzer.clear_threshold = nv #print 'set clear',nv new_clear_threshold.clear() if new_diff_threshold.isSet(): nv = self.diff_threshold_value[cam_id] realtime_analyzer.diff_threshold = nv #print 'set diff',nv new_diff_threshold.clear() if new_roi2_radius.isSet(): nv = self.roi2_radius_value[cam_id] realtime_analyzer.roi2_radius = nv new_roi2_radius.clear() n_pts = 0 with self.ufmf_writer_lock: with self.tracking_enabled_lock: ufmf_writer = self.ufmf_writer.get(cam_id,None) tracking_enabled = self.tracking_enabled.get(cam_id,False) if (ufmf_writer is not None) or tracking_enabled: try: realtime_analyzer.max_num_points = bunch.max_num_points.get_nowait() except AttributeError, err: warnings.warn('old realtime_analyzer does not support dynamic ' 'setting of max_num_points') points = realtime_analyzer.do_work(fibuf, timestamp, framenumber, use_roi2, use_cmp=use_cmp) pts = [] w = h = realtime_analyzer.roi2_radius*2 for pt in points: pts.append( (pt[0], pt[1], w, h ) ) if ufmf_writer is not None: saved_points = ufmf_writer.add_frame( fibuf, timestamp, pts ) else: saved_points = self.dummy_ufmf_writer[cam_id].add_frame( fibuf, timestamp, pts ) lineseg_lists = [ corners2linesegs( *corners ) for corners in saved_points] for linesegs in lineseg_lists: draw_linesegs.extend( linesegs ) # save any pending background model updates with self.bg_update_lock: if bunch.last_running_mean_im is not None: if ufmf_writer is not None: ufmf_writer.add_keyframe('mean', bunch.last_running_mean_im, bunch.last_bgcmp_image_timestamp) ufmf_writer.add_keyframe('sumsq', bunch.last_running_sumsqf_image, bunch.last_bgcmp_image_timestamp) # delete it bunch.last_running_mean_im = None
def retrack_movies( h5_filename, output_h5_filename=None, max_n_frames=None, start=None, stop=None, ufmf_dir=None, cfg_filename=None, ufmf_filenames=None, save_debug_images=False, ): # 2D data format for PyTables: Info2D = flydra_core.data_descriptions.Info2D if ufmf_filenames is None: ufmf_filenames = auto_discover_ufmfs.find_ufmfs(h5_filename, ufmf_dir=ufmf_dir, careful=True) print("ufmf_filenames: %r" % ufmf_filenames) if len(ufmf_filenames) == 0: raise RuntimeError( "nothing to do (autodetection of .ufmf files failed)") if ufmf_dir is not None: if (not ufmf_filenames[0].startswith("/")) and (not os.path.isfile( ufmf_filenames[0])): # filenames are not absolute and are not present, convert ufmf_filenames = [ os.path.join(ufmf_dir, fname) for fname in ufmf_filenames ] else: raise RuntimeError( "ufmf_dir given but ufmf_filenames exist without it") if os.path.exists(output_h5_filename): raise RuntimeError("will not overwrite old file '%s'" % output_h5_filename) # get name of data config = get_config_defaults() if cfg_filename is not None: loaded_cfg = cherrypy.lib.reprconf.as_dict(cfg_filename) for section in loaded_cfg: config[section].update(loaded_cfg.get(section, {})) default_camcfg = config["default"] for cam_id in config.keys(): if cam_id == "default": continue # ensure default key/value pairs in each cam_id for key, value in default_camcfg.iteritems(): if key not in config[cam_id]: config[cam_id][key] = value datetime_str = os.path.splitext(os.path.split(h5_filename)[-1])[0] datetime_str = datetime_str[4:19] retrack_cam_ids = [ ufmf_tools.get_cam_id_from_ufmf_fname(f) for f in ufmf_filenames ] with open_file_safe(h5_filename, mode="r") as h5: # Find camns in original data camn2cam_id, cam_id2camns = result_utils.get_caminfo_dicts(h5) retrack_camns = [] for cam_id in retrack_cam_ids: retrack_camns.extend(cam_id2camns[cam_id]) all_camns = camn2cam_id.keys() # Save results to temporary file. Copy to real location on success. tmpdir = tempfile.mkdtemp() tmp_output_h5_filename = os.path.join(tmpdir, "retrack.h5") with open_file_safe(tmp_output_h5_filename, mode="w", delete_on_error=True) as output_h5: out_data2d = output_h5.create_table( output_h5.root, "data2d_distorted", Info2D, "2d data", expectedrows=h5.root.data2d_distorted.nrows, ) # Are there any camns in original h5 that are not being retracked? if len(set(all_camns) - set(retrack_camns)): # Yes. # OK, exclude all camns to be retracked... orig_data2d = h5.root.data2d_distorted[:] # read all data for camn in retrack_camns: delete_cond = orig_data2d["camn"] == camn save_cond = ~delete_cond orig_data2d = orig_data2d[save_cond] # And save original data for untouched camns out_data2d.append(orig_data2d) for input_node in h5.root._f_iter_nodes(): if input_node._v_name not in [ "data2d_distorted", "kalman_estimates", "ML_estimates", "ML_estimates_2d_idxs", ]: print("copying", input_node._v_name) # copy everything from source to dest input_node._f_copy(output_h5.root, recursive=True) fpc = realtime_image_analysis.FitParamsClass( ) # allocate FitParamsClass count = 0 iterate_frames = ufmf_tools.iterate_frames # shorten notation for frame_enum, (frame_dict, frame) in enumerate( iterate_frames( h5_filename, ufmf_filenames, max_n_frames=max_n_frames, start=start, stop=stop, )): if (frame_enum % 100) == 0: print("%s: frame %d" % (datetime_str, frame)) for ufmf_fname in ufmf_filenames: try: frame_data = frame_dict[ufmf_fname] except KeyError: # no data saved (frame skip on Prosilica camera?) continue count += 1 camn = frame_data["camn"] cam_id = frame_data["cam_id"] camcfg = config.get(cam_id, default_camcfg) image = frame_data["image"] cam_received_timestamp = frame_data[ "cam_received_timestamp"] timestamp = frame_data["timestamp"] detected_points = True obj_slices = None if len(frame_data["regions"]) == 0: # no data this frame -- go to next camera or frame detected_points = False if detected_points: # print frame,cam_id,len(frame_data['regions']) absdiff_im = abs( frame_data["mean"].astype(np.float32) - image) thresh_val = (np.max(absdiff_im) * camcfg["absdiff_max_frac_thresh"]) thresh_val = max(camcfg["min_absdiff"], thresh_val) thresh_im = absdiff_im > thresh_val labeled_im, n_labels = scipy.ndimage.label(thresh_im) if not n_labels: detected_points = False else: obj_slices = scipy.ndimage.find_objects(labeled_im) detection = out_data2d.row if detected_points: height, width = image.shape if save_debug_images: xarr = [] yarr = [] frame_pt_idx = 0 detected_points = False # possible not to find any below for i in range(n_labels): y_slice, x_slice = obj_slices[i] # limit pixel operations to covering rectangle this_labeled_im = labeled_im[y_slice, x_slice] this_label_im = this_labeled_im == (i + 1) # calculate area (number of binarized pixels) xsum = np.sum(this_label_im, axis=0) pixel_area = np.sum(xsum) if pixel_area < camcfg["area_minimum_threshold"]: continue # calculate center xpos = np.arange(x_slice.start, x_slice.stop, x_slice.step) ypos = np.arange(y_slice.start, y_slice.stop, y_slice.step) xmean = np.sum((xsum * xpos)) / np.sum(xsum) ysum = np.sum(this_label_im, axis=1) ymean = np.sum((ysum * ypos)) / np.sum(ysum) if 1: if camcfg["pixel_aspect"] == 1: this_fit_im = this_label_im elif camcfg["pixel_aspect"] == 2: this_fit_im = np.repeat(this_label_im, 2, axis=0) else: raise ValueError("unknown pixel_aspect") fast_foreground = FastImage.asfastimage( this_fit_im.astype(np.uint8)) fail_fit = False try: ( x0_roi, y0_roi, weighted_area, slope, eccentricity, ) = fpc.fit(fast_foreground) except realtime_image_analysis.FitParamsError as err: fail_fit = True print("frame %d, ufmf %s: fit failed" % (frame, ufmf_fname)) print(err) else: if camcfg["pixel_aspect"] == 2: y0_roi *= 0.5 xmean = x_slice.start + x0_roi ymean = y_slice.start + y0_roi del weighted_area # don't leave room for confusion else: fail_fit = True if fail_fit: slope = np.nan eccentricity = np.nan detection["camn"] = camn detection["frame"] = frame detection["timestamp"] = timestamp detection[ "cam_received_timestamp"] = cam_received_timestamp detection["x"] = xmean detection["y"] = ymean detection["area"] = pixel_area detection["slope"] = slope detection["eccentricity"] = eccentricity detection["frame_pt_idx"] = frame_pt_idx # XXX These are not yet implemented: detection["cur_val"] = 0 detection["mean_val"] = np.nan detection["sumsqf_val"] = np.nan frame_pt_idx += 1 if save_debug_images: xarr.append(xmean) yarr.append(ymean) detection.append() detected_points = True if save_debug_images: save_dir = "debug" mkdir_p(save_dir) save_fname = "debug_%s_%d.png" % (cam_id, frame) save_fname_path = os.path.join( save_dir, save_fname) print("saving", save_fname_path) from . import benu canv = benu.Canvas(save_fname_path, width, height) maxlabel = np.max(labeled_im) fact = int(np.floor(255.0 / maxlabel)) canv.imshow((labeled_im * fact).astype(np.uint8), 0, 0) canv.scatter( xarr, yarr, color_rgba=(0, 1, 0, 1), radius=10, ) canv.save() if not detected_points: # If no point was tracked for this frame, # still save timestamp. detection["camn"] = camn detection["frame"] = frame detection["timestamp"] = timestamp detection[ "cam_received_timestamp"] = cam_received_timestamp detection["x"] = np.nan detection["y"] = np.nan detection["area"] = np.nan detection["slope"] = np.nan detection["eccentricity"] = np.nan detection["frame_pt_idx"] = 0 detection["cur_val"] = 0 detection["mean_val"] = np.nan detection["sumsqf_val"] = np.nan detection.append() if count == 0: raise RuntimeError("no frames processed") # move to correct location shutil.move(tmp_output_h5_filename, output_h5_filename)
def test_fast_vs_slow(self): h,w = 3,5 shape = h,w # 3 rows, 5 cols results = [] for func in [slow.do_bg_maint, ria.do_bg_maint]: running_mean_im = 4*numpy.ones( shape, dtype=numpy.float32 ) hw_roi_frame = 5*numpy.ones( shape, dtype=numpy.uint8 ) max_frame_size = FastImage.Size( w,h ) ALPHA = 0.25 running_mean8u_im = numpy.empty( shape, dtype=numpy.uint8 ) fastframef32_tmp = numpy.empty( shape, dtype=numpy.float32 ) running_sumsqf = 16*numpy.ones( shape, dtype=numpy.float32 ) mean2 = numpy.empty( shape, dtype=numpy.float32 ) std2 = numpy.empty( shape, dtype=numpy.float32 ) running_stdframe = numpy.empty( shape, dtype=numpy.float32 ) n_sigma = 2.0 compareframe8u = numpy.empty( shape, dtype=numpy.uint8 ) bright_non_gaussian_cutoff = 255 noisy_pixels_mask = numpy.ones( shape, dtype=numpy.uint8 ) bright_non_gaussian_replacement = 5 bench = 0 func( FastImage.asfastimage(running_mean_im), FastImage.asfastimage(hw_roi_frame), max_frame_size, ALPHA, FastImage.asfastimage(running_mean8u_im), FastImage.asfastimage(fastframef32_tmp), FastImage.asfastimage(running_sumsqf), FastImage.asfastimage(mean2), FastImage.asfastimage(std2), FastImage.asfastimage(running_stdframe), n_sigma, FastImage.asfastimage(compareframe8u), bright_non_gaussian_cutoff, FastImage.asfastimage(noisy_pixels_mask), bright_non_gaussian_replacement, bench=bench) results_order = ('running_mean8u_im', 'fastframef32_tmp', 'running_sumsqf', 'mean2', 'std2', 'running_stdframe', ) this_results = [ locals()[name] for name in results_order ] results.append( this_results ) for i,(slow_result_arr, fast_result_arr) in enumerate(zip(*results)): name = results_order[i] if 0: print name print slow_result_arr print fast_result_arr print assert slow_result_arr.shape == fast_result_arr.shape assert numpy.allclose( slow_result_arr, fast_result_arr )
def process_frame(self, cam_id, buf, buf_offset, timestamp, framenumber): """do work on each frame This function gets called on every single frame capture. It is called within the realtime thread, NOT the wxPython application mainloop's thread. Therefore, be extremely careful (use threading locks) when sharing data with the rest of the class. """ assert self.pixel_format == "MONO8" now = time.time() if self.pub_image is not None: if (now - self.pub_last_image) > 30.0: msg = self.pub_image_class() msg.header.seq = framenumber # XXX TODO: once camera trigger is ROS node, get accurate timestamp msg.header.stamp = self._rospy_time_from_sec(now) msg.header.frame_id = "0" npbuf = np.array(buf) (height, width) = npbuf.shape msg.height = height msg.width = width msg.encoding = "mono8" msg.step = width msg.data = npbuf.tostring() # let numpy convert to string self.pub_image.publish(msg) self.pub_last_image = now if self.pub_mean_luminance is not None: if (now - self.pub_last_mean_luminance) > 0.5: mean_lum = np.mean(buf) self.pub_mean_luminance.publish(float(mean_lum)) self.pub_last_mean_luminance = now buf = FastImage.asfastimage(buf) ros_list = [] point_list = [] draw_linesegs = [] # [ (x0,y0,x1,y1) ] if self.enabled.isSet(): light_on_dark = self.light_on_dark.isSet() offset_x, offset_y = buf_offset if 1: # work on a copy of the image so the original is displayed unaltered copyview = self.copybuf.roi(offset_x, offset_y, buf.size) buf.get_8u_copy_put(copyview, buf.size) buf = copyview buf_view = np.asarray(buf) # get numpy view of data # step 1. extract points analysis_radius = self.analysis_radius.get() luminance_threshold = self.luminance_threshold.get() if light_on_dark: clearval = 0 else: clearval = 255 # outside mask, set values to clearval mask = self.get_mask() buf_view[mask] = clearval for pt_num in range(self.num_points.get()): if light_on_dark: # find brightest point max_val, x, y = buf.max_index(buf.size) if max_val < luminance_threshold: break else: # find darkest point min_val, x, y = buf.min_index(buf.size) if min_val > (255 - luminance_threshold): break # calculate region around found point clearxmin = max(0, x - analysis_radius) clearxmax = min(buf.size.w - 1, x + analysis_radius) clearymin = max(0, y - analysis_radius) clearymax = min(buf.size.h - 1, y + analysis_radius) # extract a view of this region this_region = buf_view[clearymin:clearymax, clearxmin:clearxmax] if light_on_dark: binary_region = this_region > (max_val / 1.1) else: binary_region = this_region < (min_val * 1.1) num_pixels_classified = np.sum(binary_region.ravel()) # print '%d, (%d, %d)'%(num_pixels_classified,x,y) if num_pixels_classified > self.max_area.get(): # we don't want this point pass else: # compute luminance center of mass if not light_on_dark: # make a light-on-dark image this_region2 = 255 - this_region else: this_region2 = this_region fibuf = FastImage.asfastimage(this_region2) try: results = realtime_image_analysis.py_fit_params(fibuf) except Exception as err: print "%s: error extracting image data. ignoring." % (err,) else: (x0, y0, area, slope, eccentricity) = results theta = np.arctan(slope) x1 = x0 + clearxmin y1 = y0 + clearymin # save values ros_list.append((offset_x + x1, offset_y + y1, theta)) point_list.append((offset_x + x1, offset_y + y1)) # clear the region near the detected point buf_view[clearymin:clearymax, clearxmin:clearxmax] = clearval # send data over ROS if self.num_points.get(): if self.pub_position is not None: msg = self.pub_position_class() msg.header.stamp.secs = int(np.floor(timestamp)) msg.header.stamp.nsecs = int((timestamp % 1.0) * 1e9) msg.header.frame_id = "pixels" msg.framenumber = framenumber for (x, y, theta) in ros_list: pose = self.pub_pose_class() pose.x = x pose.y = y pose.theta = theta msg.points.append(pose) self.pub_position.publish(msg) if self.view_mask_mode.isSet(): w, h = self.image_size x = self.mask_center_x.get() y = self.mask_center_y.get() radius = self.mask_radius.get() draw_linesegs.extend(lineseg_circle(x, y, radius)) return point_list, draw_linesegs
##im.show() ##print np.__version__ ##nview = np.asarray( im ) ##print ai ##print nview ##nview[0,1] = 240 ##print nview ##im.show() a=np.arange(12).astype(np.uint8) a=np.reshape(a,(3,4)) b=fi.asfastimage(a) print b.stringview() b.set_val(1,b.size) br = b.roi(1,1,fi.Size(1,1)) br.set_val(10,br.size) print a c=fi.copy(a.astype(np.float32)) print c.stringview() print b.stringview() #print 'c.size == b.size',c.size == b.size c.toself_add_weighted( b, c.size, 0.1 ) print c.stringview()
def doit( h5_filename=None, output_h5_filename=None, ufmf_filenames=None, kalman_filename=None, start=None, stop=None, view=None, erode=0, save_images=False, save_image_dir=None, intermediate_thresh_frac=None, final_thresh=None, stack_N_images=None, stack_N_images_min=None, old_sync_timestamp_source=False, do_rts_smoothing=True, ): """ Copy all data in .h5 file (specified by h5_filename) to a new .h5 file in which orientations are set based on image analysis of .ufmf files. Tracking data to associate 2D points from subsequent frames is read from the .h5 kalman file specified by kalman_filename. """ if view is None: view = ["orig" for f in ufmf_filenames] else: assert len(view) == len(ufmf_filenames) if intermediate_thresh_frac is None or final_thresh is None: raise ValueError("intermediate_thresh_frac and final_thresh must be " "set") filename2view = dict(zip(ufmf_filenames, view)) ca = core_analysis.get_global_CachingAnalyzer() obj_ids, use_obj_ids, is_mat_file, data_file, extra = ca.initial_file_load( kalman_filename) try: ML_estimates_2d_idxs = data_file.root.ML_estimates_2d_idxs[:] except tables.exceptions.NoSuchNodeError as err1: # backwards compatibility try: ML_estimates_2d_idxs = data_file.root.kalman_observations_2d_idxs[:] except tables.exceptions.NoSuchNodeError as err2: raise err1 if os.path.exists(output_h5_filename): raise RuntimeError("will not overwrite old file '%s'" % output_h5_filename) with open_file_safe(output_h5_filename, delete_on_error=True, mode="w") as output_h5: if save_image_dir is not None: if not os.path.exists(save_image_dir): os.mkdir(save_image_dir) with open_file_safe(h5_filename, mode="r") as h5: fps = result_utils.get_fps(h5, fail_on_error=True) for input_node in h5.root._f_iter_nodes(): # copy everything from source to dest input_node._f_copy(output_h5.root, recursive=True) print("done copying") # Clear values in destination table that we may overwrite. dest_table = output_h5.root.data2d_distorted for colname in [ "x", "y", "area", "slope", "eccentricity", "cur_val", "mean_val", "sumsqf_val", ]: if colname == "cur_val": fill_value = 0 else: fill_value = np.nan clear_col(dest_table, colname, fill_value=fill_value) dest_table.flush() print("done clearing") camn2cam_id, cam_id2camns = result_utils.get_caminfo_dicts(h5) cam_id2fmfs = collections.defaultdict(list) cam_id2view = {} for ufmf_filename in ufmf_filenames: fmf = ufmf.FlyMovieEmulator( ufmf_filename, # darken=-50, allow_no_such_frame_errors=True, ) timestamps = fmf.get_all_timestamps() cam_id = get_cam_id_from_filename(fmf.filename, cam_id2camns.keys()) cam_id2fmfs[cam_id].append( (fmf, result_utils.Quick1DIndexer(timestamps))) cam_id2view[cam_id] = filename2view[fmf.filename] # associate framenumbers with timestamps using 2d .h5 file data2d = h5.root.data2d_distorted[:] # load to RAM data2d_idxs = np.arange(len(data2d)) h5_framenumbers = data2d["frame"] h5_frame_qfi = result_utils.QuickFrameIndexer(h5_framenumbers) fpc = realtime_image_analysis.FitParamsClass( ) # allocate FitParamsClass for obj_id_enum, obj_id in enumerate(use_obj_ids): print("object %d of %d" % (obj_id_enum, len(use_obj_ids))) # get all images for this camera and this obj_id obj_3d_rows = ca.load_dynamics_free_MLE_position( obj_id, data_file) this_obj_framenumbers = collections.defaultdict(list) if save_images: this_obj_raw_images = collections.defaultdict(list) this_obj_mean_images = collections.defaultdict(list) this_obj_absdiff_images = collections.defaultdict(list) this_obj_morphed_images = collections.defaultdict(list) this_obj_morph_failures = collections.defaultdict(list) this_obj_im_coords = collections.defaultdict(list) this_obj_com_coords = collections.defaultdict(list) this_obj_camn_pt_no = collections.defaultdict(list) for this_3d_row in obj_3d_rows: # iterate over each sample in the current camera framenumber = this_3d_row["frame"] if start is not None: if not framenumber >= start: continue if stop is not None: if not framenumber <= stop: continue h5_2d_row_idxs = h5_frame_qfi.get_frame_idxs(framenumber) frame2d = data2d[h5_2d_row_idxs] frame2d_idxs = data2d_idxs[h5_2d_row_idxs] obs_2d_idx = this_3d_row["obs_2d_idx"] kobs_2d_data = ML_estimates_2d_idxs[int(obs_2d_idx)] # Parse VLArray. this_camns = kobs_2d_data[0::2] this_camn_idxs = kobs_2d_data[1::2] # Now, for each camera viewing this object at this # frame, extract images. for camn, camn_pt_no in zip(this_camns, this_camn_idxs): # find 2D point corresponding to object cam_id = camn2cam_id[camn] movie_tups_for_this_camn = cam_id2fmfs[cam_id] cond = (frame2d["camn"] == camn) & ( frame2d["frame_pt_idx"] == camn_pt_no) idxs = np.nonzero(cond)[0] assert len(idxs) == 1 idx = idxs[0] orig_data2d_rownum = frame2d_idxs[idx] if not old_sync_timestamp_source: # Change the next line to 'timestamp' for old # data (before May/June 2009 -- the switch to # fview_ext_trig) frame_timestamp = frame2d[idx][ "cam_received_timestamp"] else: # previous version frame_timestamp = frame2d[idx]["timestamp"] found = None for fmf, fmf_timestamp_qi in movie_tups_for_this_camn: fmf_fnos = fmf_timestamp_qi.get_idxs( frame_timestamp) if not len(fmf_fnos): continue assert len(fmf_fnos) == 1 # should only be one .ufmf with this frame and cam_id assert found is None fmf_fno = fmf_fnos[0] found = (fmf, fmf_fno) if found is None: print( "no image data for frame timestamp %s cam_id %s" % (repr(frame_timestamp), cam_id)) continue fmf, fmf_fno = found image, fmf_timestamp = fmf.get_frame(fmf_fno) mean_image = fmf.get_mean_for_timestamp(fmf_timestamp) coding = fmf.get_format() if imops.is_coding_color(coding): image = imops.to_rgb8(coding, image) mean_image = imops.to_rgb8(coding, mean_image) else: image = imops.to_mono8(coding, image) mean_image = imops.to_mono8(coding, mean_image) xy = ( int(round(frame2d[idx]["x"])), int(round(frame2d[idx]["y"])), ) maxsize = (fmf.get_width(), fmf.get_height()) # Accumulate cropped images. Note that the region # of the full image that the cropped image # occupies changes over time as the tracked object # moves. Thus, averaging these cropped-and-shifted # images is not the same as simply averaging the # full frame. roiradius = 25 warnings.warn( "roiradius hard-coded to %d: could be set " "from 3D tracking" % roiradius) tmp = clip_and_math(image, mean_image, xy, roiradius, maxsize) im_coords, raw_im, mean_im, absdiff_im = tmp max_absdiff_im = absdiff_im.max() intermediate_thresh = intermediate_thresh_frac * max_absdiff_im absdiff_im[absdiff_im <= intermediate_thresh] = 0 if erode > 0: morphed_im = scipy.ndimage.grey_erosion(absdiff_im, size=erode) ## morphed_im = scipy.ndimage.binary_erosion(absdiff_im>1).astype(np.float32)*255.0 else: morphed_im = absdiff_im y0_roi, x0_roi = scipy.ndimage.center_of_mass( morphed_im) x0 = im_coords[0] + x0_roi y0 = im_coords[1] + y0_roi if 1: morphed_im_binary = morphed_im > 0 labels, n_labels = scipy.ndimage.label( morphed_im_binary) morph_fail_because_multiple_blobs = False if n_labels > 1: x0, y0 = np.nan, np.nan # More than one blob -- don't allow image. if 1: # for min flattening morphed_im = np.empty(morphed_im.shape, dtype=np.uint8) morphed_im.fill(255) morph_fail_because_multiple_blobs = True else: # for mean flattening morphed_im = np.zeros_like(morphed_im) morph_fail_because_multiple_blobs = True this_obj_framenumbers[camn].append(framenumber) if save_images: this_obj_raw_images[camn].append( (raw_im, im_coords)) this_obj_mean_images[camn].append(mean_im) this_obj_absdiff_images[camn].append(absdiff_im) this_obj_morphed_images[camn].append(morphed_im) this_obj_morph_failures[camn].append( morph_fail_because_multiple_blobs) this_obj_im_coords[camn].append(im_coords) this_obj_com_coords[camn].append((x0, y0)) this_obj_camn_pt_no[camn].append(orig_data2d_rownum) if 0: fname = "obj%05d_%s_frame%07d_pt%02d.png" % ( obj_id, cam_id, framenumber, camn_pt_no, ) plot_image_subregion( raw_im, mean_im, absdiff_im, roiradius, fname, im_coords, view=filename2view[fmf.filename], ) # Now, all the frames from all cameras for this obj_id # have been gathered. Do a camera-by-camera analysis. for camn in this_obj_absdiff_images: cam_id = camn2cam_id[camn] image_framenumbers = np.array(this_obj_framenumbers[camn]) if save_images: raw_images = this_obj_raw_images[camn] mean_images = this_obj_mean_images[camn] absdiff_images = this_obj_absdiff_images[camn] morphed_images = this_obj_morphed_images[camn] morph_failures = np.array(this_obj_morph_failures[camn]) im_coords = this_obj_im_coords[camn] com_coords = this_obj_com_coords[camn] camn_pt_no_array = this_obj_camn_pt_no[camn] all_framenumbers = np.arange(image_framenumbers[0], image_framenumbers[-1] + 1) com_coords = np.array(com_coords) if do_rts_smoothing: # Perform RTS smoothing on center-of-mass coordinates. # Find first good datum. fgnz = np.nonzero(~np.isnan(com_coords[:, 0])) com_coords_smooth = np.empty(com_coords.shape, dtype=np.float) com_coords_smooth.fill(np.nan) if len(fgnz[0]): first_good = fgnz[0][0] RTS_com_coords = com_coords[first_good:, :] # Setup parameters for Kalman filter. dt = 1.0 / fps A = np.array( [ [1, 0, dt, 0], # process update [0, 1, 0, dt], [0, 0, 1, 0], [0, 0, 0, 1], ], dtype=np.float, ) C = np.array( [[1, 0, 0, 0], [0, 1, 0, 0] ], # observation matrix dtype=np.float, ) Q = 0.1 * np.eye(4) # process noise R = 1.0 * np.eye(2) # observation noise initx = np.array( [ RTS_com_coords[0, 0], RTS_com_coords[0, 1], 0, 0 ], dtype=np.float, ) initV = 2 * np.eye(4) initV[0, 0] = 0.1 initV[1, 1] = 0.1 y = RTS_com_coords xsmooth, Vsmooth = adskalman.adskalman.kalman_smoother( y, A, C, Q, R, initx, initV) com_coords_smooth[first_good:] = xsmooth[:, :2] # Now shift images image_shift = com_coords_smooth - com_coords bad_cond = np.isnan(image_shift[:, 0]) # broadcast zeros to places where no good tracking image_shift[bad_cond, 0] = 0 image_shift[bad_cond, 1] = 0 shifted_morphed_images = [ shift_image(im, xy) for im, xy in zip(morphed_images, image_shift) ] results = flatten_image_stack( image_framenumbers, shifted_morphed_images, im_coords, camn_pt_no_array, N=stack_N_images, ) else: results = flatten_image_stack( image_framenumbers, morphed_images, im_coords, camn_pt_no_array, N=stack_N_images, ) # The variable fno (the first element of the results # tuple) is guaranteed to be contiguous and to span # the range from the first to last frames available. for ( fno, av_im, lowerleft, orig_data2d_rownum, orig_idx, orig_idxs_in_average, ) in results: # Clip image to reduce moment arms. av_im[av_im <= final_thresh] = 0 fail_fit = False fast_av_im = FastImage.asfastimage( av_im.astype(np.uint8)) try: (x0_roi, y0_roi, area, slope, eccentricity) = fpc.fit(fast_av_im) except realtime_image_analysis.FitParamsError as err: fail_fit = True this_morph_failures = morph_failures[ orig_idxs_in_average] n_failed_images = np.sum(this_morph_failures) n_good_images = stack_N_images - n_failed_images if n_good_images >= stack_N_images_min: n_images_is_acceptable = True else: n_images_is_acceptable = False if fail_fit: x0_roi = np.nan y0_roi = np.nan area, slope, eccentricity = np.nan, np.nan, np.nan if not n_images_is_acceptable: x0_roi = np.nan y0_roi = np.nan area, slope, eccentricity = np.nan, np.nan, np.nan x0 = x0_roi + lowerleft[0] y0 = y0_roi + lowerleft[1] if 1: for row in dest_table.iterrows( start=orig_data2d_rownum, stop=orig_data2d_rownum + 1): row["x"] = x0 row["y"] = y0 row["area"] = area row["slope"] = slope row["eccentricity"] = eccentricity row.update() # save data if save_images: # Display debugging images fname = "av_obj%05d_%s_frame%07d.png" % ( obj_id, cam_id, fno, ) if save_image_dir is not None: fname = os.path.join(save_image_dir, fname) raw_im, raw_coords = raw_images[orig_idx] mean_im = mean_images[orig_idx] absdiff_im = absdiff_images[orig_idx] morphed_im = morphed_images[orig_idx] raw_l, raw_b = raw_coords[:2] imh, imw = raw_im.shape[:2] n_ims = 5 if 1: # increase contrast contrast_scale = 2.0 av_im_show = np.clip(av_im * contrast_scale, 0, 255) margin = 10 scale = 3 # calculate the orientation line yintercept = y0 - slope * x0 xplt = np.array([ lowerleft[0] - 5, lowerleft[0] + av_im_show.shape[1] + 5, ]) yplt = slope * xplt + yintercept if 1: # only send non-nan values to plot plt_good = ~np.isnan(xplt) & ~np.isnan(yplt) xplt = xplt[plt_good] yplt = yplt[plt_good] top_row_width = scale * imw * n_ims + ( 1 + n_ims) * margin SHOW_STACK = True if SHOW_STACK: n_stack_rows = 4 rw = scale * imw * stack_N_images + ( 1 + n_ims) * margin row_width = max(top_row_width, rw) col_height = (n_stack_rows * scale * imh + (n_stack_rows + 1) * margin) stack_margin = 20 else: row_width = top_row_width col_height = scale * imh + 2 * margin stack_margin = 0 canv = benu.Canvas( fname, row_width, col_height + stack_margin, color_rgba=(1, 1, 1, 1), ) if SHOW_STACK: for (stacki, s_orig_idx ) in enumerate(orig_idxs_in_average): (s_raw_im, s_raw_coords) = raw_images[s_orig_idx] s_raw_l, s_raw_b = s_raw_coords[:2] s_imh, s_imw = s_raw_im.shape[:2] user_rect = (s_raw_l, s_raw_b, s_imw, s_imh) x_display = (stacki + 1) * margin + ( scale * imw) * stacki for show in ["raw", "absdiff", "morphed"]: if show == "raw": y_display = scale * imh + 2 * margin elif show == "absdiff": y_display = 2 * scale * imh + 3 * margin elif show == "morphed": y_display = 3 * scale * imh + 4 * margin display_rect = ( x_display, y_display + stack_margin, scale * raw_im.shape[1], scale * raw_im.shape[0], ) with canv.set_user_coords( display_rect, user_rect, transform=cam_id2view[cam_id], ): if show == "raw": s_im = s_raw_im.astype( np.uint8) elif show == "absdiff": tmp = absdiff_images[ s_orig_idx] s_im = tmp.astype(np.uint8) elif show == "morphed": tmp = morphed_images[ s_orig_idx] s_im = tmp.astype(np.uint8) canv.imshow(s_im, s_raw_l, s_raw_b) sx0, sy0 = com_coords[s_orig_idx] X = [sx0] Y = [sy0] # the raw coords in red canv.scatter(X, Y, color_rgba=(1, 0.5, 0.5, 1)) if do_rts_smoothing: sx0, sy0 = com_coords_smooth[ s_orig_idx] X = [sx0] Y = [sy0] # the RTS smoothed coords in green canv.scatter( X, Y, color_rgba=(0.5, 1, 0.5, 1)) if s_orig_idx == orig_idx: boxx = np.array([ s_raw_l, s_raw_l, s_raw_l + s_imw, s_raw_l + s_imw, s_raw_l, ]) boxy = np.array([ s_raw_b, s_raw_b + s_imh, s_raw_b + s_imh, s_raw_b, s_raw_b, ]) canv.plot( boxx, boxy, color_rgba=(0.5, 1, 0.5, 1), ) if show == "morphed": canv.text( "morphed %d" % (s_orig_idx - orig_idx, ), display_rect[0], (display_rect[1] + display_rect[3] + stack_margin - 20), font_size=font_size, color_rgba=(1, 0, 0, 1), ) # Display raw_im display_rect = ( margin, margin, scale * raw_im.shape[1], scale * raw_im.shape[0], ) user_rect = (raw_l, raw_b, imw, imh) with canv.set_user_coords( display_rect, user_rect, transform=cam_id2view[cam_id], ): canv.imshow(raw_im.astype(np.uint8), raw_l, raw_b) canv.plot( xplt, yplt, color_rgba=(0, 1, 0, 0.5)) # the orientation line canv.text( "raw", display_rect[0], display_rect[1] + display_rect[3], font_size=font_size, color_rgba=(0.5, 0.5, 0.9, 1), shadow_offset=1, ) # Display mean_im display_rect = ( 2 * margin + (scale * imw), margin, scale * mean_im.shape[1], scale * mean_im.shape[0], ) user_rect = (raw_l, raw_b, imw, imh) with canv.set_user_coords( display_rect, user_rect, transform=cam_id2view[cam_id], ): canv.imshow(mean_im.astype(np.uint8), raw_l, raw_b) canv.text( "mean", display_rect[0], display_rect[1] + display_rect[3], font_size=font_size, color_rgba=(0.5, 0.5, 0.9, 1), shadow_offset=1, ) # Display absdiff_im display_rect = ( 3 * margin + (scale * imw) * 2, margin, scale * absdiff_im.shape[1], scale * absdiff_im.shape[0], ) user_rect = (raw_l, raw_b, imw, imh) absdiff_clip = np.clip(absdiff_im * contrast_scale, 0, 255) with canv.set_user_coords( display_rect, user_rect, transform=cam_id2view[cam_id], ): canv.imshow(absdiff_clip.astype(np.uint8), raw_l, raw_b) canv.text( "absdiff", display_rect[0], display_rect[1] + display_rect[3], font_size=font_size, color_rgba=(0.5, 0.5, 0.9, 1), shadow_offset=1, ) # Display morphed_im display_rect = ( 4 * margin + (scale * imw) * 3, margin, scale * morphed_im.shape[1], scale * morphed_im.shape[0], ) user_rect = (raw_l, raw_b, imw, imh) morphed_clip = np.clip(morphed_im * contrast_scale, 0, 255) with canv.set_user_coords( display_rect, user_rect, transform=cam_id2view[cam_id], ): canv.imshow(morphed_clip.astype(np.uint8), raw_l, raw_b) if 0: canv.text( "morphed", display_rect[0], display_rect[1] + display_rect[3], font_size=font_size, color_rgba=(0.5, 0.5, 0.9, 1), shadow_offset=1, ) # Display time-averaged absdiff_im display_rect = ( 5 * margin + (scale * imw) * 4, margin, scale * av_im_show.shape[1], scale * av_im_show.shape[0], ) user_rect = ( lowerleft[0], lowerleft[1], av_im_show.shape[1], av_im_show.shape[0], ) with canv.set_user_coords( display_rect, user_rect, transform=cam_id2view[cam_id], ): canv.imshow( av_im_show.astype(np.uint8), lowerleft[0], lowerleft[1], ) canv.plot( xplt, yplt, color_rgba=(0, 1, 0, 0.5)) # the orientation line canv.text( "stacked/flattened", display_rect[0], display_rect[1] + display_rect[3], font_size=font_size, color_rgba=(0.5, 0.5, 0.9, 1), shadow_offset=1, ) canv.text( "%s frame % 7d: eccentricity % 5.1f, min N images %d, actual N images %d" % ( cam_id, fno, eccentricity, stack_N_images_min, n_good_images, ), 0, 15, font_size=font_size, color_rgba=(0.6, 0.7, 0.9, 1), shadow_offset=1, ) canv.save() # Save results to new table if 0: recarray = np.rec.array(list_of_rows_of_data2d, dtype=Info2DCol_description) dest_table.append(recarray) dest_table.flush() dest_table.attrs.has_ibo_data = True data_file.close()
N=stack_N_images, ) # The variable fno (the first element of the results # tuple) is guaranteed to be contiguous and to span # the range from the first to last frames available. for (fno, av_im, lowerleft, orig_data2d_rownum, orig_idx, orig_idxs_in_average) in results: # Clip image to reduce moment arms. av_im[av_im <= final_thresh] = 0 fail_fit = False fast_av_im = FastImage.asfastimage( av_im.astype(np.uint8) ) try: (x0_roi, y0_roi, area, slope, eccentricity) = fpc.fit( fast_av_im ) except realtime_image_analysis.FitParamsError, err: fail_fit = True this_morph_failures = morph_failures[orig_idxs_in_average] n_failed_images = np.sum( this_morph_failures) n_good_images = stack_N_images-n_failed_images if n_good_images >= stack_N_images_min: n_images_is_acceptable = True else: n_images_is_acceptable = False if fail_fit:
def test_fast_vs_slow(self): h, w = 3, 5 shape = h, w # 3 rows, 5 cols results = [] for func in [slow.do_bg_maint, ria.do_bg_maint]: running_mean_im = 4 * numpy.ones(shape, dtype=numpy.float32) hw_roi_frame = 5 * numpy.ones(shape, dtype=numpy.uint8) max_frame_size = FastImage.Size(w, h) ALPHA = 0.25 running_mean8u_im = numpy.empty(shape, dtype=numpy.uint8) fastframef32_tmp = numpy.empty(shape, dtype=numpy.float32) running_sumsqf = 16 * numpy.ones(shape, dtype=numpy.float32) mean2 = numpy.empty(shape, dtype=numpy.float32) std2 = numpy.empty(shape, dtype=numpy.float32) running_stdframe = numpy.empty(shape, dtype=numpy.float32) n_sigma = 2.0 compareframe8u = numpy.empty(shape, dtype=numpy.uint8) bright_non_gaussian_cutoff = 255 noisy_pixels_mask = numpy.ones(shape, dtype=numpy.uint8) bright_non_gaussian_replacement = 5 bench = 0 func(FastImage.asfastimage(running_mean_im), FastImage.asfastimage(hw_roi_frame), max_frame_size, ALPHA, FastImage.asfastimage(running_mean8u_im), FastImage.asfastimage(fastframef32_tmp), FastImage.asfastimage(running_sumsqf), FastImage.asfastimage(mean2), FastImage.asfastimage(std2), FastImage.asfastimage(running_stdframe), n_sigma, FastImage.asfastimage(compareframe8u), bright_non_gaussian_cutoff, FastImage.asfastimage(noisy_pixels_mask), bright_non_gaussian_replacement, bench=bench) results_order = ( 'running_mean8u_im', 'fastframef32_tmp', 'running_sumsqf', 'mean2', 'std2', 'running_stdframe', ) this_results = [locals()[name] for name in results_order] results.append(this_results) for i, (slow_result_arr, fast_result_arr) in enumerate(zip(*results)): name = results_order[i] if 0: print name print slow_result_arr print fast_result_arr print assert slow_result_arr.shape == fast_result_arr.shape assert numpy.allclose(slow_result_arr, fast_result_arr)