def alignphotos(): print("*** Started...Align Photos *** ", datetime.datetime.utcnow()) coord_system = PhotoScan.CoordinateSystem('EPSG::4326') chunk.crs = coord_system #chunk.matchPhotos(accuracy=config['accuracy'], preselection=PhotoScan.Preselection.GenericPreselection, filter_mask=False, keypoint_limit=40000, tiepoint_limit=10000) chunk.matchPhotos(accuracy=PhotoScan.Accuracy.LowestAccuracy, preselection=PhotoScan.Preselection.GenericPreselection, filter_mask=False, keypoint_limit=40000, tiepoint_limit=10000) chunk.alignCameras() if os.path.exists(marker_file) == True: print("marker file exist!") chunk.importMarkers(marker_file) if os.path.exists(reference_file) == True: print("reference file exist!") chunk.loadReference(reference_file, "csv", delimiter=';') chunk.optimizeCameras() for camera in chunk.cameras: camera.reference.enabled = False chunk.updateTransform() print("*** Finished - Align Photos ***")
def setCoordinateSystem(chunk, doc): ''' Установить систему координат :return: ''' chunk.crs = PhotoScan.CoordinateSystem(CK="EPSG::4326") chunk.updateTransform() doc.save()
def export_model(self): """ Export LAS and OBJ to path using the file name prefix #Texture file format is JPG for JPG input images and TIF for all others. """ for _ in self.chunks: #Texture JPG for now as Cloudcompare doesn't like the TIFF format ext = PhotoScan.ImageFormatJPEG """ext = _.cameras[0].label[-3:] if ext.upper() == 'JPG': ext = PhotoScan.ImageFormatJPEG else: ext = PhotoScan.ImageFormatTIFF""" if self.exp_crs == 0: crs = _.crs else: crs = PhotoScan.CoordinateSystem('EPSG::{}' .format(self.exp_crs)) #write log information with open(self.log, 'a+') as logfile: start_t = datetime.now() logfile.write('Exporting model {} at {} \n'. format(_, start_t.strftime('%H:%M:%S'))) logfile.write(' Export CRS: {}\n'. format(crs)) #create export file name if str(_)[8:-4] == 'Chunk': name = '' num = str(_)[-3] else: name = str(_)[8:-2] num = '' try: file = '{}{}_LAS{}.las'.format(self.prefix, name, num) _.exportPoints(path = os.path.join(self.path, file), format=PhotoScan.PointsFormatLAS, projection=crs) except RuntimeError as e: if str(e) == 'Null point cloud': print('There is no point cloud to export in chunk: {}' .format(_)) continue else: raise try: file = '{}{}_OBJ{}.obj'.format(self.prefix, name, num) _.exportModel(path = os.path.join(self.path, file), texture_format=ext, projection=crs) except RuntimeError as e: if str(e) == 'Null model': print('There is no model to export in chunk: {}'.format(_)) continue else: raise
def alignphotos(): print("*** Started...Align Photos *** ", datetime.datetime.utcnow()) coord_system = PhotoScan.CoordinateSystem('EPSG::4326') chunk.crs = coord_system chunk.matchPhotos(accuracy=PhotoScan.Accuracy.LowestAccuracy, preselection=PhotoScan.Preselection.GenericPreselection, filter_mask=False, keypoint_limit=4000, tiepoint_limit=500) chunk.alignCameras() chunk.optimizeCameras() doc.save(doc_name) PhotoScan.app.update() print("*** Finished - Align Photos ***")
def scale_cams(chunk, camdict, thd=[0.5, 0.7], lstring='_LC', d=0.4): ''' thd: Min and Max overlaping desired to select camera pairs for scalebars lstring: unique string that identify the name of the cameras as the ones on the left-hand side d: Distance between the centre of the lens from each camera ''' overlap = [] cams = {'right': [], 'left': []} chunk.decimateModel(100000) ## this is to minimise memory load for cam in chunk.cameras: if cam.transform: if cam.label.__contains__(camdict['lstring']): cams['left'].append(np.r_[cam.key, np.asarray(cam.center)]) else: cams['right'].append(np.r_[cam.key, np.asarray(cam.center)]) if chunk.crs == None: crs = PhotoScan.CoordinateSystem( 'LOCAL_CS["Local CS",LOCAL_DATUM["Local Datum",0],UNIT["metre",1]]' ) chunk.crs = crs #Find the closed camera pair and check that is a camera pair based on overlaping to set the scalebars for l in cams['left'][5::10]: lcam = l[1:] lcam_index = np.int(l[0]) rcams = np.asarray(cams['right']) rcams = rcams[:, 1:] rcam_index = np.int(cams['right'][closest_pair(lcam, rcams)][0]) scalebar = chunk.addScalebar(chunk.cameras[lcam_index], chunk.cameras[rcam_index]) scalebar.label = chunk.cameras[ lcam_index].label + " - " + chunk.cameras[rcam_index].label scalebar.reference.distance = camdict['cam_dist'] PhotoScan.app.update() chunk.updateTransform() #fine-tune scalebars based on image-pair overlapping. #Remove those scalebars where images are not overlapping enough or too much. #This avoid false pairs try: thisIOI = co.IOI(lcam_index, rcam_index, chunk) overlap = np.r_[overlap, thisIOI] if (thisIOI < camdict['overlap_threshold'][0] or thisIOI > camdict['overlap_threshold'][1]): chunk.remove(scalebar) except Exception as e: overlap = np.r_[ overlap, 0] #most likely, these are cameras which edge falls outside the chunk.remove(scalebar) pass return (overlap)
def photoscanProcess(root_path): #PhotoScan.app.messageBox('hello world! \n') PhotoScan.app.console.clear() ## construct the document class doc = PhotoScan.app.document ## save project #doc.open("M:/Photoscan/practise.psx") psxfile = root_path + 'practise.psx' doc.save(psxfile) print('>> Saved to: ' + psxfile) ## point to current chunk #chunk = doc.chunk ## add a new chunk chunk = doc.addChunk() ## set coordinate system # - PhotoScan.CoordinateSystem("EPSG::4612") --> JGD2000 chunk.crs = PhotoScan.CoordinateSystem("EPSG::4612") ################################################################################################ ### get photo list ### photoList = [] getPhotoList(root_path, photoList) #print (photoList) ################################################################################################ ### add photos ### # addPhotos(filenames[, progress]) # - filenames(list of string) – A list of file paths. chunk.addPhotos(photoList) ################################################################################################ ### align photos ### ## Perform image matching for the chunk frame. # matchPhotos(accuracy=HighAccuracy, preselection=NoPreselection, filter_mask=False, keypoint_limit=40000, tiepoint_limit=4000[, progress]) # - Alignment accuracy in [HighestAccuracy, HighAccuracy, MediumAccuracy, LowAccuracy, LowestAccuracy] # - Image pair preselection in [ReferencePreselection, GenericPreselection, NoPreselection] chunk.matchPhotos(accuracy=PhotoScan.LowAccuracy, preselection=PhotoScan.ReferencePreselection, filter_mask=False, keypoint_limit=0, tiepoint_limit=0) chunk.alignCameras() ################################################################################################ ### build dense cloud ### ## Generate depth maps for the chunk. # buildDenseCloud(quality=MediumQuality, filter=AggressiveFiltering[, cameras], keep_depth=False, reuse_depth=False[, progress]) # - Dense point cloud quality in [UltraQuality, HighQuality, MediumQuality, LowQuality, LowestQuality] # - Depth filtering mode in [AggressiveFiltering, ModerateFiltering, MildFiltering, NoFiltering] chunk.buildDenseCloud(quality=PhotoScan.LowQuality, filter=PhotoScan.AggressiveFiltering) ################################################################################################ ### build mesh ### ## Generate model for the chunk frame. # buildModel(surface=Arbitrary, interpolation=EnabledInterpolation, face_count=MediumFaceCount[, source ][, classes][, progress]) # - Surface type in [Arbitrary, HeightField] # - Interpolation mode in [EnabledInterpolation, DisabledInterpolation, Extrapolated] # - Face count in [HighFaceCount, MediumFaceCount, LowFaceCount] # - Data source in [PointCloudData, DenseCloudData, ModelData, ElevationData] chunk.buildModel(surface=PhotoScan.HeightField, interpolation=PhotoScan.EnabledInterpolation, face_count=PhotoScan.HighFaceCount) ################################################################################################ ### build texture (optional) ### ## Generate uv mapping for the model. # buildUV(mapping=GenericMapping, count=1[, camera ][, progress]) # - UV mapping mode in [GenericMapping, OrthophotoMapping, AdaptiveOrthophotoMapping, SphericalMapping, CameraMapping] #chunk.buildUV(mapping=PhotoScan.AdaptiveOrthophotoMapping) ## Generate texture for the chunk. # buildTexture(blending=MosaicBlending, color_correction=False, size=2048[, cameras][, progress]) # - Blending mode in [AverageBlending, MosaicBlending, MinBlending, MaxBlending, DisabledBlending] #chunk.buildTexture(blending=PhotoScan.MosaicBlending, color_correction=True, size=30000) ################################################################################################ ## save the project before build the DEM and Ortho images doc.save() ################################################################################################ ### build DEM (before build dem, you need to save the project into psx) ### ## Build elevation model for the chunk. # buildDem(source=DenseCloudData, interpolation=EnabledInterpolation[, projection ][, region ][, classes][, progress]) # - Data source in [PointCloudData, DenseCloudData, ModelData, ElevationData] chunk.buildDem(source=PhotoScan.DenseCloudData, interpolation=PhotoScan.EnabledInterpolation, projection=chunk.crs) ################################################################################################ ## Build orthomosaic for the chunk. # buildOrthomosaic(surface=ElevationData, blending=MosaicBlending, color_correction=False[, projection ][, region ][, dx ][, dy ][, progress]) # - Data source in [PointCloudData, DenseCloudData, ModelData, ElevationData] # - Blending mode in [AverageBlending, MosaicBlending, MinBlending, MaxBlending, DisabledBlending] chunk.buildOrthomosaic(surface=PhotoScan.ModelData, blending=PhotoScan.MosaicBlending, color_correction=True, projection=chunk.crs) ################################################################################################ ## auto classify ground points (optional) #chunk.dense_cloud.classifyGroundPoints() #chunk.buildDem(source=PhotoScan.DenseCloudData, classes=[2]) ################################################################################################ doc.save()
chunk.elevation = float( ProcParams.photoscan.referencesettingsmiscellaneousgroundalt) # Add Trajectory if ProcParams.importfiles.trajectoryfilename != "": trajectoryname = rootdir + "\\" + ProcParams.importfiles.rootname + "\\" + ProcParams.importfiles.trajectoryfilename chunk.loadReference(trajectoryname) # Add Markers if ProcParams.importfiles.controlfilename != "": markername = rootdir + "\\" + ProcParams.importfiles.rootname + "\\" + ProcParams.importfiles.controlfilename chunk.importMarkers(markername) # DEFINE COORDINATE SYSTEM if not (ProcParams.importfiles.epsg == ''): doc.chunk.crs = PhotoScan.CoordinateSystem("EPSG::" + ProcParams.importfiles.epsg) else: print("Using PhotoScan Default CRS") msg = "Added Trajectory/Reference Data" proctime.write( msg.ljust(40) + " , " + strftime("%Y-%m-%d %H:%M:%S", gmtime()) + " , " + elaptime(lasttime, time.time()) + "\n") lasttime = time.time() proctime.flush() ## Do Sparse Alignment # Match Photos if ProcParams.photoscan.aligngeneralaccuracy == 'lowest': matchacc = PhotoScan.Accuracy.LowestAccuracy elif ProcParams.photoscan.aligngeneralaccuracy == 'low':
def local_coordinates(chunk): chunk.crs = PhotoScan.CoordinateSystem( 'LOCAL_CS["Local CS",LOCAL_DATUM["Local Datum",0],UNIT["metre",1]]')
<%=orthoRes%> <%=preset_RU%> <%=preset_RE%> <%=preset_PA%> <%=loop_RU%> <%=loop_RE%> <%=loop_PA%> if sys.argv[1:]: goal = sys.argv[1] if sys.argv[2:]: imgPath = sys.argv[2] if goal == "ortho": # define short variables crs = PhotoScan.CoordinateSystem("EPSG::32632") doc = PhotoScan.app.document chunk = doc.addChunk() PSPCF = PhotoScan.PointCloud.Filter() count = 0 # creating image list image_list = glob.glob(imgPath + "/*.JPG") print(image_list) # load images chunk.addPhotos(image_list) # load exif data chunk.loadReferenceExif() # create project doc.save(imgPath + "/" + projName) # reopen it doc.open(imgPath + "/" + projName)
def script_setup(): file_loc = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) input_file_B = (file_loc + "/" + "input_file.csv") input_file_B = input_file_B.replace('\\', '/') print (input_file_B) var_list = [] with open(input_file_B, 'r') as f: mycsv = csv.reader(f) for row in mycsv: colB = row[1] var_list.append(colB) home = var_list[1] doc_title = var_list[2] datadir = var_list[3] coord_sys = var_list[4] marker_coords = var_list[5] marker_crs = var_list[6] Est_img_qual = var_list[8] img_qual_thresh = var_list[9] spc_quality = var_list[10] reproj_err_limit = var_list[32] rolling_shutter = var_list[37] print (home) print(doc_title) print (datadir) print (coord_sys) name = "/" + doc_title + ".psx" doc = PS.app.document PS.app.gpu_mask = 2 ** len(PS.app.enumGPUDevices()) - 1 # activate all available GPUs if PS.app.gpu_mask <= 1: PS.app.cpu_enable = True # Enable CPU for GPU accelerated processing (faster with 1 no difference with 0 GPUs) elif PS.app.gpu_mask > 1: PS.app.cpu_enable = False # Disable CPU for GPU accelerated tasks (faster when multiple GPUs are present) doc.save(home+name) # Locate and add photos photos = os.listdir(datadir) # Get the photos filenames photos = [os.path.join(datadir, p) for p in photos] # convert to full paths chunk = PS.app.document.addChunk() # create a chunk chunk.addPhotos([photos]) # add photos to chunk if rolling_shutter == 'TRUE': chunk.sensors[0].rolling_shutter = True # Option to enable Rolling shutter compensation new_crs = PS.CoordinateSystem(coord_sys) # define desired Coordinate System try: for camera in chunk.cameras: # set the coordinates for cameras camera.reference.location = new_crs.project(chunk.crs.unproject(camera.reference.location)) except Exception: print ("Images do not have projection data... No Worries! continue without!") # Optional import of markers if desired... if marker_coords == "NONE": # if no markers are given then pass pass else: chunk.loadReference(marker_coords, columns="nxyzXYZ", delimiter=",", group_delimiters=False, # if a path is given markers are added skip_rows=1, ignore_labels=False, create_markers=True, threshold=0.1) if marker_crs == coord_sys: # if marker and project crs match then pass otherwise convert marker crs pass else: for marker in chunk.markers: # This needs testing but should theoretically work... marker.reference.location = new_crs.project(chunk.crs.unproject(marker.reference.location)) chunk.crs = new_crs # set project coordinate system doc.save(home + name) orig_n_cams, n_filter_removed, perc_filter_removed, real_qual_thresh = preprocess(Est_img_qual, img_qual_thresh, chunk) doc.save(home + name) points, projections = build_SPC(chunk, spc_quality) total_points, perc_ab_thresh, nselected = filter_reproj_err(chunk, reproj_err_limit) n_not_aligned = ref_setting_setup(doc, points, projections, home, name) export_settings(orig_n_cams, n_filter_removed, perc_filter_removed, real_qual_thresh, n_not_aligned, total_points, nselected, home, doc_title) # SAVE DOCUMENT doc.save(home + name) if perc_ab_thresh > 20: print ("-------------------------------------------------------------") print ("WARNING >20% OF POINTS ABOVE REPROJECTION ERROR THRESHOLD!!!!") print ("-------------------------------------------------------------") # Get Execution Time... print ("Total Time: " + str(datetime.now() - startTime)) # GET TOTAL TIME
import PhotoScan import os app = PhotoScan.app filelist = app.getOpenFileNames("Select Images", "Images(*.jpg)") chunk = app.document.addChunk() chunk.addPhotos(filelist) for camera in chunk.cameras: camera.reference.enabled = False chunk.crs = PhotoScan.CoordinateSystem() # chunk.crs = PhotoScan.CoordinateSystem('LOCAL_CS["Local CS",LOCAL_DATUM["Local Datum",0],UNIT["metre",1]]') chunk.matchPhotos(accuracy=PhotoScan.HighAccuracy, generic_preselection=True,reference_preselection=False) chunk.alignCameras() # PhotoScan.LowQuality chunk.buildDepthMaps(quality=PhotoScan.HighQuality, filter=PhotoScan.AggressiveFiltering) chunk.buildDenseCloud() tempPointCloudPath = os.path.join(os.path.dirname(filelist[0]),"pc.txt") chunk.exportPoints(tempPointCloudPath, format= PhotoScan.PointsFormat.PointsFormatXYZ, binary=False, precision=6, normals=False, colors=False) f = open(tempPointCloudPath) pointcloud = [] for line in f: point = list(map(lambda x: float(x), line.split())) pointcloud.append(point) f.close()
def __init__(self, parent): #_____________Пременные уровня класса___________ self.OUT_dir = '' #выходная дирректория self.orthoBounds = [] # ВЫХОДНАЯ ПРОЕКЦИЯ по умолчанию #out_crs='PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' self.out_crs = PhotoScan.CoordinateSystem( 'PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' ) #out_crs=PhotoScan.CoordinateSystem('PROJCS["WGS 84 / UTM zone 38N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",45],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32638"]]') self.crsShapes = PhotoScan.CoordinateSystem( 'PROJCS["WGS 84 / UTM zone 37N",GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32637"]]' ) self.DATA_OK = 0 #print ('orthoBounds=',len(self.orthoBounds)) #формат массива:0-имя ортофото, 1-Xmin, 2-Ymin, 3-sizeX, 4-sizeY, 5-ID полигона #__________________________________________________ QDialog.__init__(self, parent) self.setWindowTitle("Экспорт Орто по разграфке") #Заголвок окна self.resize(500, 250) #размер окна self.txt_comment = QLabel( " Модуль экспортирует ортофото и DEM из фотоскана по нарезке. \ Нарезка в текстовом файле: название листа, координаты нижнего левого угла, размеры. \n Проекция нарезки должна совпадать с проекцией выходного ортофотоплана.\ Листы делятся по нарезке, а внутри нарезки по блокам, размеры задаются. ФОРМАТ JPG \n При импорте SHP должно быть текстовое поле NAME \n \ Адрес сервера: " + ServerIP + " меняем в теле программы. Ваша версия фотоскана: " + PH_version + " \n") self.txt_comment.setWordWrap(True) self.now_prj = QLabel(str(self.out_crs)) self.select_prj = QPushButton("Выберете проекцию") #(" открыть ") self.select_prj.setFixedSize(170, 26) self.TXT_dif_pix = QLabel("<B>Размер пикселя: </B>") self.TXT_dif_pix.setFixedSize(170, 26) self.dif_pix = QLineEdit() self.dif_pix.setText('0.1') # Задает размер пикселя по умолчанию self.dif_pix.setFixedSize(100, 26) items_bloksize = ('5000', '8192', '10000', '15000', '20000', '25000', '29999', 'Full') # список с размерами тайлов #items_bloksize = {5000:5000, 8192:8192, 10000:10000, 15000:15000, 20000:20000, 25000:25000, 29999:29999} self.TXT_block_size = QLabel("<B>Размер блока: </B>", ) self.TXT_block_size.setFixedSize(170, 26) self.block_size = QComboBox() self.block_size.setFixedSize(100, 26) self.block_size.addItems(items_bloksize) self.block_size.setCurrentIndex( 1) #Устанавливает по умолчанию второе значение из списка - 8192 self.TXT_SHPname = QLabel("Файл разграфки SHP (NAME,poligons)") self.SHPname = QPushButton( "Выберете файл разграфки SHP") #(" открыть ") self.SHPname.setFixedSize(170, 26) self.TXT_filename = QLabel( "Файл разграфки TXT(имя; X0; Y0; sizeX; SizeY)") self.filename = QPushButton("Выберете Файл разграфки") #(" открыть ") self.filename.setFixedSize(170, 26) self.TXT_CheckOrthoDem = QLabel("Вид выходной продукции") self.TXT_CheckOrthoDem.setFixedSize(170, 26) self.CheckOrtho_Radio = QRadioButton("Ортофото") self.CheckOrtho_Radio.setChecked(True) self.CheckDem_Radio = QRadioButton("ДЕМ") self.TXT_OUTFOLDER = QLabel("Выходная дирректория") self.OUTFOLDER = QPushButton("Выберете дирректорию") #(" открыть ") self.OUTFOLDER.setFixedSize(170, 26) items_format = ( 'JPG', 'TIF' ) # список форматов, ПРИ выборе ДЕМ будет выбран второй формат - внимательно при изменении списка!!! self.file_format = QComboBox() self.file_format.setFixedSize(50, 26) self.file_format.addItems(items_format) self.file_format.setCurrentIndex( 0) #Устанавливает по умолчанию первое значение self.TXT_checkExportOrtho = QLabel("Построить ортофото:") # Ортофото self.TXT_checkExportOrtho.setFixedSize(170, 26) self.checkExportOrtho = QCheckBox() self.checkExportOrtho.setChecked(False) self.GoGo = QPushButton("Экспорт локально") #(" Экспорт локально ") self.GoGo.setFixedSize(170, 26) self.GoGo.setDisabled(True) self.GoGoNet = QPushButton("Экспорт по сети") #(" Экспорт по сети ") self.GoGoNet.setFixedSize(170, 26) self.GoGoNet.setDisabled(True) hbox0 = QHBoxLayout() hbox0.addWidget(self.txt_comment, alignment=0) hbox1 = QHBoxLayout() hbox1.addWidget(self.select_prj, alignment=0) hbox1.addWidget(self.now_prj, alignment=0) hbox2 = QHBoxLayout() hbox2.addWidget(self.TXT_block_size, alignment=1) hbox2.addWidget(self.block_size, alignment=1) hbox3 = QHBoxLayout() hbox3.addWidget(self.TXT_dif_pix, alignment=1) hbox3.addWidget(self.dif_pix, alignment=1) hbox4 = QHBoxLayout() #hbox4.addStretch(1) hbox4.addWidget(self.SHPname, alignment=0) hbox4.addWidget(self.TXT_SHPname, alignment=0) hbox5 = QHBoxLayout() #hbox5.addStretch(1) hbox5.addWidget(self.filename, alignment=0) hbox5.addWidget(self.TXT_filename, alignment=0) hbox51 = QHBoxLayout() hbox51.addWidget(self.TXT_CheckOrthoDem, alignment=0) hbox51.addWidget(self.CheckOrtho_Radio, alignment=0) hbox51.addWidget(self.CheckDem_Radio, alignment=0) hbox6 = QHBoxLayout() #hbox5.addStretch(1) hbox6.addWidget(self.OUTFOLDER, alignment=0) hbox6.addWidget(self.TXT_OUTFOLDER, alignment=0) hbox6.addWidget(self.file_format, alignment=0) hbox7 = QHBoxLayout() #build ortho hbox7.addWidget(self.TXT_checkExportOrtho, alignment=0) hbox7.addWidget(self.checkExportOrtho, alignment=0) hbox8 = QHBoxLayout() hbox8.addWidget(self.GoGo, stretch=0, alignment=0) hbox8.addWidget(self.GoGoNet, stretch=0, alignment=0) vbox = QVBoxLayout() #Определяем вбокс и забиваем его Нбоксами #vbox.addStretch(1) vbox.addLayout(hbox0) vbox.addLayout(hbox1) vbox.addLayout(hbox2) vbox.addLayout(hbox3) vbox.addLayout(hbox4) vbox.addLayout(hbox5) vbox.addLayout(hbox51) #выбор, что строить орто или дем vbox.addLayout(hbox6) #Функция построения ортофото спрятана, поскольку работает не стабильно и построение ортофото для каждого листа в сумме занимает очень много времени, #гораздо больше, чем один раз построить ортофото для всех #vbox.addLayout(hbox7) #build ortho vbox.addLayout(hbox8) self.setLayout(vbox) self.select_prj.clicked.connect(self.set_projection) self.SHPname.clicked.connect(self.input_razgr_SHPname) self.filename.clicked.connect(self.input_razgr_name) self.OUTFOLDER.clicked.connect(self.input_out_dir) self.GoGo.clicked.connect(self.ortho_local) self.GoGoNet.clicked.connect(self.ortho_net) #Организация блокировки интерфейса для радио кнопок self.CheckOrtho_Radio.clicked.connect(self.CheckOrtho_Radio_DO) self.CheckDem_Radio.clicked.connect(self.CheckDem_Radio_DO) #____________ self.checkExportOrtho.clicked.connect( self.PrintChkStat) #Функция для проверки работы чека #self.WindowContextHelpButtonHint.clicked.connect(self.prog_hint) #self.WindowTitleHint.clicked.connect(self.prog_hint) self.exec()
def __init__(self, epsg): print("InnoPAM") self.my_crs = PhotoScan.CoordinateSystem('EPSG::%s' % str(epsg))
#Need to set the following appropriately #Path to photos #photo_fn_path = "/tmp/export" photo_fn_path = "/Volumes/SHEAN_PHOTO/photo/20140825_MammothTerraces_SfM/export_orig" photo_fn_ext = "*.jpg" #Path to ground control file, can contain orientation gc_fn = "/tmp/gcp.txt" #Path to calibration file cal_fn = "/tmp/D800_cal.xml" #This is the base fn for output files #out_fn = "/tmp/test" out_fn = os.path.join(photo_fn_path, "test") #Define input coordinate system as WGS84 in_crs = PhotoScan.CoordinateSystem() in_crs.init("EPSG::4326") #Define output coordinate system as UTM 10N, WGS84 out_crs = PhotoScan.CoordinateSystem() #out_crs.init("EPSG::32610") #This is Yellowstone out_crs.init("EPSG::32612") #Add timestamp print("Started") #Create project file doc = PhotoScan.app.document #*** #NOTE: the following (loading photos, ground control, calibration, etc.) can be done manually
def process2(showReady=True): try: saveTimestamp("process2.01") ts = time.time() settings = QtCore.QSettings() print(u"[[processing2.start]]") saveTimestamp("process2.02") doc = PhotoScan.app.document activeChunk = doc.activeChunk if doc == None or activeChunk == None: PhotoScan.app.messageBox(u"[[error.noDocChunk]]") return False doc.meta['mavinci.plugin.release'] = mavinciRelease doc.meta['mavinci.plugin.exportHeaderCore'] = exportHeader qual = doc.meta['mavinci.quality'] resolution = float(doc.meta['mavinci.resolution']) accuracy = float(doc.meta['mavinci.camAccuracy']) print(u"[[gpsAccuracyAssumption]]" % (accuracy)) mavinciOptimize(False) saveTimestamp("process2.10") if qual != 'low': doc.save() saveTimestamp("process2.11") testOp( activeChunk.buildDenseCloud( quality=qual, gpu_mask=int(settings.value('main/opencl_mask', 0)), cpu_cores_inactive=int( settings.value('main/opencl_cores_inactive', 0))), u"[[buildDenseCloud]]") saveTimestamp("process2.12") #activeChunk.buildDepth(quality=qual,gpu_mask=1, cpu_cores_inactive=1) #activeChunk.buildModel(object='height field', geometry='sharp', faces=0) testOp( doc.activeChunk.buildModel(surface='height field', source='dense', interpolation='enabled', faces=qual), u"[[buildModel]]") saveTimestamp("process2.13") doc.save() saveTimestamp("process2.14") testOp( doc.activeChunk.buildTexture(mapping='orthophoto', blending='mosaic', size=4096), u"[[buildTexture]]") saveTimestamp("process2.15") doc.save() saveTimestamp("process2.16") else: testOp( doc.activeChunk.buildModel(surface='height field', source='sparse', interpolation='enabled', faces=qual), u"[[buildModel]]") saveTimestamp("process2.18") testOp( doc.activeChunk.buildTexture(mapping='orthophoto', blending='mosaic', size=2048), u"[[buildTexture]]") saveTimestamp("process2.19") saveTimestamp("process2.20") crs = PhotoScan.CoordinateSystem() projection = PhotoScan.GeoProjection() #chunk projection in WGS84 crs.init(doc.meta['mavinci.wkt']) projection.init(doc.meta['mavinci.wkt']) folder = os.path.abspath(os.path.join(doc.path, os.pardir)) #we take coordinates of first photo (you can add a check that it's aligned), #then take small horizontal vectors along OX and OY #and calculate their orgProjection = doc.activeChunk.ground_control.projection doc.activeChunk.ground_control.projection = projection doc.activeChunk.ground_control.apply() crd = doc.activeChunk.ground_control.locations.items( )[0][1].coord #coordinates of first photo #longitude v1 = PhotoScan.Vector((crd[0], crd[1], 0)) v2 = PhotoScan.Vector((crd[0] + 0.01, crd[1], 0)) vm1 = doc.activeChunk.projection.unproject(v1) vm2 = doc.activeChunk.projection.unproject(v2) res_x = (vm1 - vm2).norm() * 100 #latitude v2 = PhotoScan.Vector((crd[0], crd[1] + 0.01, 0)) vm2 = doc.activeChunk.projection.unproject(v2) doc.activeChunk.ground_control.projection = orgProjection doc.activeChunk.ground_control.apply() res_y = (vm1 - vm2).norm() * 100 pixel_x = pixel_y = resolution #export resolution 50cm/pix d_x = pixel_x / res_x d_y = pixel_y / res_y print(u"d_x=%e d_y=%e" % (d_x, d_y)) vertices = activeChunk.model.vertices maxSamples = 100000 step = 1 if len(vertices) > maxSamples * step: step = int(len(vertices) / maxSamples) xmin = float('inf') xmax = -1 * float('inf') ymin = float('inf') ymax = -1 * float('inf') for i in range(0, len(vertices), step): v = vertices[i].coord v.size = 4 v.w = 1 v_t = activeChunk.transform * v v_t.size = 3 v_new = activeChunk.crs.project(v_t) if v_new.x < xmin: xmin = v_new.x if v_new.x > xmax: xmax = v_new.x if v_new.y < ymin: ymin = v_new.y if v_new.y > ymax: ymax = v_new.y print("x=%f < %f y=%f < %f" % (xmin, xmax, ymin, ymax)) v0 = PhotoScan.Vector((xmin, ymin, 0)) vX = PhotoScan.Vector((xmax, ymin, 0)) vY = PhotoScan.Vector((xmin, ymax, 0)) vm0 = doc.activeChunk.projection.unproject(v0) vmX = doc.activeChunk.projection.unproject(vX) vmY = doc.activeChunk.projection.unproject(vY) size_x = (vm0 - vmX).norm() size_y = (vm0 - vmY).norm() print("x-size=%f m y-size=%f m" % (size_x, size_y)) maxPix = 30000 maxPixDem = maxPix blockOffset = 0.2 pixX = math.ceil(size_x / resolution) pixY = math.ceil(size_y / resolution) pixXdem = math.ceil(size_x / (2 * resolution)) pixYdem = math.ceil(size_y / (2 * resolution)) print("x-pix=%i y-pix=%i" % (pixX, pixY)) print("x-pixDEM=%i y-pixDEM=%i" % (pixXdem, pixYdem)) blockCountX = math.ceil(pixX / maxPix + blockOffset) blockCountY = math.ceil(pixY / maxPix + blockOffset) blockCountXdem = math.ceil(pixXdem / maxPixDem + blockOffset) blockCountYdem = math.ceil(pixYdem / maxPixDem + blockOffset) print("blockCount x=%i y=%i" % (blockCountX, blockCountY)) print("blockCountDEM x=%i y=%i" % (blockCountXdem, blockCountYdem)) doc.meta['mavinci.blockCount.ortho'] = "%i:%i" % (blockCountX, blockCountY) doc.meta['mavinci.blockCount.dem'] = "%i:%i" % (blockCountXdem, blockCountYdem) blockw = math.ceil(pixX / blockCountX) blockh = math.ceil(pixY / blockCountY) blockwDEM = math.ceil(pixXdem / blockCountXdem) blockhDEM = math.ceil(pixYdem / blockCountYdem) print("block w=%i h=%i" % (blockw, blockh)) print("blockDEM w=%i h=%i" % (blockwDEM, blockhDEM)) reportPath = os.path.join(folder, 'report.pdf') saveTimestamp("process2.21") testOp(activeChunk.exportReport(reportPath), u"[[exportReport]]") saveTimestamp("process2.22") openFile(reportPath) saveTimestamp("process2.23") if blockCountX > 1 or blockCountY > 1: testOp( activeChunk.exportOrthophoto( os.path.join(folder, 'ortho.tif'), format='tif', blending='mosaic', color_correction=doc.meta['mavinci.enableColCorrection'] != '0', projection=crs, dx=d_x, dy=d_y, write_kml=False, write_world=True, blockw=blockw, blockh=blockh), u"[[exportOrthophoto]]") else: testOp( activeChunk.exportOrthophoto( os.path.join(folder, 'ortho.tif'), format='tif', blending='mosaic', color_correction=doc.meta['mavinci.enableColCorrection'] != '0', projection=crs, dx=d_x, dy=d_y, write_kml=False, write_world=True), u"[[exportOrthophoto]]") saveTimestamp("process2.24") if blockCountXdem > 1 or blockCountYdem > 1: testOp( activeChunk.exportDem(os.path.join(folder, 'dem.tif'), format='tif', projection=crs, dx=2 * d_x, dy=2 * d_y, write_world=True, blockw=blockwDEM, blockh=blockhDEM), u"[[exportDem]]") else: testOp( activeChunk.exportDem(os.path.join(folder, 'dem.tif'), format='tif', projection=crs, dx=2 * d_x, dy=2 * d_y, write_world=True), u"[[exportDem]]") saveTimestamp("process2.25") doc.save() saveTimestamp("process2.26") openFile(folder) saveTimestamp("process2.27") t = str(datetime.timedelta(seconds=round(time.time() - ts))) print(u"[[processing2.ready]]" % t) if showReady: PhotoScan.app.messageBox(u"[[processing2.ready]]" % t) return True except (KeyboardInterrupt, SystemExit): print('>>> INTERRUPTED BY USER <<<') return False except: e = sys.exc_info()[0] print(e) print('>>> traceback <<<') traceback.print_exc() print('>>> end of traceback <<<') PhotoScan.app.messageBox(u"[[error]]") return False
def main(root_path, image_folder): # PhotoScan.app.messageBox('hello world! \n') # PhotoScan.app.console.clear() # PhotoScan.app.gpu_mask = 1 """1: creat project""" doc = createOrOpenProject(root_path, image_folder) """2: creat chunk""" chunk = PhotoScan.Chunk if len(doc.chunks) > 0: chunk = doc.chunk logAction("Using the existing chunk '{}'".format(chunk.label)) else: chunk = doc.addChunk() chunk.crs = PhotoScan.CoordinateSystem("EPSG::4326") logAction("Created the new chunk '{}'".format(chunk.label)) if len(chunk.cameras) > 0: logAction( "Skipping adding photos and aligning cameras because chunk already has {} cameras" .format(len(chunk.cameras))) else: logAction("Started adding photos") t = datetime.datetime.now() addPhotos(chunk, image_folder) logAction("Added photos ({})".format(datetime.datetime.now() - t)) logAction("Started photos alignment") t = datetime.datetime.now() """3: alignPhotos""" alignPhotos(chunk) logAction("Aligned photos ({})".format(datetime.datetime.now() - t)) saveProject(doc) """4:Create point cloud""" if chunk.dense_cloud is None: logAction("Started buildling dense cloud") t = datetime.datetime.now() buildDenseCloud(chunk) logAction("Built dense cloud ({})".format(datetime.datetime.now() - t)) saveProject(doc) else: logAction( "Skipping dense cloud build because chunk already has {}".format( chunk.dense_cloud)) """5:buildsource""" logAction("Started buildling source") t = datetime.datetime.now() buildsource(chunk) logAction("Built source ({})".format(datetime.datetime.now() - t)) saveProject(doc) """6: buildtexture""" logAction("Started buildling texture") t = datetime.datetime.now() buildtexture(chunk) logAction("Built texture ({})".format(datetime.datetime.now() - t)) saveProject(doc) """7: buildorthomosaic""" logAction("Started buildling orthomosaic") t = datetime.datetime.now() buildOrtho(chunk) logAction("Built orthomosaic ({})".format(datetime.datetime.now() - t)) saveProject(doc) """8: exporting orthomosaic""" logAction("Started exporting orthomosaic") t = datetime.datetime.now() out_image_name = image_name(image_folder) exportOrtho(chunk, root_path, out_image_name) logAction("Exported orthomosaic ({})".format(datetime.datetime.now() - t))
def generate3D(filePath): fullPathPhotoDirectoryName = filePath # Define: AlignPhotosAccuracy ["high", "medium", "low"] #change me print("\n**enum gpu devices", PhotoScan.app.enumGPUDevices()) print("\n**gpu mask ", PhotoScan.app.gpu_mask) TireAuditDataRoot = os.path.dirname( os.path.dirname(fullPathPhotoDirectoryName)) + "\\" #1 PhotoScanInputGCPFileTireAuditMarkers=generate_3DSettings.photoScanGCPFile #1 PhotoScanInputGCPFileAgisoftMarkers=TireAuditDataRoot+"gcp_agisoft.csv" #1 PhotoScanInputGCPFileAgisoftMarkers=TireAuditDataRoot+"foo4.txt" PhotoScanInputCalibFile = generate_3DSettings.photoScanCalibrationFile #fdebug.write("\n ********************* TireAuditDataRoot PhotoScanInputCalibFile PhotoScanInputGCPFileAgisoftMarkers PhotoScanInputGCPFileAgisoftMarkers PhotoScanInputCalibFile\n ",TireAuditDataRoot , PhotoScanInputCalibFile , PhotoScanInputGCPFileAgisoftMarkers, PhotoScanInputGCPFileAgisoftMarkers ,PhotoScanInputCalibFile) PhotoScanPlyFile = fullPathPhotoDirectoryName + "\\" + generate_3DSettings.photoScanPlyName PhotoScanLogFile = fullPathPhotoDirectoryName + "\\" + generate_3DSettings.photoScanLogName PhotoScanDebugFile = fullPathPhotoDirectoryName + "\\" + generate_3DSettings.photoScanDebugName PhotoScanProjectFile = fullPathPhotoDirectoryName + "\\" + generate_3DSettings.photoScanProjectName PhotoScanReprojectionErrorsFile = fullPathPhotoDirectoryName + "\\" + generate_3DSettings.photoScanReprojectionErrorsName #PhotoScanMarkerFile = fullPathPhotoDirectoryName+"\\"+generate_codesSettings.markerInformationPixelToCode #fdebug.write("\n*********** Checking for %s \n", PhotoScanProjectFile) # if path already has a psz file in exit then go onto nex directory if os.path.exists(PhotoScanProjectFile): #fdebug.write("\n*********** already proceessed %s \n", PhotoScanProjectFile) exit fdebug = open(PhotoScanDebugFile, 'w') flog = open(PhotoScanLogFile, 'w') start = time.time() #####pattern = 'IMG_*[02468].JPG' pattern = 'IMG_*' #print 'Pattern :', pattern print("abc") #files = os.listdir('.') files = os.listdir(fullPathPhotoDirectoryName) photoList = [] for filename in fnmatch.filter(files, pattern): #print ('Filename: %-25s %s' % (name, fnmatch.fnmatch(name, pattern)) ) #item = fullPathPhotoDirectoryName+"\\"+filename item = os.path.join(fullPathPhotoDirectoryName, filename) photoList.append(item) print("\n777 Photolist is ", photoList) doc = PhotoScan.Document() chunk = doc.addChunk() chunk.crs = PhotoScan.CoordinateSystem( 'LOCAL_CS["Local Coordinates",LOCAL_DATUM["Local Datum",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]' ) chunk.label = "New ChunkB" cameraDictionary = {} user_calib = PhotoScan.Calibration() success = user_calib.load(PhotoScanInputCalibFile) print("\n success loading calib file ", success) sensor = chunk.addSensor( ) #creating camera calibration group for the loaded image sensor.label = "Calibration Group 1" sensor.type = PhotoScan.Sensor.Type.Frame #sensor.width = camera.photo.image().width #sensor.height = camera.photo.image().height sensor.width = 5312 sensor.height = 2988 sensor.fixed = True sensor.user_calib = user_calib #sensor.width = 3264 #1 chunk.marker_projection_accuracy=0.0002 for i, filepath in enumerate(photoList): fdebug.write("\nxxxxxxxx filepath" + " " + filepath) camera = chunk.addCamera() camera.sensor = sensor pos = filepath.find("IMG") img = filepath[pos:] #cameraDictionary[img]=i cameraDictionary[img] = camera.key camera.open(filepath) #camera.open("c:\\Projects\\123DCatch\\Tires_25982510_B_Samsung6ChoppedExampleForTesting\\A\\IMG_14.JPG") camera.label = img #fdebug.write("\n filepath key", filepath, camera.key,camera.photo.image().width,camera.photo.image().height) fdebug.write("\n filepath key" + " " + filepath + " " + str(camera.key) + " " + camera.photo.path) fdebug.write("\n^^^^^^^^^^ Camera Dictionary" + " " + str(cameraDictionary)) fdebug.write("\n PhotoList &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n" + " " + str(photoList)) fdebug.write("hello") templateName = fullPathPhotoDirectoryName + "\\" + "M{filename}.JPG" #templateName=fullPathPhotoDirectoryName+ "\\" + "M{filename}.JPG" #successMask=chunk.importMasks(path=templateName,method='file',tolerance=10) successMask = chunk.importMasks( path=templateName, source=PhotoScan.MaskSourceFile, operation=PhotoScan.MaskOperationReplacement, tolerance=10, cameras=chunk.cameras) print( "\n***********************&&&&&&&&&&&&&&&&& successMask ************", successMask) #ALIGN PHOTOS fdebug.write("---Aligning photos ...") fdebug.write("Accuracy: " + generate_3DSettings.matchAccuracy) fdebug.write("\nBefore Matching **** \n") if (generate_3DSettings.matchAccuracy == "Low"): accuracyMatch = PhotoScan.Accuracy.LowAccuracy elif (generate_3DSettings.matchAccuracy == "High"): accuracyMatch = PhotoScan.Accuracy.HighAccuracy else: accuracyMatch = PhotoScan.Accuracy.MediumAccuracy if (generate_3DSettings.modelAccuracy == "Ultra"): accuracyModel = PhotoScan.Quality.UltraQuality elif (generate_3DSettings.modelAccuracy == "High"): accuracyModel = PhotoScan.Quality.HighQuality elif (generate_3DSettings.modelAccuracy == "Low"): accuracyModel = PhotoScan.Quality.LowQuality elif (generate_3DSettings.modelAccuracy == "Lowest"): accuracyModel = PhotoScan.Quality.LowestQuality else: accuracyModel = PhotoScan.Quality.MediumQuality chunk.matchPhotos(accuracy=accuracyMatch, preselection=PhotoScan.Preselection.GenericPreselection, filter_mask=True) fdebug.write("\nBefore Align **** \n") chunk.alignCameras() fdebug.write("\nBefore Optimize **** \n") chunk.optimizeCameras() fdebug.write("\nBefore Build Dense **** \n") chunk.buildDenseCloud(quality=accuracyModel) fdebug.write("\nBefore Build Model **** \n") #chunk.buildModel(surface= PhotoScan.SurfaceType.Arbitrary, interpolation=PhotoScan.Interpolation.EnabledInterpolation , face_count=generate_3DSettings.faceCount) #chunk.buildModel(surface= PhotoScan.SurfaceType.Arbitrary, interpolation=PhotoScan.Interpolation.EnabledInterpolation , face_count=300000) fdebug.write("\nBefore Build Texture **** \n") mapping = PhotoScan.MappingMode.GenericMapping #build texture mapping chunk.buildUV(mapping=mapping, count=1) chunk.buildTexture() #chunk.exportModel(path=PhotoScanPlyFile, format = 'ply', texture_format='jpg') chunk.exportModel(PhotoScanPlyFile, format=PhotoScan.ModelFormat.ModelFormatPLY, texture_format=PhotoScan.ImageFormat.ImageFormatJPEG) #chunk.exportModel(path_export + "\\model.obj", format = "obj", texture_format='PhotoScan.ImageFormat.ImageFormatJPEG) PhotoScan.app.update() #save ground control information a chunk.saveReference(PhotoScanReprojectionErrorsFile, PhotoScan.ReferenceFormat.ReferenceFormatCSV) # # if not(chunk.saveReference(PhotoScanReprojectionErrorsFile, PhotoScan.ReferenceFormat.ReferenceFormatCSV )): # app.messageBox("Saving GCP info failed!") # # SAVE PROJECT fdebug.write("---Saving project...") fdebug.write("File: " + PhotoScanProjectFile) doc.save(PhotoScanProjectFile) doc.chunks.remove(chunk) end = time.time() fdebug.close() flog.write('\nelapsed time =' + str(end - start)) # python will convert \n to os.linesep flog.close() return
def export_geo(self): """ Export LAS, DEM and Ortho to path using the file name prefix Ortho file format is JPG for JPG input images and TIF for all others, unless the resulting JPG is > 65535 pixels, in which case a TIF will be used. """ jpg_limit = 65535 for _ in self.chunks: ext = _.cameras[0].label[-3:] if self.exp_crs == 0: crs = _.crs else: crs = PhotoScan.CoordinateSystem('EPSG::{}' .format(self.exp_crs)) #write log information with open(self.log, 'a+') as logfile: start_t = datetime.now() logfile.write('Exporting geo {} at {} \n'. format(_, start_t.strftime('%H:%M:%S'))) logfile.write(' Export CRS: {}\n'. format(crs)) #check if input is JPG and below the limit if (ext.upper() == 'JPG' and not (_.orthomosaic.width > jpg_limit or _.orthomosaic.height > jpg_limit)): ext = 'jpg' else: ext = 'tif' if str(_)[8:-4] == 'Chunk': name = '' num = str(_)[-3] else: name = str(_)[8:-2] num = '' try: print('las crs: {}'.format(crs)) file = '{}{}_LAS{}.las'.format(self.prefix, name, num) _.exportPoints(path = os.path.join(self.path, file), format=PhotoScan.PointsFormatLAS, projection=crs) except RuntimeError as e: if str(e) == 'Null point cloud': print('There is no point cloud to export in chunk: {}' .format(_)) continue else: raise try: file = '{}{}_DSM{}.tif'.format(self.prefix, name, num) _.exportDem(path = os.path.join(self.path, file), write_world = True, projection=crs) except RuntimeError as e: if str(e) == 'Null elevation': print('There is no elevation to export in chunk: {}' .format(_)) continue else: raise try: file = '{}{}_Ortho{}.{}'.format(self.prefix, name, num, ext) _.exportOrthomosaic(path = os.path.join(self.path, file), write_world = True, projection=crs) except RuntimeError as e: if str(e) == 'Null orthomosaic': print('There is no orthomosaic to export in chunk: {}' .format(_)) continue else: raise
os.chdir(HomeDirectory) print("Home directory: " + HomeDirectory) # get main app objects doc = PhotoScan.app.document app = PhotoScan.Application() # create chunk chunk = PhotoScan.Chunk() chunk.label = "New_Chunk" doc.chunks.add(chunk) # SET COORDINATE SYSTEM print("---Settings coordinate system...") # init coordinate system object CoordinateSystem = PhotoScan.CoordinateSystem() if not (CoordinateSystem.init(CoordinateSystemEPSG)): app.messageBox("Coordinate system EPSG code not recognized!") # define coordinate system in chunk chunk.crs = CoordinateSystem chunk.projection = CoordinateSystem # FIND ALL PHOTOS IN PATH AerialImageFiles = glob.glob(AerialImagesPattern) # LOAD CAMERA CALIBRATION print("---Loading camera calibration...") # we need to open first image to define image size cam = PhotoScan.Camera() cam.open(AerialImageFiles[0]) # Load sensor calib
## author: Chia-Ching Lin ## ## ## ## 專案CHUNK名字必須與155上資料夾一致 ## ######################################## import os, sys, zipfile, pathlib, datetime, shutil, subprocess import PhotoScan, chardet from tkinter.filedialog import * from bs4 import BeautifulSoup from subprocess import PIPE from ftplib import FTP import xml.etree.ElementTree as ET from xml.dom import minidom # 前置設定參數 tw97 = PhotoScan.CoordinateSystem("EPSG::3826") ws84 = PhotoScan.CoordinateSystem("EPSG::3857") ds84 = PhotoScan.CoordinateSystem("EPSG::4326") crs = PhotoScan.CoordinateSystem('LOCAL_CS["Local CS",LOCAL_DATUM["Local Datum",0],UNIT["metre",1]]') path = r'\\140.116.228.155\geodac_uav\2019' dir = r'C:\Users\RSLAB\Desktop\dir\\' dir_1 = '1.測繪產品' dir_1_1 = '1.1.Ortho_正射影像(包含附加檔)' dir_1_2 = '1.2.OrigPhoto_原始照片' dir_1_3 = '1.3.PrecEval_精度評估報告' dir_1_4 = '1.4.ContCoor_控制點座標)' dir_1_5 = '1.5.ContPhoto_控制點照片' dir_1_6 = '1.6.FlyRec_飛行記錄'
class Agisoft: EXPORT_IMAGE_TYPE = '.tif' IMPORT_IMAGE_TYPE = '.tif' PROJECT_TYPE = '.psx' PROJECT_REPORT = '.pdf' REFERENCE_FILE = 'images_metadata.csv' WGS_84 = PhotoScan.CoordinateSystem("EPSG::4326") UTM_CA = PhotoScan.CoordinateSystem("EPSG::32611") UTM_CO = PhotoScan.CoordinateSystem("EPSG::32613") X_1M_IN_DEG = 1.13747e-05 # 1m in degree using EPSG:4326 Y_1M_IN_DEG = 9.0094e-06 # X_5M_IN_DEG = 5.76345e-05 # 5m in degree using EPSG:4326 Y_5M_IN_DEG = 4.50396e-05 # IMAGE_ACCURACY_MATCHING = PhotoScan.HighestAccuracy KEYPOINT_LIMIT = 40000 TIEPOINT_LIMIT = 4000 REPROJECTION_ERROR_THRESHOLD = 0.3 REPROJECTION_ACCURACY_THRESHOLD = 10 DENSE_POINT_QUALITY = dict( high=PhotoScan.HighQuality, medium=PhotoScan.MediumQuality, ) EXPORT_DEFAULTS = dict( image_format=PhotoScan.ImageFormat.ImageFormatTIFF, projection=WGS_84, dx=X_1M_IN_DEG, dy=Y_1M_IN_DEG, ) def __init__(self, options): # Ensure trailing slash self.project_base_path = os.path.join(options.base_path, '') self.project_file_name = self.project_file_path(options.project_name) self.setup_application() self.create_new_project() self.project = PhotoScan.app.document self.project.open(self.project_file_name + self.PROJECT_TYPE) self.chunk = self.project.chunk self.setup_camera() self.image_folder = os.path.join( self.project_base_path, options.image_folder, '' ) self.image_type = options.image_type def create_new_project(self): if not os.path.exists(path=self.project_file_name + self.PROJECT_TYPE): new_project = PhotoScan.Document() chunk = new_project.addChunk() new_project.save( path=self.project_file_name + self.PROJECT_TYPE, chunks=[chunk] ) def project_file_path(self, project_name): run_date = datetime.date.today().strftime('%Y_%m_%d') project_name = project_name + '_' + run_date return os.path.join( self.project_base_path, project_name ) def setup_application(self): app = PhotoScan.Application() # Use all available GPUs, needs a bit mask number_of_gpus = len(PhotoScan.app.enumGPUDevices()) mask = int(str('1' * number_of_gpus).rjust(8, '0'), 2) app.gpu_mask = mask # Allow usage of CPU and GPU app.cpu_enable = True settings = PhotoScan.Application.Settings() # Logging settings.log_enable = True settings.log_path = self.project_file_name + '_agisoft.log' settings.save() def setup_camera(self): # Imported camera coordinates projection self.chunk.crs = self.WGS_84 # Accuracy for camera position in m self.chunk.camera_location_accuracy = PhotoScan.Vector([1, 1, 1]) # Accuracy for camera orientations in degree self.chunk.camera_rotation_accuracy = PhotoScan.Vector([1, 1, 1]) def save_and_exit(self): self.project.save() sys.exit(-1) def image_list(self): images = glob.glob( self.image_folder + '**/*' + self.image_type, recursive=True ) if len(images) == 0: print('**** EXIT - ' + self.image_type + ' no files found in directory:') print(' ' + self.image_folder) self.save_and_exit() else: return images def check_reference_file(self, file): """ Check that the given reference file exists and has the image types loaded with this project by comparing file endings. """ if os.path.exists(file): with open(file) as file: next(file) # skip header line first_file = next(file).split(',')[0] if not first_file.endswith(self.image_type): print('**** Reference file has different ' 'source image types *****\n' ' given: ' + self.image_type + '\n' ' first image: ' + first_file) self.save_and_exit() else: print('**** EXIT - No reference file found ****') self.save_and_exit() def load_image_references(self): reference_file = self.project_base_path + self.REFERENCE_FILE self.check_reference_file(reference_file) self.chunk.loadReference( path=reference_file, delimiter=',', format=PhotoScan.ReferenceFormatCSV, ) def align_images(self): self.chunk.addPhotos(self.image_list()) self.load_image_references() self.chunk.matchPhotos( accuracy=self.IMAGE_ACCURACY_MATCHING, generic_preselection=True, reference_preselection=True, keypoint_limit=self.KEYPOINT_LIMIT, tiepoint_limit=self.TIEPOINT_LIMIT, ) self.chunk.alignCameras() self.project.save() def remove_by_criteria(self, criteria, threshold): point_cloud_filter = PhotoScan.PointCloud.Filter() point_cloud_filter.init(self.chunk, criterion=criteria) point_cloud_filter.removePoints(threshold) def filter_sparse_cloud(self): # Points that statistical error in point placement exceed threshold self.remove_by_criteria( PhotoScan.PointCloud.Filter.ReprojectionError, self.REPROJECTION_ERROR_THRESHOLD, ) # Points that accuracy of point placement from local neighbor points # exceed threshold self.remove_by_criteria( PhotoScan.PointCloud.Filter.ProjectionAccuracy, self.REPROJECTION_ACCURACY_THRESHOLD, ) def build_dense_cloud(self, dense_cloud_quality): self.chunk.buildDepthMaps( quality=self.DENSE_POINT_QUALITY.get(dense_cloud_quality, 'high'), filter=PhotoScan.AggressiveFiltering, ) self.chunk.buildDenseCloud() self.project.save() def export_results(self): self.chunk.exportDem( path=self.project_file_name + '_dem' + self.EXPORT_IMAGE_TYPE, **self.EXPORT_DEFAULTS ) self.chunk.exportOrthomosaic( path=self.project_file_name + self.EXPORT_IMAGE_TYPE, tiff_big=True, **self.EXPORT_DEFAULTS ) self.chunk.exportReport(self.project_file_name + self.PROJECT_REPORT) def process(self, options): self.align_images() self.filter_sparse_cloud() self.build_dense_cloud(options.dense_cloud_quality) self.chunk.buildDem() self.chunk.buildOrthomosaic() self.project.save() if options.with_export: self.export_results()
def main(root_path, image_folder): # PhotoScan.app.messageBox('hello world! \n') # PhotoScan.app.console.clear() # PhotoScan.app.gpu_mask = 1 doc = createOrOpenProject(root_path, image_folder) chunk = PhotoScan.Chunk if len(doc.chunks) > 0: chunk = doc.chunk logAction("Using the existing chunk '{}'".format(chunk.label)) else: chunk = doc.addChunk() chunk.crs = PhotoScan.CoordinateSystem("EPSG::4326") logAction("Created the new chunk '{}'".format(chunk.label)) if len(chunk.cameras) > 0: logAction( "Skipping adding photos and aligning cameras because chunk already has {} cameras" .format(len(chunk.cameras))) else: logAction("Started adding photos") t = datetime.datetime.now() addPhotos(chunk, root_path) logAction("Added photos ({})".format(datetime.datetime.now() - t)) logAction("Started photos alignment") t = datetime.datetime.now() alignPhotos(chunk) logAction("Aligned photos ({})".format(datetime.datetime.now() - t)) saveProject(doc) ################################################################################################ if chunk.dense_cloud is None: logAction("Started buildling dense cloud") t = datetime.datetime.now() buildDenseCloud(chunk) logAction("Built dense cloud ({})".format(datetime.datetime.now() - t)) saveProject(doc) else: logAction( "Skipping dense cloud build because chunk already has {}".format( chunk.dense_cloud)) ################################################################################################ # logAction("Started buildling DEM") # t = datetime.datetime.now() # buildDEM(chunk) # logAction("Built DEM ({})".format(datetime.datetime.now() - t)) # saveProject(doc) ################################################################################################ logAction("Started buildling orthomosaic") t = datetime.datetime.now() buildOrtho(chunk) logAction("Built orthomosaic ({})".format(datetime.datetime.now() - t)) saveProject(doc) logAction("Started exporting orthomosaic") t = datetime.datetime.now() out_image_name = image_name(image_folder) exportOrtho(chunk, root_path, out_image_name) logAction("Exported orthomosaic ({})".format(datetime.datetime.now() - t)) logAction("Started exporting dem") t = datetime.datetime.now() exportDem(chunk, root_path) logAction("Exported dem ({})".format(datetime.datetime.now() - t))
try: os.makedirs(workingPath + "pointcloud") print("Creating Point Cloud Directory.") except OSError as exception: if exception.errno != errno.EEXIST: raise project = workingPath + "ortho_dem_process.psx" app = PhotoScan.Application() doc = PhotoScan.app.document doc.open(project) chunk = doc.chunk chunk.crs = PhotoScan.CoordinateSystem("EPSG::4326") if int(pcTF) > 0: chunk.exportPoints( path=workingPath + "pointcloud\\dpc.txt", binary=False, precision=8, normals=False, colors=True, raster_transform=PhotoScan.RasterTransformType.RasterTransformNone, format=PhotoScan.PointsFormat.PointsFormatXYZ, projection=PhotoScan.CoordinateSystem("EPSG::4326")) else: chunk.exportPoints( path=workingPath + "pointcloud\\dpc.txt", binary=False,
def process(images_path, output_path, reference_path, model_name): # Font settings os.environ['QT_QPA_FONTDIR'] = '/usr/share/fonts/truetype/dejavu/' # Below code was to enable all available GPUs, was throwing an error. #PhotoScan.app.gpu_mask = 2 ** len(PhotoScan.app.enumGPUDevices()) - 1 #setting GPU mask PhotoScan.app.gpu_mask = 3 # gpu_mask is a bitmask. 3 in binary = 11 so only two GPUs are used. if PhotoScan.app.gpu_mask: PhotoScan.app.cpu_enable = False else: PhotoScan.app.cpu_enable = True ### Processing parameters accuracy = PhotoScan.Accuracy.HighAccuracy #align photos accuracy reference_preselection = False generic_preselection = True keypoints = 40000 # Align photos key point limit tiepoints = 4000 # Align photos tie point limit source = PhotoScan.DataSource.DenseCloudData # Build mesh/DEM source surface = PhotoScan.SurfaceType.Arbitrary # Build mesh surface type quality = PhotoScan.Quality.MediumQuality # Build dense cloud quality filtering = PhotoScan.FilterMode.AggressiveFiltering # Depth filtering interpolation = PhotoScan.Interpolation.EnabledInterpolation # Build mesh interpolation mosaic_blending = PhotoScan.BlendingMode.MosaicBlending # Blending mode average_blending = PhotoScan.BlendingMode.AverageBlending disabled_blending = PhotoScan.BlendingMode.DisabledBlending face_num = PhotoScan.FaceCount.HighFaceCount # Build mesh polygon count mapping = PhotoScan.MappingMode.GenericMapping #Build texture mapping atlas_size = 4096 TYPES = ["jpg", "jpeg", "tif", "tiff", "png"] # Load images into master list of fore and aft. list_photos_master = load_images(TYPES, images_path) # Create PhotoScan document project_file = os.path.join(output_path, "Model.psx") doc = PhotoScan.Document() doc.save(project_file) chunk = doc.addChunk() chunk.label = model_name print("Saving PhotoScan project to: ", project_file) print("Chunk label: ", str(chunk.label)) # Add Images to Chunk chunk.addPhotos(list_photos_master) # Load ref file. chunk.loadReference(path=reference_path, format=PhotoScan.ReferenceFormat.ReferenceFormatCSV, columns='zanxy', delimiter=',') # Set coordinate system for lat lon values. chunk.crs = PhotoScan.CoordinateSystem("EPSG::4326") # TODO Load calibration parameters from file # Create Sensor definitions sensor_fore = chunk.addSensor() sensor_fore.label = "Fore Sensor" sensor_fore.type = PhotoScan.Sensor.Type.Frame sensor_fore.width = chunk.cameras[-1].sensor.width sensor_fore.height = chunk.cameras[-1].sensor.height sensor_fore.pixel_size = [0.00345, 0.00345] sensor_fore.focal_length = 6.7 # Focal length is 10.4mm, 14.6mm effective length in water. sensor_fore.antenna.location_ref = PhotoScan.Vector([0.38, 0, 0.25]) sensor_aft = chunk.addSensor() sensor_aft.label = "Aft Sensor" sensor_aft.type = PhotoScan.Sensor.Type.Frame sensor_aft.width = chunk.cameras[-1].sensor.width sensor_aft.height = chunk.cameras[-1].sensor.height sensor_aft.pixel_size = [0.00345, 0.00345] sensor_aft.focal_length = 6.7 sensor_aft.antenna.location_ref = PhotoScan.Vector([0.53, 0, 0.25]) for camera in chunk.cameras: if "F" in camera.label: camera.sensor = sensor_fore print("Added ", camera.label, "to fore group") elif "A" in camera.label: camera.sensor = sensor_aft print("Added ", camera.label, "to aft group") else: print("No sensor defined for ", camera.label) # Add scalebars between stereo images # This is the baseline between two cameras. # Iver3 system is 6" baseline, 0.1524 meters. index = 0 while (True): scalebar = chunk.addScalebar(chunk.cameras[index], chunk.cameras[index + 1]) scalebar.reference.distance = 0.1524 index += 2 if index >= len(chunk.cameras): break ### Estimate image quality chunk.estimateImageQuality(chunk.cameras) badImages = 0 #for camera in chunk.cameras: # if float(camera.photo.meta["Image/Quality"]) < 0.5: # camera.enabled = False # badImages+=1 print("Removed ", badImages, " from chunk") ### Align photos chunk.matchPhotos(accuracy=accuracy, generic_preselection=generic_preselection, reference_preselection=reference_preselection, filter_mask=False, keypoint_limit=keypoints, tiepoint_limit=tiepoints, progress=progress_print) chunk.alignCameras() chunk.optimizeCameras() chunk.resetRegion() doc.read_only = False doc.save() ###building dense cloud chunk.buildDepthMaps(quality=quality, filter=filtering, progress=progress_print) chunk.buildDenseCloud(point_colors=True, progress=progress_print) doc.save() ###building mesh chunk.buildModel(surface=surface, source=source, interpolation=interpolation, face_count=face_num, progress=progress_print) doc.save() ###build texture chunk.buildUV(mapping=mapping, count=1, progress=progress_print) chunk.buildTexture(blending=mosaic_blending, size=atlas_size, progress=progress_print) doc.save() ###export model chunk.exportModel(path=os.path.join(output_path, chunk.label + ".obj"), binary=False, texture_format=PhotoScan.ImageFormatJPEG, texture=True, normals=False, colors=False, cameras=False, format=PhotoScan.ModelFormatOBJ) ### Export GeoTiff file chunk.buildDem(source=source, interpolation=interpolation, projection=chunk.crs, progress=progress_print) chunk.exportDem( path=os.path.join(output_path, chunk.label + '_DEM.jpeg'), image_format=PhotoScan.ImageFormat.ImageFormatJPEG, raster_transform=PhotoScan.RasterTransformType.RasterTransformPalette, projection=chunk.crs, nodata=-32767, write_kml=True, write_world=True, write_scheme=True, tiff_big=True) # Export orthomosaic chunk.buildOrthomosaic(surface=PhotoScan.DataSource.ElevationData, blending=mosaic_blending, fill_holes=True) chunk.exportOrthomosaic(path=os.path.join( output_path, chunk.label + '_' + str(mosaic_blending) + '_orthomosaic.tif'), projection=chunk.crs) chunk.buildOrthomosaic(surface=PhotoScan.DataSource.ElevationData, blending=average_blending, fill_holes=True) chunk.exportOrthomosaic(path=os.path.join( output_path, chunk.label + '_' + str(average_blending) + '_orthomosaic.tif'), projection=chunk.crs) chunk.buildOrthomosaic(surface=PhotoScan.DataSource.ElevationData, blending=disabled_blending, fill_holes=True) chunk.exportOrthomosaic(path=os.path.join( output_path, chunk.label + '_' + str(disabled_blending) + '_orthomosaic.tif'), projection=chunk.crs) ### Export camera poses export_camera_pose( chunk, os.path.join(output_path, chunk.label + '_camera_pose.csv')) ### Generate report chunk.exportReport(os.path.join(output_path, chunk.label + '_report.pdf')) print("Processed " + chunk.label) return True
# precision is not lost when coordinates are saved as floats. The offset will be subtracted from point coordinates. # [RECOMMENDED] - Leave as NaN; the script will automatically calculate and apply a suitable offset, which will be saved # as a text file for further processing, OR edit the line to impose a specific offset of your choice - # e.g. pts_offset = PhotoScan.Vector( [266000, 4702000, 0] ) pts_offset = PhotoScan.Vector([NaN, NaN, NaN]) ################################### END OF SETUP ################################### ######################################################################################## # Initialisation chunk = PhotoScan.app.document.chunk point_proj = chunk.point_cloud.projections # Need CoordinateSystem object, but PS only returns 'None' if an arbitrary coordinate system is being used # thus need to set manually in this case; otherwise use the Chunk coordinate system. if chunk.crs == None: crs = PhotoScan.CoordinateSystem( 'LOCAL_CS["Local CS",LOCAL_DATUM["Local Datum",0],UNIT["metre",1]]') chunk.crs = crs else: crs = chunk.crs # Find which markers are enabled for use as control points in the bundle adjustment act_marker_flags = [] for marker in chunk.markers: act_marker_flags.append(marker.reference.enabled) num_act_markers = sum(act_marker_flags) # Write the active marker flags to a text file - one line per BA iteration # This is actually relict code and not strictly needed. with open(dir_path + act_ctrl_file, 'w') as f: fwriter = csv.writer(f, delimiter=' ', lineterminator='\n') for line_ID in range(0, num_randomisations):
# Which will be calculated later Max_Angle = 13 Cell_Size = 10 # # Variable for building orthomosaic # Since 1.4.0, users can choose performing color correction (vignetting) and balance separately. # Blending: AverageBlending, MosaicBlending, MinBlending, MaxBlending, DisabledBlending # Color_correction: True, False # Color_balance: True, False BlendingMode = PhotoScan.BlendingMode.MosaicBlending Color_correction = True Color_balance = False # ####################################################### wgs_84 = PhotoScan.CoordinateSystem("EPSG::4326") def AlignPhoto(chunk, Accuracy, Key_Limit, Tie_Limit): chunk.matchPhotos(accuracy=Accuracy, generic_preselection=True, reference_preselection=True, filter_mask=False, keypoint_limit=Key_Limit, tiepoint_limit=Tie_Limit) chunk.alignCameras(adaptive_fitting=True) def BuildDenseCloud(chunk, Quality, FilterMode): try: chunk.buildDenseCloud(quality=Quality,
def generate3D(filePath): fullPathPhotoDirectoryName=filePath # Define: AlignPhotosAccuracy ["high", "medium", "low"] #change me AlignPhotosAccuracy = "medium" TireAuditDataRoot=os.path.dirname(os.path.dirname(fullPathPhotoDirectoryName))+"\\" PhotoScanInputGCPFileTireAuditMarkers=generate_3DSettings.photoScanGCPFile PhotoScanInputGCPFileAgisoftMarkers=TireAuditDataRoot+"gcp_agisoft.csv" PhotoScanInputGCPFileAgisoftMarkers=TireAuditDataRoot+"foo4.txt" PhotoScanInputCalibFile=generate_3DSettings.photoScanCalibrationFile #fdebug.write("\n ********************* TireAuditDataRoot PhotoScanInputCalibFile PhotoScanInputGCPFileAgisoftMarkers PhotoScanInputGCPFileAgisoftMarkers PhotoScanInputCalibFile\n ",TireAuditDataRoot , PhotoScanInputCalibFile , PhotoScanInputGCPFileAgisoftMarkers, PhotoScanInputGCPFileAgisoftMarkers ,PhotoScanInputCalibFile) PhotoScanPlyFile = fullPathPhotoDirectoryName+"\\"+generate_3DSettings.photoScanPlyName PhotoScanLogFile = fullPathPhotoDirectoryName+"\\"+ generate_3DSettings.photoScanLogName PhotoScanDebugFile = fullPathPhotoDirectoryName+"\\"+ generate_3DSettings.photoScanDebugName PhotoScanProjectFile= fullPathPhotoDirectoryName+"\\"+ generate_3DSettings.photoScanProjectName PhotoScanReprojectionErrorsFile = fullPathPhotoDirectoryName+"\\"+ generate_3DSettings.photoScanReprojectionErrorsName PhotoScanMarkerFile = fullPathPhotoDirectoryName+"\\"+generate_codesSettings.markerInformationPixelToCode #fdebug.write("\n*********** Checking for %s \n", PhotoScanProjectFile) # if path already has a psz file in exit then go onto nex directory if os.path.exists(PhotoScanProjectFile): #fdebug.write("\n*********** already proceessed %s \n", PhotoScanProjectFile) exit fdebug=open(PhotoScanDebugFile,'w') flog = open(PhotoScanLogFile,'w') start=time.time() #####pattern = 'IMG_*[02468].JPG' pattern = 'IMG_*' #print 'Pattern :', pattern print ( "abc") #files = os.listdir('.') files = os.listdir(fullPathPhotoDirectoryName) photoList=[] for filename in fnmatch.filter(files,pattern): #print ('Filename: %-25s %s' % (name, fnmatch.fnmatch(name, pattern)) ) #item = fullPathPhotoDirectoryName+"\\"+filename item = os.path.join(fullPathPhotoDirectoryName,filename) photoList.append(item) print ("\n777 Photolist is ", photoList) doc = PhotoScan.app.document chunk = PhotoScan.app.document.addChunk() chunk.crs = PhotoScan.CoordinateSystem('LOCAL_CS["Local Coordinates",LOCAL_DATUM["Local Datum",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]') #successLoad=chunk.loadReference("c:\\temp\\pgcp.csv","csv") #successLoad=chunk.loadReference("c:\\temp\\foo1.csv","csv") #successLoad=chunk.loadReference("c:\\temp\\dtest.csv","csv") #print ("\n ############# Success Load is ", successLoad) #chunk.updateTransform() chunk.label = "New ChunkB" cameraDictionary={} user_calib = PhotoScan.Calibration() success=user_calib.load(PhotoScanInputCalibFile) print ("\n success loading calib file ", success) sensor = chunk.addSensor() #creating camera calibration group for the loaded image sensor.label = "Calibration Group 1" sensor.type = PhotoScan.Sensor.Type.Frame #sensor.width = camera.photo.image().width #sensor.height = camera.photo.image().height sensor.width = 5312 sensor.height = 2988 sensor.fixed=True sensor.user_calib=user_calib #sensor.width = 3264 #sensor.height = 2448 #sensor.calibration.cx=1.61822175e+03 #sensor.calibration.cy=1.26702669e+03 #sensor.calibration.fx=3.08768833e+03 #sensor.calibration.fy=3.08786068e+03 #sensor.calibration.k1=0.23148765 #sensor.calibration.k2=0.51836559 #sensor.calibration.k3=-0.48297284 # sensor.calibration.fx = 3.99411182e+03 # sensor.calibration.fy = 3.99418122e+03 # sensor.calibration.cx = 2.68713926e+03 # sensor.calibration.cy = 1.51055154e+03 # sensor.calibration.k1= 0.24503953 # sensor.calibration.k2 = -0.80636859 # sensor.calibration.k3 = 0.77637451 # sensor.user_calib.fx = 3.99411182e+03 # sensor.user_calib.fy = 3.99418122e+03 # sensor.user_calib.cx = 2.68713926e+03 # sensor.user_calib.cy = 1.51055154e+03 # sensor.user_calib.k1= 0.24503953 # sensor.user_calib.k2 = -0.80636859 # sensor.user_calib.k3 = 0.77637451 # sensor.user_calib = True # sensor.calibration.fx = 4.05913e+03 # sensor.calibration.fy = 4.06049e+03 # sensor.calibration.cx = 2.68463e+03 # sensor.calibration.cy = 1.52241e+03 # sensor.calibration.k1= 0.273712 # sensor.calibration.k2 = -1.03971 # sensor.calibration.k3 = 1.05705 chunk.accuracy_markers=0.0002 for i,filepath in enumerate(photoList): fdebug.write("\nxxxxxxxx filepath" + " " + filepath) camera=chunk.addCamera() camera.sensor = sensor pos= filepath.find("IMG") img= filepath[pos:] #cameraDictionary[img]=i cameraDictionary[img]=camera.key camera.open(filepath) #camera.open("c:\\Projects\\123DCatch\\Tires_25982510_B_Samsung6ChoppedExampleForTesting\\A\\IMG_14.JPG") camera.label=img #fdebug.write("\n filepath key", filepath, camera.key,camera.photo.image().width,camera.photo.image().height) fdebug.write("\n filepath key" + " " + filepath + " "+ str(camera.key)+ " "+camera.photo.path) fdebug.write("\n^^^^^^^^^^ Camera Dictionary" + " " + str(cameraDictionary) ) fdebug.write ("\n PhotoList &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n" + " " + str(photoList)) fdebug.write("hello") if (os.path.isfile(PhotoScanMarkerFile)): automaticMarkers=False else: automaticMarkers=True fdebug.write ("\n ^^^^^^^^^^^^^^^^^ automatic markers is \n " + str(automaticMarkers) + "\n") if (automaticMarkers): chunk.detectMarkers(PhotoScan.TargetType.CircularTarget20bit,44) print ("\n ^^^^^^^^^^^^^^^^^ loading automatic ground contreol information\n", PhotoScanInputGCPFileAgisoftMarkers,"\n") successLoad=chunk.loadReference(PhotoScanInputGCPFileAgisoftMarkers,"csv") fdebug.write("\n succes load is" + " "+ str(successLoad)) else: markerNamePosList=[] processTAMarkers(PhotoScanMarkerFile,markerNamePosList,chunk,cameraDictionary,fdebug) fdebug.write ("\n ^^^^^^^^^^^^^^^^^ loading ground contreol information\n" + " " + PhotoScanInputGCPFileTireAuditMarkers + "\n") #successLoad=chunk.loadReference("c:\\temp\\gcp_25982510.csv","csv") successLoad=chunk.loadReference(PhotoScanInputGCPFileTireAuditMarkers,"csv") # load in ground control information # load in masks templateName=fullPathPhotoDirectoryName+ "\\" + "M{filename}.JPG" #templateName=fullPathPhotoDirectoryName+ "\\" + "M{filename}.JPG" successMask=chunk.importMasks(path=templateName,method='file',tolerance=10) #ALIGN PHOTOS fdebug.write("---Aligning photos ...") fdebug.write("Accuracy: " + AlignPhotosAccuracy) fdebug.write("\nBefore Matching **** \n") if (generate_3DSettings.matchAccuracy=="Low"): accuracyMatch= PhotoScan.Accuracy.LowAccuracy elif (generate_3DSettings.matchAccuracy=="High"): accuracyMatch= PhotoScan.Accuracy.HighAccuracy else: accuracyMatch= PhotoScan.Accuracy.MediumAccuracy if (generate_3DSettings.modelAccuracy=="Ultra"): accuracyModel= PhotoScan.Quality.UltraQuality elif (generate_3DSettings.modelAccuracy=="High"): accuracyModel= PhotoScan.Quality.HighQuality elif (generate_3DSettings.modelAccuracy=="Low"): accuracyModel= PhotoScan.Quality.LowQuality elif (generate_3DSettings.modelAccuracy=="Lowest"): accuracyModel= PhotoScan.Quality.LowestQuality else: accuracyModel= PhotoScan.Quality.MediumQuality chunk.matchPhotos(accuracy= accuracyMatch, preselection=PhotoScan.Preselection.GenericPreselection) fdebug.write("\nBefore Align **** \n") chunk.alignCameras() fdebug.write("\nBefore Optimize **** \n") chunk.optimizeCameras() fdebug.write("\nBefore Build Dense **** \n") chunk.buildDenseCloud(quality=accuracyModel) fdebug.write("\nBefore Build Model **** \n") chunk.buildModel(surface= PhotoScan.SurfaceType.Arbitrary, interpolation=PhotoScan.Interpolation.EnabledInterpolation, source= PhotoScan.PointsSource.DensePoints , face_count=generate_3DSettings.faceCount) fdebug.write("\nBefore Build Texture **** \n") mapping = PhotoScan.MappingMode.GenericMapping #build texture mapping chunk.buildUV(mapping = mapping, count = 1) chunk.buildTexture() chunk.exportModel(PhotoScanPlyFile, format = "ply", texture_format='jpg') PhotoScan.app.update() #save ground control information a if not(chunk.saveReference(PhotoScanReprojectionErrorsFile,"csv")): app.messageBox("Saving GCP info failed!") # SAVE PROJECT fdebug.write("---Saving project...") fdebug.write("File: " + PhotoScanProjectFile) if not(doc.save(PhotoScanProjectFile)): app.messageBox("Saving project failed!") doc.chunks.remove(chunk) end=time.time() fdebug.close() flog.write('\nelapsed time ='+str(end-start)) # python will convert \n to os.linesep flog.close() return
import PhotoScan import os from math import ceil chunk = PhotoScan.app.document.chunk # ВЫХОДНАЯ ПРОЕКЦИЯ - Краснодарская первый варинат, без номера зоны out_crs = PhotoScan.CoordinateSystem( 'PROJCS["SK-42/GK_ZONE7_noZone (var1)",GEOGCS["Pulkovo 1942",DATUM["Pulkovo 1942",SPHEROID["Krassowsky 1940",6378245,298.3,AUTHORITY["EPSG","7024"]],TOWGS84[82.28,-123.01,-138.08,1.07,-2.371,1.15,1.867],AUTHORITY["EPSG","----"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9102"]],AUTHORITY["EPSG","----"]],PROJECTION["Transverse_Mercator",AUTHORITY["EPSG","9807"]],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",39],PARAMETER["scale_factor",1],PARAMETER["false_easting",7500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]' ) # предварительные настройки difX = 0.15 difY = 0.15 sizeXM = 1000.05 sizeYM = 1000.05 sizeXMpix = ceil(sizeXM / difX) sizeYMpix = ceil(sizeYM / difY) #if sizeXMpix%2: sizeXMpix=sizeXMpix+1 #if sizeYMpix%2: sizeYMpix=sizeYMpix+1 sizeXMround = sizeXMpix * difX sizeYMround = sizeYMpix * difY # КООРДИАНТЫ ДОЛЖНЫ БЫТЬ В ВЫХОДНОЙ ПРОЕКЦИИ!!!!! FileRazgr = os.path.dirname(__file__) + "/orthoexport_full_file_razgrafka.txt" #ЗДЕСЬ ПОМЕНЯТЬ ПУТИ!!! OFolder = "v:\\Photoscan_Cluster\\test_test\\Ortho\\" with open(FileRazgr) as file_razgr: for line in file_razgr: cu_string = line.split(";") print(cu_string) OName = cu_string[0] XMLeft = float(cu_string[1])
args = vars(ap.parse_args()) workingPath = args["wpath"] + "\\" markerFile = args["mfile"] print("Working path is: %s" % workingPath) project = workingPath + "ortho_dem_process.psx" app = PhotoScan.Application() doc = PhotoScan.app.document doc.open(project) PhotoScan.app.gpu_mask = 1 # PhotoScan.app.cpu_enable = 8 chunk = doc.chunk chunk.crs = PhotoScan.CoordinateSystem("EPSG::4326") # Assign GCPs markerList = open(markerFile, "rt") # print(markerList) eof = False line = markerList.readline() #reading the line in input file # print(line) while not eof: photos_total = len(chunk.cameras) #number of photos in chunk # print(photos_total) markers_total = len(chunk.markers) #number of markers in chunk sp_line = line.rsplit(",", 6) #splitting read line by four parts camera_name = sp_line[0] #camera label marker_name = sp_line[1] #marker label x = int(sp_line[2]) #x- coordinate of the current projection in pixels
# for each member in the list try to add it to our active chunk ### the try except is very important because the list goes one beyond our photos and returns an error for photo_name in photo_list: try: chunk.addPhotos([path_photos + "\\" + photo_name]) except: continue # match, align, and optimize photos that have been added chunk.matchPhotos(accuracy=photo_accuracy, preselection=PhotoScan.GenericPreselection) chunk.alignCameras() chunk.optimizeCameras(fit_f=True, fit_cxcy=True, fit_aspect=True, fit_skew=True, fit_k1k2k3=True, fit_p1p2=True, fit_k4=False) # set coordinate system for each camera n_crs = PhotoScan.CoordinateSystem(coordinate_system) for camera in chunk.cameras: camera.reference.location = PhotoScan.CoordinateSystem.transform(camera.reference.location, chunk.crs, n_crs) # build the dense cloud and then build the model doc.save chunk.buildDenseCloud() chunk.buildModel(surface=PhotoScan.Arbitrary, interpolation=PhotoScan.EnabledInterpolation, face_count=num_faces, vertex_colors=True) # build UV has to be done before the texture can be built # chunk.buildUV(mapping=PhotoScan.GenericMapping) # chunk.buildTexture(blending=PhotoScan.MosaicBlending, size=texture_size, fill_holes=True) # generate the .ply for the points and the .pdf for the report ### photoscan requires the project is aved before a report can be generated doc.save()