Forum

Author Topic: Python script to loop and process 800 projects one after another  (Read 5329 times)

Ant

  • Newbie
  • *
  • Posts: 20
    • View Profile
Hi there,

I'm a newbie in Python!

I need to write a script that I can use in PhotoScan 1.4.2 to process 800 projects from 800 folders (named from 0001 to 0800) that contains different sets of pictures.

The idea is simply to load the pictures from the first folder, align them, build dense point cloud, build mesh, save the .psx file with the name 0001.psx, export the mesh with the name 0001.ply.

And then automatically loop to go to the next folder to process the exact same steps... and this until folder 0800.

Can anyone help me with this?

Regards,
Ant

Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 14813
    • View Profile
Re: Python script to loop and process 800 projects one after another
« Reply #1 on: July 01, 2018, 08:42:51 PM »
Hello Ant,

Please check the following script. It requires to specify the path to the "master folder" via script arguments:

Code: [Select]
## Autoprocessing script for multiple sub-folders in some master folder

#compatibility Agisoft PhotoScan Professional 1.4.2
#use argument to specify the path to the "master folder"

import PhotoScan, os, sys, time

def process(path):

PhotoScan.app.gpu_mask = 2 ** len(PhotoScan.app.enumGPUDevices()) - 1 #setting GPU mask
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
blending = PhotoScan.BlendingMode.MosaicBlending #blending mode
face_num = PhotoScan.FaceCount.HighFaceCount #build mesh polygon count
mapping = PhotoScan.MappingMode.GenericMapping #build texture mapping
atlas_size = 4096
TYPES = ["jpg", "jpeg", "tif", "tiff"]
###end of processing parameters definition

print("Processing " + path)
list_files = os.listdir(path)
list_photos = list()
for entry in list_files: #finding image files
file = path + "/" + entry
if os.path.isfile(file):
if file[-3:].lower() in TYPES:
list_photos.append(file)
if not(len(list_photos)):
print("No images in " + path)
return False

doc = PhotoScan.Document()
doc.save(path + "/" + path.rsplit("/", 1)[1] + ".psx")
chunk = doc.addChunk()
chunk.label = path.rsplit("/", 1)[1]

###align photos
chunk.addPhotos(list_photos)
chunk.matchPhotos(accuracy = accuracy, generic_preselection = generic_preselection, reference_preselection = reference_preselection, filter_mask = False, keypoint_limit = keypoints, tiepoint_limit = tiepoints)
chunk.alignCameras()
chunk.optimizeCameras()
chunk.resetRegion()
doc.save()

###building dense cloud
chunk.buildDepthMaps(quality = quality, filter = filtering)
chunk.buildDenseCloud(point_colors = True, keep_depth = False)
doc.save()

###building mesh
chunk.buildModel(surface = surface, source = source, interpolation = interpolation, face_count = face_num)
doc.save()

###build texture
chunk.buildUV(mapping = mapping, count = 1)
chunk.buildTexture(blending = blending, size = atlas_size)
doc.save()

###export model
chunk. exportModel(path = path + "/" + chunk.label + ".obj", binary=False, texture_format=ImageFormatJPEG, texture=True, normals=False, colors=False, cameras=False, format = PhotoScan.ModelFormatOBJ)

print("Processed " + chunk.label)
return True

def main()

t0 = time.time()
print("Script started...")

if len(sys.argv) < 2:
print("No valid path input. Script aborted.")
return False
if os.path.isdir(sys.argv[1]):
path = sys.argv[1]
else:
print("No valid path input. Script aborted.")
return False

folders = ["/".join([path,entry]) for entry in os.listdir(path) if os.path.isdir(os.path.join(path,entry))]

for folder in folders:
process(folder)

t1 = time.time()
t1 -= t0
t1 = float(t1)

print("Script finished in " + "{:.2f}".format(t1) + " seconds.\n")
return

main()

You can check it on a few subfolders and let me know, if everything works as expected or if there are any issues. In case of any problems, please provide the Console pane output with the related error information.
Best regards,
Alexey Pasumansky,
Agisoft LLC

Ant

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Python script to loop and process 800 projects one after another
« Reply #2 on: July 02, 2018, 11:46:27 AM »
Thanks Alexey!

I've actually managed to make it work with the script below (in case it can help out someone else).

***

import os, PhotoScan

dir_projects = 'E:/...//' #Directory folders with pictures
dir_PS_outputs = 'E:/...//' #Directory saved PS outputs


foldernames = os.listdir(dir_projects)
len(foldernames)

for i in range (0,len(foldernames)):
   
   doc=PhotoScan.app.document
   
   chunk = doc.addChunk()

   path_photos=dir_projects+foldernames

   image_list=os.listdir(path_photos)

   photo_list = list()

   for photo in image_list:
      if photo.rsplit(".",1)[1].lower() in  ["jpg", "jpeg", "tif", "tiff"]:
         photo_list.append("/".join([path_photos, photo]))

   chunk.addPhotos(photo_list)

   chunk.matchPhotos(accuracy=PhotoScan.HighestAccuracy,
                  generic_preselection=False,
                  reference_preselection=False,
                  filter_mask=False,
                  mask_tiepoints=False,
                  keypoint_limit=40000,
                  tiepoint_limit=4000)

   #accuracy=HighestAccuracy, HighAccuracy, MediumAccuracy, LowAccuracy, LowestAccuracy               
                  
   chunk.alignCameras(adaptive_fitting=True)

   chunk.buildDepthMaps(quality=PhotoScan.UltraQuality,
                  filter=PhotoScan.ModerateFiltering)
                  
   #quality=UltraQuality, HighQuality, MediumQuality, LowQuality, LowestQuality               

   chunk.buildDenseCloud(point_colors=True)

   chunk.buildModel(surface=PhotoScan.Arbitrary,
                  interpolation=PhotoScan.EnabledInterpolation,
                  face_count=PhotoScan.HighFaceCount,
                  vertex_colors=True)
                  
   #face_count=LowFaceCount, MediumFaceCount, HighFaceCount               

   chunk.buildUV(mapping=PhotoScan.GenericMapping,
                  count=1,
                  adaptive_resolution=False)
   
   chunk.buildTexture(blending=PhotoScan.MosaicBlending,
                  size=4096,
                  fill_holes=True,
                  ghosting_filter=True)   

   chunk.exportModel(path=dir_PS_outputs+foldernames+"_PS.ply",
                  binary=False,
                  precision=6,
                  texture_format=PhotoScan.ImageFormatNone,
                  texture=False,
                  normals=True,
                  colors=True,
                  cameras=False,
                  markers=False,
                  udim=False,
                  alpha=False,
                  strip_extensions=False,
                  raster_transform=PhotoScan.RasterTransformNone,
                  format=PhotoScan.ModelFormatPLY)

   chunk.exportModel(path=dir_PS_outputs+foldernames+"_PS.obj",
                  binary=False,
                  precision=6,
                  texture_format=PhotoScan.ImageFormatNone,
                  texture=False,
                  normals=True,
                  colors=True,
                  cameras=False,
                  markers=False,
                  udim=False,
                  alpha=False,
                  strip_extensions=False,
                  raster_transform=PhotoScan.RasterTransformNone,
                  format=PhotoScan.ModelFormatOBJ)

   doc.save(path=dir_PS_outputs+foldernames+"_PS.psx")
   
   doc.clear()

Ant

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Python script to loop and process 800 projects one after another
« Reply #3 on: July 02, 2018, 11:49:09 AM »
Another question about Python in PhotoScan Pro 1.2.3:

What command line should I use to re-locate the pictures of a project that has already been created (with aligning, scaling and optimising steps done).

Regards,
Ant

Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 14813
    • View Profile
Re: Python script to loop and process 800 projects one after another
« Reply #4 on: July 02, 2018, 12:22:33 PM »
Hello Ant,

Do you mean to modify the paths to the images, similar to Change Paths operation from GUI?
Best regards,
Alexey Pasumansky,
Agisoft LLC

Ant

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Python script to loop and process 800 projects one after another
« Reply #5 on: July 02, 2018, 12:33:59 PM »
Yes

Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 14813
    • View Profile
Re: Python script to loop and process 800 projects one after another
« Reply #6 on: July 02, 2018, 02:44:43 PM »
Hello Ant,

You can use the following approach:

Code: [Select]
new_path = "D:/new_image_folder/" #the new location of the image folder (same filenames)
for camera in chunk.cameras:
camera.photo.path = "/".join([new_path, camera.photo.path.rsplit("/",1)[1]])

another way that can be considered as safer:

Code: [Select]
for camera in chunk.cameras:
        photo = camera.photo.copy()
        photo.path = "/".join([new_path, camera.photo.path.rsplit("/",1)[1]])
        camera.photo = photo
« Last Edit: July 02, 2018, 03:43:20 PM by Alexey Pasumansky »
Best regards,
Alexey Pasumansky,
Agisoft LLC

Ant

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Python script to loop and process 800 projects one after another
« Reply #7 on: July 13, 2018, 08:48:50 AM »
Thanks Alexey!