Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veggiemonk/3df2b59d1b7d3c49b045655c12734b23 to your computer and use it in GitHub Desktop.
Save veggiemonk/3df2b59d1b7d3c49b045655c12734b23 to your computer and use it in GitHub Desktop.
Creating 3D Models for QGIS With ODM

Capture a movie on your phone of the object by walking around it. If possible shoot it from different angles e.g. from above looking down, below looking up, side on etc. When you film it, walk around it or move the camera around it in a full 360 revolution (or even a couple of revolutions). You should get something like this (note that the image below is a resized copy of the orignal downrated to 1 fps):

DrinkingFountainSmall

Put the video into an empty folder and then use ffmpeg to extract the frames. You can experiment with different frame rates but generally there will be little value in extracting at 60fps or whatever your phone natively shoots at.

If you are on an iPhone you may need to convert your movie from .HEIC format first:

sudo dnf install libheif
ffmpeg -i waterfountain.MOV -vf fps=1 -f image2 image-%07d.png

For interest, I generated the above GIF from the extracted frames using this ImageMagick command:

convert *.PNG DrinkingFountain.gif
convert -scale 25% DrinkingFountain.gif DrinkingFountainSmall.gif

ODM Processing

Web ODM (way one)

The exported images can now be imported into WebODM. I ran it through WebODM using the steps below to create a project an then load the image:

image

Then I ran the processing using the following settings:

2021-julho-31-Screenshot_2

In otherwords, I only processed the 3D model and I used the images in their original resolution. You may want to play around with this depending on how detailed you want the model.

ODM (way two)

This way just uses straight ODM from a docker container and is probably easier and more reliable than way 1 above.

Place your images from the previous step in a subfolder of your current working directory (e.g. here I put them in a folder called Tree/images):

Tree
├── images
│   ├── image-0000001.png
│   ├── image-0000002.png
│   ├── image-0000003.png
│   ├── image-0000004.png
│   ├── image-0000005.png
│   ├── image-0000006.png
│   ├── image-0000007.png
│   ├── image-0000008.png
│   ├── image-0000009.png
│   ├── image-0000010.png
│   ├── image-0000011.png
│   ├── image-0000012.png
│   ├── image-0000013.png
│   ├── image-0000014.png
│   ├── image-0000015.png
│   ├── image-0000016.png
│   ├── image-0000017.png
│   ├── image-0000018.png
│   ├── image-0000019.png
│   ├── image-0000020.png
│   ├── image-0000021.png
│   ├── image-0000022.png
│   ├── image-0000023.png
│   ├── image-0000024.png
│   ├── image-0000025.png
│   ├── image-0000026.png
│   ├── image-0000027.png
│   ├── image-0000028.png
│   ├── image-0000029.png
│   ├── image-0000030.png
│   ├── image-0000031.png
│   ├── image-0000032.png
│   ├── image-0000033.png
│   ├── image-0000034.png
│   ├── image-0000035.png
│   ├── image-0000036.png
│   ├── image-0000037.png
│   ├── image-0000038.png
│   ├── image-0000039.png
│   ├── image-0000040.png
│   ├── image-0000041.png
│   ├── image-0000042.png
│   ├── image-0000043.png
│   ├── image-0000044.png
│   ├── image-0000045.png
│   ├── image-0000046.png
│   ├── image-0000047.png
│   ├── image-0000048.png
│   ├── image-0000049.png
│   └── image-0000050.png
├── tree.gif
└── tree.mp4

Then run this docker command:

docker run -ti --rm -v ${PWD}:/datasets opendronemap/odm --project-path /datasets Tree

If you are on windows you can replace ${PWD} with the absolute path to the current working directory.

Blender

After processing, download the assets for the textured model as shown below:

image

Next, fire up Blender, create a new project, delete the default block and import the .obj:

image

Make sure to take the geo object file:

image

After enabling Viewport Shading mode, you should see your model loaded (may take a while to load depending on complexity).

image

As you can see, my model came in lying on it's side.

2021-julho-31-Screenshot

I am not going to cover Blender workflows in here - go and watch some youtube tutorials for Rotate (R), Move (G) and Scale (S) so that you can rotate your model so the axes are correctly orientated.

image

The next job is to edit the model, removing all the unwanted stuff around your object. To do this I simply put Blender into edit mode (first select the imported object so it goes orange):

image

Way 1

Select everything in the scene while in edit mode, right click, then from the context menu choose 'loose parts'

image

Then return to object mode and iteratively select and delete parts you don't want.

Way 2

And then deselect everything, select a group of vertices / faces you want to remove, and press (X) then choose Vertices from the context menu as the next image sequence shows:

image

image

image

image

You may need to reselect from the same area and delete vertices repeatedly as the selection will not choose vertices that are behind other faces. Keep doing this until you have nothing but your model left:

image

Switch back to View mode, add your texture back on, spin the model around and admire (ahem: quality check) your model.

Next we want to simplify the model as much as possible. QGIS is going to grind to a halt if you ask it to render complex models as symbols so we are going to 'decimate' the geometry such that it maintains it's form but loses as many vertices as possible. You need to jump back into edit mode for this:

image

In the decimate popup, slide the ratio down below 1 as small as you can make it without destroying the integrity of your model's shape.

image

If you are lucky you may be able to reduce the model complexity down to 10-15% of the original:

image

Ok now let's reverse the blender import process and write our model and it's texture to a new .obj file:

image

Next hop over to QGIS and make a new project with the OpenStreetMap XYZ layer added and create a scratch point layer with Z value. Make sure to use EPSG:3857 for the project CRS and the new point layer CRS:

image

Now zoom to your object's location on the OSM map and stick a dot in that location on your point layer:

image

Make sure to save your edits.

Now add a new 3D map view to your project.

Then in your point layer properties, set the 2d symbology to no symbol:

image

And the 3d symbology to use your new object file:

image

Take care of the settings 1,2,3 in the image above. Now navigate to your model in the 3D map and enjoy the 3D awesomeness of your real world model in QGIS!

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment