kopia lustrzana https://github.com/OpenDroneMap/ODM
commit
59f7cbe2b3
|
@ -0,0 +1,23 @@
|
||||||
|
# Blender scripts
|
||||||
|
# odm_photo
|
||||||
|
Renders photos from ODM generated texture models.
|
||||||
|
Currently can produce 360 panoramic photos and 360 3D panoramic (VR) photos.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
* Blender
|
||||||
|
* ExifTool (must be on your PATH)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
To generate a 360 panoramic photo:
|
||||||
|
|
||||||
|
blender -b photo_360.blend --python odm_photo.py -- <project-path>
|
||||||
|
|
||||||
|
Output is `<project-path>/odm_photo/odm_photo_360.jpg`.
|
||||||
|
|
||||||
|
To generate a 360 3D panoramic photo:
|
||||||
|
|
||||||
|
blender -b photo_vr.blend --python odm_photo.py -- <project-path>
|
||||||
|
|
||||||
|
Output is `<project-path>/odm_photo/odm_photo_vr_L.jpg` and `<project-path>/odm_photo/odm_photo_vr_R.jpg`.
|
||||||
|
|
||||||
|
**NB: argument order matters!**
|
|
@ -0,0 +1,103 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Renders a photo.
|
||||||
|
# ExifTool must be on your PATH.
|
||||||
|
# To generate a 360 panoramic photo:
|
||||||
|
# blender -b photo_360.blend --python odm_photo.py -- <project-path>
|
||||||
|
# To generate a 360 3D panoramic photo:
|
||||||
|
# blender -b photo_vr.blend --python odm_photo.py -- <project-path>
|
||||||
|
# NB: argument order matters!
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import bpy
|
||||||
|
import materials_utils
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
surfaceShaderType = 'ShaderNodeEmission'
|
||||||
|
surfaceShaderName = 'Emission'
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
if len(sys.argv) < 5 or sys.argv[-2] != '--':
|
||||||
|
sys.exit('Please provide the ODM project path.')
|
||||||
|
|
||||||
|
projectHome = sys.argv[-1]
|
||||||
|
|
||||||
|
bpy.utils.register_module('materials_utils')
|
||||||
|
|
||||||
|
bpy.ops.import_scene.obj(filepath=projectHome +
|
||||||
|
'/odm_texturing/odm_textured_model_geo.obj',
|
||||||
|
axis_forward='Y', axis_up='Z')
|
||||||
|
|
||||||
|
bpy.ops.xps_tools.convert_to_cycles_all()
|
||||||
|
|
||||||
|
model = bpy.data.objects[-1]
|
||||||
|
minX = float('inf')
|
||||||
|
maxX = float('-inf')
|
||||||
|
minY = float('inf')
|
||||||
|
maxY = float('-inf')
|
||||||
|
minZ = float('inf')
|
||||||
|
maxZ = float('-inf')
|
||||||
|
for coord in model.bound_box:
|
||||||
|
x = coord[0]
|
||||||
|
y = coord[1]
|
||||||
|
z = coord[2]
|
||||||
|
minX = min(x, minX)
|
||||||
|
maxX = max(x, maxX)
|
||||||
|
minY = min(y, minY)
|
||||||
|
maxY = max(y, maxY)
|
||||||
|
minZ = min(z, minZ)
|
||||||
|
maxZ = max(z, maxZ)
|
||||||
|
|
||||||
|
model.location[2] += (maxZ - minZ)/2
|
||||||
|
|
||||||
|
for m in bpy.data.materials:
|
||||||
|
nt = m.node_tree
|
||||||
|
nt.nodes.remove(nt.nodes['Color Mult'])
|
||||||
|
nt.nodes.remove(nt.nodes['Diffuse BSDF'])
|
||||||
|
nt.nodes.new(surfaceShaderType)
|
||||||
|
nt.links.new(nt.nodes['Material Output'].inputs[0],
|
||||||
|
nt.nodes[surfaceShaderName].outputs[0])
|
||||||
|
nt.links.new(nt.nodes[surfaceShaderName].inputs[0],
|
||||||
|
nt.nodes['Diffuse Texture'].outputs[0])
|
||||||
|
|
||||||
|
blendName = bpy.path.display_name_from_filepath(bpy.data.filepath)
|
||||||
|
fileName = projectHome + '/odm_photo/odm_' + blendName
|
||||||
|
render = bpy.data.scenes[0].render
|
||||||
|
render.filepath = fileName
|
||||||
|
bpy.ops.render.render(write_still=True)
|
||||||
|
|
||||||
|
width = render.resolution_x
|
||||||
|
height = render.resolution_y
|
||||||
|
if(render.use_multiview):
|
||||||
|
writeExif(fileName+render.views[0].file_suffix+'.jpg', width, height)
|
||||||
|
writeExif(fileName+render.views[1].file_suffix+'.jpg', width, height)
|
||||||
|
else:
|
||||||
|
writeExif(fileName+'.jpg', width, height)
|
||||||
|
|
||||||
|
|
||||||
|
def writeExif(fileName, width, height):
|
||||||
|
w = str(width)
|
||||||
|
h = str(height)
|
||||||
|
|
||||||
|
subprocess.run(['exiftool',
|
||||||
|
'-overwrite_original',
|
||||||
|
'-CroppedAreaImageWidthPixels=' + w,
|
||||||
|
'-CroppedAreaImageHeightPixels=' + h,
|
||||||
|
'-FullPanoWidthPixels=' + w,
|
||||||
|
'-FullPanoHeightPixels=' + h,
|
||||||
|
'-CroppedAreaLeftPixels=0',
|
||||||
|
'-CroppedAreaTopPixels=0',
|
||||||
|
'-ProjectionType=equirectangular',
|
||||||
|
'-UsePanoramaViewer=True',
|
||||||
|
'-PoseHeadingDegrees=0',
|
||||||
|
'-LargestValidInteriorRectLeft=0',
|
||||||
|
'-LargestValidInteriorRectTop=0',
|
||||||
|
'-LargestValidInteriorRectWidth=' + w,
|
||||||
|
'-LargestValidInteriorRectHeight=' + h,
|
||||||
|
fileName])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
|
@ -0,0 +1,16 @@
|
||||||
|
# GRASS scripts
|
||||||
|
# odm_grass
|
||||||
|
Generates DEM, contour and textured relief maps.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
* GRASS
|
||||||
|
* Environment variables:
|
||||||
|
* PYTHONHOME set to the location of Python
|
||||||
|
* PYTHONPATH set to the location of GRASS Python libs
|
||||||
|
* PATH includes GRASS bin and lib directories
|
||||||
|
* GISBASE set to the location of GRASS
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
python odm_grass.py <project-path>
|
||||||
|
|
||||||
|
Output is `<project-path>/odm_georeferencing/odm_dem.tif`, `<project-path>/odm_georeferencing/odm_contour.shp` and `<project-path>/odm_orthophoto/odm_relief.tif`.
|
Ładowanie…
Reference in New Issue