def __init__(self, parent=None): glformat = QtOpenGL.QGLFormat() glformat.setVersion(1,1) glformat.setProfile(QtOpenGL.QGLFormat.CoreProfile) QtOpenGL.QGLWidget.__init__(self, glformat, parent) # Test we have a valid context ver = QtOpenGL.QGLFormat.openGLVersionFlags() if not ver & QtOpenGL.QGLFormat.OpenGL_Version_1_1: raise Exception("Requires OpenGL Version 1.1 or above.") # Default values self._background_colour = QtGui.QColor("silver") self._display_wireframe = False self._voxel_colour = QtGui.QColor.fromHsvF(0,1.0,1.0) self._voxeledges = True # Mouse position self._mouse = QtCore.QPoint() # Default camera self.reset_camera(False) # zoom self._zoom_speed = 0.1 # Render floor grid? self._display_floor_grid = True # Our voxel scene self.voxels = voxel.VoxelData() # Grid manager self._grids = VoxelGrid( self.voxels ) # Used to track the z component of various mouse activity self._depth_focus = 1
def __init__(self, parent=None): glformat = QtOpenGL.QGLFormat() glformat.setVersion(1, 1) glformat.setProfile(QtOpenGL.QGLFormat.CoreProfile) QtOpenGL.QGLWidget.__init__(self, glformat, parent) # Test we have a valid context ver = QtOpenGL.QGLFormat.openGLVersionFlags() if not ver & QtOpenGL.QGLFormat.OpenGL_Version_1_1: raise Exception("Requires OpenGL Version 1.1 or above.") # Default values self.setFocusPolicy(QtCore.Qt.ClickFocus) self._background_color = QtGui.QColor("silver") self._display_wireframe = False self._voxel_color = QtGui.QColor.fromHsvF(0, 1.0, 1.0) self._voxeledges = True # Mouse position self._mouse = QtCore.QPoint() self._mouse_absolute = QtCore.QPoint() self.mouse_delta_relative = (0, 0) self.mouse_delta_absolute = (0, 0) self.mouse_position = (0, 0) # Default camera self.reset_camera(False) # zoom import platform as p if p.system() == "Darwin": self._zoom_speed = 0.1 else: self._zoom_speed = -0.1 # Render axis grids? self._display_axis_grids = True # Our voxel scene self.voxels = voxel.VoxelData() # Grid manager self._grids = VoxelGrid(self.voxels) # create the default _grids self.grids.add_grid_plane(GridPlanes.X, offset=0, visible=True, color=QtGui.QColor(0x6c, 0x7d, 0x67)) self.grids.add_grid_plane(GridPlanes.Y, offset=0, visible=True, color=QtGui.QColor(0x65, 0x65, 0x7b)) self.grids.add_grid_plane(GridPlanes.Z, offset=self.voxels.depth, visible=True, color=QtGui.QColor(0x7b, 0x65, 0x68)) # Used to track the z component of various mouse activity self._depth_focus = 1 # Keep track how long mouse buttons are down for self._mousedown_time = 0 self.button_down = None self._dragging = False self._rotating = False self._key_modifiers = 0 self._keystate = set() self.ready = False
def change_detection(files_path, prm, diff_uid): # Set the distance threshold. This will also be the voxel size change_detection_threshold = 5 # Square the distance because during calculations no square root will be computed cd_thresh = change_detection_threshold**2 # Grab all of the points from the file. pc_a_file = laspy.file.File(files_path + prm["t1"][1], mode="r") # Grab all of the points from the file. pc_b_file = laspy.file.File(files_path + prm["t2"][1], mode='r') # This is the 1st prepared point cloud pc_a = (pc_a_file.x, pc_a_file.y, pc_a_file.z) print "Number of points in 1st point cloud:", len(pc_a[0]) # This is the 2nd prepared point cloud pc_b = (pc_b_file.x, pc_b_file.y, pc_b_file.z) print "Number of points in 2nd point cloud:", len(pc_b[0]) print "Start building the voxel grid" # Get the origin point that will be used to build the Voxel Grid, from the combined minimum extents origin_point = pc_parser.combined_extent(pc_a_file.header, pc_b_file.header) # Generate a Voxel Grid object, based on a voxel size and the origin corner point. voxel_grid = VoxelGrid(origin_point, change_detection_threshold) # Fill the grid with the points pc_parser.prepare_grid(voxel_grid, (pc_a, pc_b)) print "Start detecting 1st difference" # Detect 1st change order between point clouds and return the needed arrays diff_BA = pc_parser.detect_changes(voxel_grid, 1, 0, cd_thresh) if len(diff_BA[0]) > 0: # Prepare the file paths save_path = "{0}Point_Clouds\\temp\\t2t1_{1}.las".format( prm["t2"][3][0], diff_uid) print "1", save_path # Store the differences from the new point cloud to the old one pc_parser.store_diffs(diff_BA, pc_b_file, save_path) # Publish the new calculated differences command21 = prm["t2"][3][0] + 'Tools\\PotreeConverter_1.5RC_windows_64bit\\PotreeConverter.exe ' + \ save_path + ' -o ' + prm["t2"][3][1] + \ 'pointclouds\\AHN3-AHN2 --output-format LAZ --projection "+proj=somerc ' \ '+lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel ' \ '+towgs84=674.4,15.1,405.3,0,0,0,0 +units=m +no_defs" --incremental' process = os.popen(command21) process.close() # Close files pc_b_file.close() print "Start detecting 2nd difference" # Detect 2nd change order between point clouds and return the needed arrays diff_AB = pc_parser.detect_changes(voxel_grid, 0, 1, cd_thresh) if len(diff_AB[0]) > 0: # Prepare the file paths save_path = "{0}Point_Clouds\\temp\\t1t2_{1}.las".format( prm["t1"][3][0], diff_uid) print "2", save_path # Store the differences from the old point cloud to the new one pc_parser.store_diffs(diff_AB, pc_a_file, save_path) # Publish the new calculated differences sys_par[1] command12 = prm["t1"][3][0] + 'Tools\\PotreeConverter_1.5RC_windows_64bit\\PotreeConverter.exe ' \ + save_path + ' -o ' + prm["t1"][3][1] + \ 'pointclouds\\AHN2-AHN3 --output-format LAZ --projection "+proj=somerc ' \ '+lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel ' \ '+towgs84=674.4,15.1,405.3,0,0,0,0 +units=m +no_defs" --incremental' process = os.popen(command12) process.close() # Close files pc_a_file.close()
save_path = "../data/test_features/grid_size_" + str(grid_size) try: vector = np.load(save_path + "/feature_vector_" + str(i) + ".npy") except: break test_feature_vectors.append(vector) # Save training data if it doesn't exist. if len(feature_vectors) < 278: for i in range(1, 279): img = nib.load("../data/set_train/train_" + str(i) + ".nii") img_array = np.array(img.dataobj) fft = FourierTransform(img_array) fourier_transform_result = fft.return_output_array() grid = VoxelGrid(img_array, grid_size) fourier_grid = VoxelGrid(fourier_transform_result, grid_size) save_path = "../data/features/grid_size_" + str(grid_size) if not os.path.exists(save_path): os.makedirs(save_path) vector = fourier_grid.get_feature_vector() feature_vector = np.append(vector, grid.get_feature_vector()) feature_vectors.append(feature_vector) np.save(save_path + "/feature_vector_" + str(i), feature_vectors[i - 1]) print("Saved training feature vector #" + str(i)) # Save test data if it doesn't exist. if len(test_feature_vectors) < 138:
class GLWidget(QtOpenGL.QGLWidget): # Constants for referring to axis X_AXIS = 1 Y_AXIS = 2 Z_AXIS = 3 @property def floor_grid(self): return self._display_floor_grid @floor_grid.setter def floor_grid(self, value): self._display_floor_grid = value self.updateGL() @property def wireframe(self): return self._display_wireframe @wireframe.setter def wireframe(self, value): self._display_wireframe = value self.updateGL() @property def voxel_colour(self): return self._voxel_colour @voxel_colour.setter def voxel_colour(self, value): self._voxel_colour = value @property def background(self): return self._background_colour @background.setter def background(self, value): self._background_colour = value self.updateGL() @property def autoresize(self): return self.voxels.autoresize @autoresize.setter def autoresize(self, value): self.voxels.autoresize = value @property def voxel_edges(self): return self._voxeledges @voxel_edges.setter def voxel_edges(self, value): self._voxeledges = value self.updateGL() @property def grids(self): return self._grids # Our signals tool_activated = QtCore.Signal() tool_dragged = QtCore.Signal() tool_deactivated = QtCore.Signal() def __init__(self, parent=None): glformat = QtOpenGL.QGLFormat() glformat.setVersion(1,1) glformat.setProfile(QtOpenGL.QGLFormat.CoreProfile) QtOpenGL.QGLWidget.__init__(self, glformat, parent) # Test we have a valid context ver = QtOpenGL.QGLFormat.openGLVersionFlags() if not ver & QtOpenGL.QGLFormat.OpenGL_Version_1_1: raise Exception("Requires OpenGL Version 1.1 or above.") # Default values self._background_colour = QtGui.QColor("silver") self._display_wireframe = False self._voxel_colour = QtGui.QColor.fromHsvF(0,1.0,1.0) self._voxeledges = True # Mouse position self._mouse = QtCore.QPoint() # Default camera self.reset_camera(False) # zoom self._zoom_speed = 0.1 # Render floor grid? self._display_floor_grid = True # Our voxel scene self.voxels = voxel.VoxelData() # Grid manager self._grids = VoxelGrid( self.voxels ) # Used to track the z component of various mouse activity self._depth_focus = 1 # Reset the control and clear all data def clear(self): self.voxels.clear() self.refresh() # Force an update of our internal data def refresh(self): self.build_mesh() self.build_grid() self.updateGL() # Reset camera position to defaults def reset_camera(self, update = True): self._translate_x = 0 self._translate_y = 0 self._translate_z = -60 self._rotate_x = 0 self._rotate_y = 0 self._rotate_z = 0 if update: self.updateGL() # Initialise OpenGL def initializeGL(self): # Set background colour self.qglClearColor(self._background_colour) # Our polygon winding order is clockwise glFrontFace(GL_CW) # Enable depth testing glEnable(GL_DEPTH_TEST) # Enable backface culling glCullFace(GL_BACK) glEnable(GL_CULL_FACE) # Shade model glShadeModel(GL_SMOOTH) # Texture support glEnable(GL_TEXTURE_2D) # Load our texture pixmap = QtGui.QPixmap(":/images/gfx/texture.png") self._texture = self.bindTexture(pixmap) self.build_mesh() # Setup our lighting self.setup_lights() # Render our scene def paintGL(self): self.qglClearColor(self._background_colour) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() glTranslatef(self._translate_x,self._translate_y, self._translate_z) glRotated(self._rotate_x, 1.0, 0.0, 0.0) glRotated(self._rotate_y, 0.0, 1.0, 0.0) glRotated(self._rotate_z, 0.0, 0.0, 1.0) # Enable vertex buffers glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glEnableClientState(GL_COLOR_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) # Wireframe? if self.wireframe: glPolygonMode( GL_FRONT, GL_LINE ) # Bind our texture glBindTexture(GL_TEXTURE_2D, self._texture) # Describe our buffers glVertexPointer( 3, GL_FLOAT, 0, self._vertices) if self._voxeledges: glTexCoordPointer(2, GL_FLOAT, 0, self._uvs) else: glDisable(GL_TEXTURE_2D) glColorPointer(3, GL_UNSIGNED_BYTE, 0, self._colours) glNormalPointer(GL_FLOAT, 0, self._normals) # Render the buffers glDrawArrays(GL_TRIANGLES, 0, self._num_vertices) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_TEXTURE_COORD_ARRAY) glDisableClientState(GL_COLOR_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) if not self._voxeledges: glEnable(GL_TEXTURE_2D) # draw the _grids self.grids.paint() # Default back to filled rendering glPolygonMode( GL_FRONT, GL_FILL ) # Window is resizing def resizeGL(self, width, height): self._width = width self._height = height glViewport(0,0,width,height) glMatrixMode(GL_PROJECTION) glLoadIdentity() self.perspective(45.0, float(width) / height, 0.1, 300) glMatrixMode(GL_MODELVIEW) # Render scene as colour ID's def paintID(self): # Disable lighting glDisable(GL_LIGHTING) glDisable(GL_TEXTURE_2D) # Render with white background self.qglClearColor(QtGui.QColor.fromRgb(0xff, 0xff, 0xff)) # Ensure we fill our polygons glPolygonMode( GL_FRONT, GL_FILL ) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() glTranslatef(self._translate_x,self._translate_y, self._translate_z) glRotated(self._rotate_x, 1.0, 0.0, 0.0) glRotated(self._rotate_y, 0.0, 1.0, 0.0) glRotated(self._rotate_z, 0.0, 0.0, 1.0) # Enable vertex buffers glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_COLOR_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) # Describe our buffers glVertexPointer( 3, GL_FLOAT, 0, self._vertices) glColorPointer(3, GL_UNSIGNED_BYTE, 0, self._colour_ids) glNormalPointer(GL_FLOAT, 0, self._normals) # Render the buffers glDrawArrays(GL_TRIANGLES, 0, self._num_vertices) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_COLOR_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) # Set background colour back to original self.qglClearColor(self._background_colour) # Re-enable lighting glEnable(GL_LIGHTING) glEnable(GL_TEXTURE_2D) def perspective(self, fovY, aspect, zNear, zFar ): fH = math.tan( fovY / 360.0 * math.pi ) * zNear fW = fH * aspect glFrustum( -fW, fW, -fH, fH, zNear, zFar ) def setup_lights(self): glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glEnable(GL_COLOR_MATERIAL) # Build a mesh from our current voxel data def build_mesh(self): # Grab the voxel vertices (self._vertices, self._colours, self._normals, self._colour_ids, self._uvs) = self.voxels.get_vertices() self._num_vertices = len(self._vertices)//3 self._vertices = array.array("f", self._vertices).tostring() self._colours = array.array("B", self._colours).tostring() self._colour_ids = array.array("B", self._colour_ids).tostring() self._normals = array.array("f", self._normals).tostring() self._uvs = array.array("f", self._uvs).tostring() # Build floor grid def build_grid(self): self.grids.update_grid_plane() def mousePressEvent(self, event): self._mouse = QtCore.QPoint(event.pos()) if event.buttons() & QtCore.Qt.LeftButton: x, y, z, face = self.window_to_voxel(event.x(), event.y()) self.activate_tool(x, y, z, face) self.refresh() # Remember the 3d coordinates of this click mx, my, mz, d = self.window_to_world(event.x(), event.y()) mxd, myd, mzd, _ = self.window_to_world(event.x()+1, event.y(), d) self._htranslate = ((mxd - mx),(myd - my),(mzd - mz)) mxd, myd, mzd, _ = self.window_to_world(event.x(), event.y()+1, d) self._vtranslate = ((mxd - mx),(myd - my),(mzd - mz)) # Work out translation for x,y ax,ay = self.view_axis() if ax == self.X_AXIS: self._htranslate = abs(self._htranslate[0]) if ax == self.Y_AXIS: self._htranslate = abs(self._htranslate[1]) if ax == self.Z_AXIS: self._htranslate = abs(self._htranslate[2]) if ay == self.X_AXIS: self._vtranslate = abs(self._vtranslate[0]) if ay == self.Y_AXIS: self._vtranslate = abs(self._vtranslate[1]) if ay == self.Z_AXIS: self._vtranslate = abs(self._vtranslate[2]) self._depth_focus = d def mouseMoveEvent(self, event): # Screen units delta dx = event.x() - self._mouse.x() dy = event.y() - self._mouse.y() # Right mouse button held down - rotate if event.buttons() & QtCore.Qt.RightButton: self._rotate_x = self._rotate_x + dy self._rotate_y = self._rotate_y + dx self.updateGL() # Middle mouse button held down - translate if event.buttons() & QtCore.Qt.MiddleButton: # Work out the translation in 3d space self._translate_x = self._translate_x + dx * self._htranslate self._translate_y = self._translate_y + ((-dy) * self._vtranslate) self.updateGL() # Left mouse button held down if event.buttons() & QtCore.Qt.LeftButton: x, y, z, face = self.window_to_voxel(event.x(), event.y()) self.drag_tool(x, y, z, face) self.refresh() self._mouse = QtCore.QPoint(event.pos()) def mouseReleaseEvent(self, event): self._mouse = QtCore.QPoint(event.pos()) if event.button() == QtCore.Qt.LeftButton: x, y, z, face = self.window_to_voxel(event.x(), event.y()) self.deactivate_tool(x, y, z, face) self.refresh() def wheelEvent(self, event): if event.delta() > 0: self._translate_z *= 1+self._zoom_speed else: self._translate_z *= 1-self._zoom_speed self.updateGL() # Return voxel space x,y,z coordinates given x, y window coordinates # Also return an identifier which indicates which face was clicked on. # If the background was clicked on rather than a voxel, calculate and return # the location on the floor grid. def window_to_voxel(self, x, y): # We must invert y coordinates y = self._height - y # Render our scene (to the back buffer) using colour IDs self.paintID() # Grab the colour / ID at the coordinates c = glReadPixels( x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE) if type(c) is str: # This is what MESA on Linux seems to return # Grab the colour (ID) which was clicked on voxelid = ord(c[0])<<16 | ord(c[1])<<8 | ord(c[2]) else: # Windows seems to return an array voxelid = c[0][0][0]<<16 | c[1][0][0]<<8 | c[2][0][0] # Perhaps we clicked on the background? if voxelid == 0xffffff: x, y, z = self.plane_intersection(x, y) if x is None: return None, None, None, None return x, y, z, None # Decode the colour ID into x,y,z,face x = (voxelid & 0xfe0000)>>17 y = (voxelid & 0x1fc00)>>10 z = (voxelid & 0x3f8)>>3 face = voxelid & 0x07 # Return what we learned return x,y,z,face # Calculate the intersection between mouse coordinates and a plane def plane_intersection(self, x, y): # Unproject coordinates into object space nx,ny,nz = gluUnProject(x, y, 0.0) fx,fy,fz = gluUnProject(x, y, 1.0) # Calculate the ray near = Point3(nx, ny, nz) far = Point3(fx, fy, fz) ray = LineSegment3(near, far) # Retrieve the planes defined in the VoxelGrid object and iterate through them planes = [] for grid_plane in self._grids.get_grid_planes_list(): # check if the current plane is colliding. If not, then move on to the next if( not grid_plane.collision ): continue normal_x = 1 if grid_plane.plane == GridPlanes.X else 0 normal_y = 1 if grid_plane.plane == GridPlanes.Y else 0 normal_z = 1 if grid_plane.plane == GridPlanes.Z else 0 origins = { GridPlanes.X: lambda: self.voxels.voxel_to_world(grid_plane.offset-0, 0, 0)[0], GridPlanes.Y: lambda: self.voxels.voxel_to_world(0, grid_plane.offset-0, 0)[1], GridPlanes.Z: lambda: self.voxels.voxel_to_world(0, 0, grid_plane.offset-1)[2] } plane = Plane( Vector3( normal_x, normal_y, normal_z), origins[grid_plane.plane]() ) planes.append( plane ) intersection = None, None, None distance = sys.maxint for plane in planes: # Get intersection point intersect = plane.intersect(ray) if intersect: # Adjust to voxel space coordinates x, y, z = self.voxels.world_to_voxel(intersect.x, intersect.y, intersect.z) # Ignore out of bounds insections if not self.voxels.is_valid_bounds(x, y, z): continue length = near.distance(Point3(intersect.x, intersect.y, intersect.z)) if length < distance: intersection = int(x), int(y), int(round(z)) distance = length return intersection # Determine the axis which are perpendicular to our viewing ray, ish def view_axis(self): # Shoot a ray into the scene x1,y1,z1 = gluUnProject(self.width()//2, self.height()//2, 0.0) x2,y2,z2 = gluUnProject(self.width()//2, self.height()//2, 1.0) dx = abs(x2-x1) dy = abs(y2-y1) dz = abs(z2-z1) # The largest deviation is the axis we're looking down if dz >= dx and dz >= dy: return (self.X_AXIS, self.Y_AXIS) elif dy >= dx and dy >= dz: return (self.X_AXIS, self.Z_AXIS) return (self.Z_AXIS, self.Y_AXIS) # Convert window x,y coordinates into x,y,z world coordinates, also return # the depth def window_to_world(self, x, y, z = None): # Find depth y = self._height - y if z is None: z = glReadPixels( x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0] fx,fy,fz = gluUnProject(x, y, z) return fx,fy,fz,z # Convert x,y,z world coorindates to x,y window coordinates def world_to_window(self, x, y, z): x,y,z = gluProject(x, y, z) y = self._height - y return x,y def activate_tool(self, x, y, z, face): self.target = Target(self.voxels, x, y, z, face) self.tool_activated.emit() def drag_tool(self, x, y, z, face): self.target = Target(self.voxels, x, y, z, face) self.tool_dragged.emit() def deactivate_tool(self, x, y, z, face): self.target = Target(self.voxels, x, y, z, face) self.tool_deactivated.emit()