def lf_blur_subaperture(in_data, in_align, in_format, in_layout, clen, xlen, ylen, ulen, vlen, u, v, k, k_h_offset, k_width, k_v_offset, dst_img_type, dst_byte_offset, dst_col_stride, dst_row_stride, output=None, threads=2): """ Return a subaperture image (u,v) from given light field correlated with the given kernel """ # calculate light field strides (lf_byte_offset, c_stride, x_stride, y_stride, u_stride, v_stride, full_size) = mlsl.strides(in_format, in_layout, in_align, clen, xlen, ylen, ulen, vlen) if u < 0 or u >= ulen or v < 0 or v >= vlen: raise Error('u or v out of bounds') lf_byte_offset += u_stride * u + v_stride * v if threads < 1: raise Error('the argument threads must be positive') if threads < 2: return mlsl.correlate2(in_data, in_format, lf_byte_offset, 0, 0, x_stride, y_stride, xlen, ylen, dst_img_type, dst_byte_offset, 0, 0, dst_col_stride, dst_row_stride, xlen, ylen, xlen, ylen, k, k_h_offset, k_width, k_v_offset, output=output) if threads > ylen: threads = ylen # create a shared output buffer if needed if output is None: max_col_reach = max(0, (dst_col_stride-1)*xlen) max_row_reach = max(0, (dst_row_stride-1)*ylen) max_reach = dst_byte_offset + max_col_reach + max_row_reach + struct.calcsize(dst_img_type) output = array.array(dst_img_type, '\x00'*max_reach) is_array = True else: is_array = False # create semaphores for task completion completed = threading.Semaphore(0) def thread_func(start,end): try: mlsl.correlate2(in_data, in_format, lf_byte_offset, 0, start, x_stride, y_stride, xlen, ylen, dst_img_type, dst_byte_offset, 0, start, dst_col_stride, dst_row_stride, xlen, ylen, xlen, end-start, k, k_h_offset, k_width, k_v_offset, output=output) finally: completed.release() # start tasks for i in range(threads): start = int(round(1.0*i/threads*ylen)) end = int(round(1.0*(i+1)/threads*ylen)) thread.start_new_thread(thread_func, (start,end)) # wait for task completion for i in range(threads): completed.acquire() if is_array: return output.tostring() else: return output
def lf_blur3d(in_data, in_align, in_format, in_layout, out_align, out_format, out_layout, clen, xlen, ylen, ulen, vlen, var_x, var_y, var_z, pitch, slopes, out_data=None, threads=2): """ Blur a light field such that the generated focal stack is blurred by the given variances (in microns^2). The light field geometry is given by pitch and slopes (output from mlsl.geometry) """ # calculate the light field strides (byte_offset, c_stride, x_stride, y_stride, u_stride, v_stride, full_size) = mlsl.strides(in_format, in_layout, in_align, clen, xlen, ylen, ulen, vlen) (out_byte_offset, out_c_stride, out_x_stride, out_y_stride, out_u_stride, out_v_stride, out_full_size) = mlsl.strides(out_format, out_layout, out_align, clen, xlen, ylen, ulen, vlen) out_pixel_size = struct.calcsize(out_format) if out_full_size % out_pixel_size: out_full_size += out_pixel_size - (out_full_size % out_pixel_size) # allocate an output buffer if it's not there make_string = False if out_data is None: make_string = True out_data = array.array(out_format, '\x00'*out_full_size) all_jobs = [] # do some precalculations var_x_norm = var_x / (2*math.pi) var_y_norm = var_y / (2*math.pi) var_z_norm = var_z / (2*math.pi) for (u,v) in slopes: # get the actual slope for a u,v u_f, v_f, u_s2, v_s2 = slopes[(u,v)] print u_f, v_f # calculate new covariance matrix var_h_norm = var_x_norm + var_z_norm * u_f * u_f var_v_norm = var_y_norm + var_z_norm * v_f * v_f var_c_norm = u_f * v_f * var_z_norm # rescale variances var_h = 2*math.pi * var_h_norm / (pitch*pitch) var_v = 2*math.pi * var_v_norm / (pitch*pitch) var_c = 2*math.pi * var_c_norm / (pitch*pitch) print var_h, var_v, var_c # create Gaussian kernel kernel = mlsl.gaussian2(var_h, var_v, var_c) # iterate over color channels for c in range(clen): src_byte_offset = byte_offset + c*c_stride + u*u_stride + v*v_stride dst_byte_offset = out_byte_offset + c*out_c_stride + u*out_u_stride + v*out_v_stride # append to job list all_jobs.append((src_byte_offset, dst_byte_offset, kernel)) if len(all_jobs) < threads: threads = len(all_jobs) # threads done = threading.Semaphore(0) def work_thread(jobs): try: for (src_byte_offset, dst_byte_offset, kernel) in jobs: k, k_h_offset, k_width, k_v_offset = kernel mlsl.correlate2(in_data, in_format, src_byte_offset, 0, 0, x_stride, y_stride, xlen, ylen, out_format, dst_byte_offset, 0, 0, out_x_stride, out_y_stride, xlen, ylen, xlen, ylen, k, k_h_offset, k_width, k_v_offset, output=out_data) finally: done.release() for i in range(threads): job_start = int(round(1.0*len(all_jobs)*i/threads)) job_end = int(round(1.0*len(all_jobs)*(i+1)/threads)) job_segment = all_jobs[job_start:job_end] thread.start_new_thread(work_thread,(job_segment,)) for i in range(threads): done.acquire() if make_string: out_data = out_data.tostring() return out_data