查看: 1847|回复: 0

技术 | 用python生成无人机影像的正射影像、数字高程模型以及三维建模

[复制链接]

315

主题

353

帖子

984

积分

高级飞友

Rank: 4

积分
984
飞币
629
注册时间
2017-7-4
发表于 2023-1-9 10:52:39 | 显示全部楼层 |阅读模式
点击上方蓝字关注我们

『OpenDroneMap』https://github.com/OpenDroneMap
  OpenDroneMap 是一个开源的航拍图像处理工具,可以把航拍图像进行点云、正射影像和高程模型等处理,也可以做3维重构,生成3维模型。简直是个神器,做出来的效果和pix4d等软件差不多(我目前只做了无人机影像的正摄影像的生成)。

  根据官方文档所说,PyODM可以很轻易的创建无人机影像的正射图,DEM,3d模型以及点云。

第一步:下面开始使用OpenDroneMap的python库PyODM。
  注:若图片内有exif信息,则odm可以直接生成tif的正射影像。
(1)图片exif信息对比

  在做处理之前可以通过图片属性查看是否含有gps信息。看这个例子里面图片信息是不包含exif信息的。



在做了以下操作后可以看到图片属性里面已经加上了gps信息.
技术 | 用python生成无人机影像的正射影像、数字高程模型以及三维建模w2.jpg
(2)实践代码

这里主要调用piexif库来实现,所以需要先安装piexif。
$ pip install piexif

    1

  代码中写有详细的注释。就不做额外说明了。
  这里是通过pos数据批量修改图片,所以需要一个pos.csv文件,图片目录,以及图片输出存放的目录。并且对应pos数据的列号修改main函数中的lng, lat, alt的item序号。
#ecoding:utf-8
import datetime
from PIL import Image
import piexif
import csv
import os

def main(csv_path, image_root, save_root):
    csv_data = open(csv_path, "r")
    reader = csv.reader(csv_data)

    # 读取csv的每一行,跳过标题行
    for item in reader:
        if reader.line_num <= 1:
            continue
        lng = float(item[1])
        lat = float(item[2])
        alt=float(item[4])

        # 将经纬度与相对航高转为exif可用的经纬度与行高
        # exif需要的航高输入为(20000,2)格式,表示高度为20000/100米
        # exif需要的经度与维度为((12, 1), (20,1), (41000, 1000))格式表示12度20分41秒
        lng_exif = format_latlng(lng)
        lat_exif = format_latlng(lat)
        alt_exif = (int(100*round(alt,2)),100)
        _dict = {"alt": alt_exif, "lng":
            lng_exif, "lat": lat_exif, "lng_ref":'W', "lat_ref":'N'}

        image_path = os.path.join(image_root, item[-1])
        save_path = os.path.join(save_root, item[-1])
        # 修改图片的exif
        read_modify_exif(image_path, save_path, _dict)
        print('{} finished'.format(item[-1]))

def format_latlng(latlng):
    """经纬度十进制转为分秒"""
    degree = int(latlng)
    res_degree = latlng - degree
    minute = int(res_degree * 60)
    res_minute = res_degree * 60 - minute
    seconds = round(res_minute * 60.0,3)

    return ((degree, 1), (minute,1), (int(seconds*1000), 1000))

def read_modify_exif(image_path,save_path, _dict):
    """ 读取并且修改exif文件"""
    img = Image.open(image_path)  # 读图
    exif_dict = piexif.load(img.info['exif'])  # 提取exif信息
    exif_dict['GPS'][piexif.GPSIFD.GPSAltitude] = _dict['alt']  # 修改高度,GPSAltitude是内置变量,不可修改
    exif_dict['GPS'][piexif.GPSIFD.GPSLongitude] = _dict['lng']  # 修改经度
    exif_dict['GPS'][piexif.GPSIFD.GPSLatitude] = _dict['lat']  # 修改纬度
    exif_dict['GPS'][piexif.GPSIFD.GPSLongitudeRef] = _dict['lng_ref']  # odm需要读取,一般为’W'
    exif_dict['GPS'][piexif.GPSIFD.GPSLatitudeRef] = _dict['lat_ref']  # 一般为‘N'

    exif_bytes = piexif.dump(exif_dict)
    print('alt:{} lng:{} lat:{}'.format(exif_dict['GPS'][piexif.GPSIFD.GPSAltitude], exif_dict['GPS'][piexif.GPSIFD.GPSLongitude], exif_dict['GPS'][piexif.GPSIFD.GPSLatitude]))
    img.save(save_path, "jpeg", exif=exif_bytes)  # 保存

def check_folder(path_list):
    """输入为文件夹列表,文件夹不存在则创建"""
    for path in path_list:
        if not os.path.exists(path):
            os.mkdir(path)

if __name__ == "__main__":
    csv_path = '/home/dennis/pure_python/odm/exif_write/exif_data/from/pos.csv'
    image_root = '/home/dennis/pure_python/odm/exif_write/exif_data/from'
    save_root = '/home/dennis/pure_python/odm/exif_write/exif_data/to'
    check_folder([csv_path, image_root, save_root])
    main(csv_path, image_root, save_root)
第二步:用python生成无人机影像的正射影像、数字高程模型以及三维建模
(1)环境准备

安装pyodm包

  用pip安装即可。
pip install -U pyodm

    1
启动docker

pyodm需要启动docker,所以在使用之前还需要先安装docker.
windows的安装就不说了,可以自行百度,下面介绍linux系统下docker的安装。
# 安装docker
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-get install -y docker-ce

# 启动docker,这里会自己下载需要的包,所以需要等待一会儿。
$ sudo docker run -ti -p 3000:3000 opendronemap/nodeodm


    1

    2

    3

    4

    5

    6

    7
(2)python教程

  大致流程是这样,先连接Node,然后新建任务,然后等待任务执行完成,最后获取结果。
  这里关键是新建任务时有个option选项,可以设置一些配置。看文档说明得知,配置会影响处理速度与结果的质量。
  对正射影像的制作来说,需要配置的一些参数(参数可以在官方文档查看)如下:

    orthophoto-resolution:米/像素,表示地面分辨率

    dsm:是否要生成dsm,如果不需要的话,选false会加快处理速度

    ignore-gsd:设置为True就会跳过一些加速处理,得到的图像质量会好一些

    min-num-features:找的特征点数量,数量越多质量越好,处理时间越长

    texturing-nadir-weight:官方建议,在都市设为29-32,草地或者平底设置为0-6

    mesh-octree-depth:官方建议设置为10-11,增加建筑屋顶的平滑性。

  注意:在制作正射影像时,选择的图片最好是有至少两个轨道的数据,一个航线的数据拼接会失败,即task.wait_for_completion()会返回failed.
import os
from pyodm import Node
import time
from tqdm import tqdm

image_dir = 'testdata/'
result_path = image_dir.split('/')[0]+'_results'
ip = 'xxx.xx.xx.xx' # 改为自己的ip
port = 3000

start = time.time()
images_name = os.listdir(image_dir)
images_name = [image_dir+image_name for image_name in images_name]
print(images_name)

n = Node(ip, port)
print("Node连接成功,{}张图开始处理".format(len(images_name)))

task = n.create_task(images_name, {'orthophoto-resolution': 0.0274,"min-num-features":35000})
print("任务创建完成")
pbar = tqdm(total=100)
processing = 0
while True:
    info = task.info()
    if info.progress==100:
        break
    pbar.update(info.progress-processing)
    processing = info.progress
    if info.last_error!='':
        print("error ", info.last_error)

    time.sleep(0.1)
pbar.close()

print("处理完成")
# task.wait_for_completion()
task.download_assets(result_path)

print("{}张图消耗{}秒".format(len(images_name), time.time() - start))

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41
(3)其它

  查看官方文档可能需要科学上网,所以把option列出来了。
-h, --help            show this help message and exit
--images <path>, -i <path>
                      Path to input images
--project-path <path>
                      Path to the project folder
--resize-to <integer>
                      resizes images by the largest side for opensfm. Set to
                      -1 to disable.
                                              Default: 2048
--end-with <string>, -e <string>
                      Can be one of:dataset | split | merge | opensfm | mve
                      | odm_filterpoints | odm_meshing | mvs_texturing |
                      odm_georeferencing | odm_dem | odm_orthophoto
--rerun <string>, -r <string>
                      Can be one of:dataset | split | merge | opensfm | mve
                      | odm_filterpoints | odm_meshing | mvs_texturing |
                      odm_georeferencing | odm_dem | odm_orthophoto
--rerun-all           force rerun of all tasks
--rerun-from <string>
                      Can be one of:dataset | split | merge | opensfm | mve
                      | odm_filterpoints | odm_meshing | mvs_texturing |
                      odm_georeferencing | odm_dem | odm_orthophoto
--proj <PROJ4 string>
                      Projection used to transform the model into geographic
                      coordinates
--min-num-features <integer>
                      Minimum number of features to extract per image. More
                      features leads to better results but slower execution.
                      Default: 8000
--matcher-neighbors <integer>
                      Number of nearest images to pre-match based on GPS
                      exif data. Set to 0 to skip pre-matching. Neighbors
                      works together with Distance parameter, set both to 0
                      to not use pre-matching. OpenSFM uses both parameters
                      at the same time, Bundler uses only one which has
                      value, prefering the Neighbors parameter.
                                              Default: 8
--matcher-distance <integer>
                      Distance threshold in meters to find pre-matching
                      images based on GPS exif data. Set both matcher-
                      neighbors and this to 0 to skip pre-matching.
                                              Default: 0
--use-fixed-camera-params
                      Turn off camera parameter optimization during bundler
                                              Off by default unless --camera parameter used
--camera-lens <string>
                      Can be one of auto | perspective | brown | fisheye | spherical
                      Set a camera projection type. Manually setting a value
                      can help improve geometric undistortion. By default the application
                      tries to determine a lens type from the images metadata.
                                              Default: auto
--max-concurrency <positive integer>
                      The maximum number of processes to use in various
                      processes. Peak memory requirement is ~1GB per thread
                      and 2 megapixel image resolution.
                                              Default: number of cores
--depthmap-resolution <positive float>
                      Controls the density of the point cloud by setting the
                      resolution of the depthmap images. Higher values take
                      longer to compute and more memory but produce denser
                                              point clouds.
                      Default: 640
--opensfm-depthmap-min-consistent-views <integer: 2 <= x <= 9>
                      Minimum number of views that should reconstruct a
                      point for it to be valid. Use lower values if your
                      images have less overlap. Lower values result in
                      denser point clouds but with more noise. Only applies
                                              if using OpenSfM for dense matching.
                                              Default: 3
--opensfm-depthmap-method <string>
                      Raw depthmap computation algorithm. PATCH_MATCH and
                      PATCH_MATCH_SAMPLE are faster, but might miss some
                      valid points. BRUTE_FORCE takes longer but produces
                      denser reconstructions.
                                              Default: PATCH_MATCH
--opensfm-depthmap-min-patch-sd <positive float>
                      When using PATCH_MATCH or PATCH_MATCH_SAMPLE, controls
                      the standard deviation threshold to include patches.
                      Patches with lower standard deviation are ignored.
                      Default: 1
--use-hybrid-bundle-adjustment
                      Run local bundle adjustment for every image added to
                      the reconstruction and a global adjustment every 100
                      images. Speeds up reconstruction for very large
                      datasets.
--mve-confidence <float: 0 <= x <= 1>
                      Discard points that have less than a certain
                      confidence threshold. This only affects dense
                      reconstructions performed with MVE. Higher values
                      discard more points.
                                              Default: 0.6
--use-3dmesh          Use a full 3D mesh to compute the orthophoto instead
                      of a 2.5D mesh. This option is a bit faster and
                      provides similar results in planar areas.
--skip-3dmodel        Skip generation of a full 3D model. This can save time
                      if you only need 2D results such as orthophotos and
                      DEMs.
--use-opensfm-dense   Use opensfm to compute dense point cloud alternatively
--ignore-gsd          Ignore Ground Sampling Distance (GSD). GSD caps the
                      maximum resolution of image outputs and resizes images
                      when necessary, resulting in faster processing and
                      lower memory usage. Since GSD is an estimate,
                      sometimes ignoring it can result in slightly better
                      image output quality.
--mesh-size <positive integer>
                      The maximum vertex count of the output mesh.
                                              Default: 100000
--mesh-octree-depth <positive integer>
                      Oct-tree depth used in the mesh reconstruction,
                      increase to get more vertices, recommended values are
                      8-12.
                                              Default: 9
--mesh-samples <float >= 1.0>
                      Number of points per octree node, recommended and
                      Default: 1.0
--mesh-point-weight <positive float>
                      This floating point value specifies the importance
                      that interpolation of the point samples is given in
                      the formulation of the screened Poisson equation. The
                      results of the original (unscreened) Poisson
                      Reconstruction can be obtained by setting this value
                      to 0.
                                              Default: 4
--fast-orthophoto     Skips dense reconstruction and 3D model generation. It
                      generates an orthophoto directly from the sparse
                      reconstruction. If you just need an orthophoto and do
                      not need a full 3D model, turn on this option.
                      Experimental.
--crop <positive float>
                      Automatically crop image outputs by creating a smooth
                      buffer around the dataset boundaries, shrinked by N
                      meters. Use 0 to disable cropping.
                                              Default: 3
--pc-classify         Classify the point cloud outputs using a Simple
                      Morphological Filter. You can control the behavior of
                      this option by tweaking the --dem-* parameters.
                      Default: False
--pc-csv              Export the georeferenced point cloud in CSV format.
                      Default: False
--pc-las              Export the georeferenced point cloud in LAS format.
                      Default: False
--pc-filter <positive float>
                      Filters the point cloud by removing points that
                      deviate more than N standard deviations from the local
                      mean. Set to 0 to disable filtering.
                                              Default: 2.5
--smrf-scalar <positive float>
                      Simple Morphological Filter elevation scalar
                      parameter.
                                              Default: 1.25
--smrf-slope <positive float>
                      Simple Morphological Filter slope parameter (rise over
                      run).
                                              Default: 0.15
--smrf-threshold <positive float>
                      Simple Morphological Filter elevation threshold
                      parameter (meters).
                                              Default: 0.5
--smrf-window <positive float>
                      Simple Morphological Filter window radius parameter
                      (meters).
                                              Default: 18.0
--texturing-data-term <string>
                      Data term: [area, gmi].
                                              Default: gmi
--texturing-nadir-weight <integer: 0 <= x <= 32>
                      Affects orthophotos only. Higher values result in
                      sharper corners, but can affect color distribution and
                      blurriness. Use lower values for planar areas and
                      higher values for urban areas. The default value works
                      well for most scenarios.
                                              Default: 16
--texturing-outlier-removal-type <string>
                      Type of photometric outlier removal method: [none,
                      gauss_damping, gauss_clamping].
                                              Default: gauss_clamping
--texturing-skip-visibility-test
                      Skip geometric visibility test.
                                              Default: False
--texturing-skip-global-seam-leveling
                      Skip global seam leveling. Useful for IR data.
                                              Default: False
--texturing-skip-local-seam-leveling
                      Skip local seam blending.
                                              Default: False
--texturing-skip-hole-filling
                      Skip filling of holes in the mesh.
                                              Default: False
--texturing-keep-unseen-faces
                      Keep faces in the mesh that are not seen in any
                      camera.
                                              Default: False
--texturing-tone-mapping <string>
                      Turn on gamma tone mapping or none for no tone
                      mapping. Choices are 'gamma' or 'none'.
                                              Default: none
--gcp <path string>   path to the file containing the ground control points
                      used for georeferencing. Default: None. The file needs
                      to be on the following line format: easting northing
                      height pixelrow pixelcol imagename
--use-exif            Use this tag if you have a gcp_list.txt but want to
                      use the exif geotags instead
--dtm                 Use this tag to build a DTM (Digital Terrain Model,
                      ground only) using a simple morphological filter.
                      Check the --dem* and --smrf* parameters for finer
                      tuning.
--dsm                 Use this tag to build a DSM (Digital Surface Model,
                      ground + objects) using a progressive morphological
                      filter. Check the --dem* parameters for finer tuning.
--dem-gapfill-steps <positive integer>
                      Number of steps used to fill areas with gaps. Set to 0
                      to disable gap filling. Starting with a radius equal
                      to the output resolution, N different DEMs are
                      generated with progressively bigger radius using the
                      inverse distance weighted (IDW) algorithm and merged
                      together. Remaining gaps are then merged using nearest
                      neighbor interpolation.
                                              Default: 3
--dem-resolution <float>
                      DSM/DTM resolution in cm / pixel.
                                              Default: 5
--dem-decimation <positive integer>
                      Decimate the points before generating the DEM. 1 is no
                      decimation (full quality). 100 decimates ~99% of the
                      points. Useful for speeding up generation.
                                              Default: 1
--dem-euclidean-map   Computes an euclidean raster map for each DEM. The map
                      reports the distance from each cell to the nearest
                      NODATA value (before any hole filling takes place).
                      This can be useful to isolate the areas that have been
                      filled.
                                              Default: False
--orthophoto-resolution <float > 0.0>
                      Orthophoto resolution in cm / pixel.
                                              Default: 5
--orthophoto-no-tiled
                      Set this parameter if you want a stripped geoTIFF.
                      Default: False
--orthophoto-compression <string>
                      Set the compression to use. Note that this could break
                      gdal_translate if you don't know what you are doing.
                      Options: JPEG, LZW, PACKBITS, DEFLATE, LZMA, NONE.
                      Default: DEFLATE
--orthophoto-bigtiff {YES,NO,IF_NEEDED,IF_SAFER}
                      Control whether the created orthophoto is a BigTIFF or
                      classic TIFF. BigTIFF is a variant for files larger
                      than 4GiB of data. Options are YES, NO, IF_NEEDED,
                      IF_SAFER. See GDAL specs:
                      https://www.gdal.org/frmt_gtiff.html for more info.
                      Default: IF_SAFER
--orthophoto-cutline  Generates a polygon around the cropping area that cuts
                      the orthophoto around the edges of features. This
                      polygon can be useful for stitching seamless mosaics
                      with multiple overlapping orthophotos.
                                              Default: False
--build-overviews     Build orthophoto overviews using gdaladdo.
--verbose, -v         Print additional messages to the console
                                              Default: False
--time                Generates a benchmark file with runtime info
                                              Default: False
--version             Displays version number and exits.
--split <positive integer>
                      Average number of images per submodel. When splitting
                      a large dataset into smaller submodels, images are
                      grouped into clusters. This value regulates the number
                      of images that each cluster should have on average.
--split-overlap <positive integer>
                      Radius of the overlap between submodels. After
                      grouping images into clusters, images that are closer
                      than this radius to a cluster are added to the
                      cluster. This is done to ensure that neighboring
                      submodels overlap.
--sm-cluster <string>
                      URL to a ClusterODM instance for distributing a
                      split-merge workflow on multiple nodes in parallel.
                      Default: None
--merge <string>      Choose what to merge in the merge step in a split
                      dataset. By default all available outputs are merged.
                      Default: all
转自https://blog.csdn.net/weixin_43162240/article/details/103579657

方向 | 多位院士发声:测绘科技必将迈入智能化时代

科普 | 无人机的六种动力驱动及常用接口

疑问 | 测绘专业有时间能考什么证?

漫画 | 为什么C语言永不过时?
您需要登录后才可以回帖 登录 | 加入联盟

本版积分规则

快速回复 返回顶部 返回列表