Skip to content

Commit

Permalink
Merge pull request #1652 from alicevision/dev/focalMM_valid
Browse files Browse the repository at this point in the history
[camerainit] update parameters to use focal in mm
  • Loading branch information
fabiencastan authored Apr 25, 2022
2 parents 8e064fc + 7083b01 commit a1bd5bd
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 26 deletions.
7 changes: 6 additions & 1 deletion meshroom/core/desc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import os
import psutil
import ast
import distutils.util


class Attribute(BaseObject):
"""
Expand Down Expand Up @@ -191,7 +193,10 @@ def __init__(self, name, label, description, value, uid, group='allParams', adva

def validateValue(self, value):
try:
return bool(int(value)) # int cast is useful to handle string values ('0', '1')
if isinstance(value, pyCompatibility.basestring):
# use distutils.util.strtobool to handle (1/0, true/false, on/off, y/n)
return bool(distutils.util.strtobool(value))
return bool(value)
except:
raise ValueError('BoolParam only supports bool value (param:{}, value:{}, type:{})'.format(self.name, value, type(value)))

Expand Down
41 changes: 22 additions & 19 deletions meshroom/nodes/aliceVision/CameraInit.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "6.0"
__version__ = "7.0"

import os
import json
Expand Down Expand Up @@ -28,16 +28,17 @@

Intrinsic = [
desc.IntParam(name="intrinsicId", label="Id", description="Intrinsic UID", value=-1, uid=[0], range=None),
desc.FloatParam(name="pxInitialFocalLength", label="Initial Focal Length",
desc.FloatParam(name="initialFocalLength", label="Initial Focal Length",
description="Initial Guess on the Focal Length (in pixels). \n"
"When we have an initial value from EXIF, this value is not accurate but cannot be wrong. \n"
"So this value is used to limit the range of possible values in the optimization. \n"
"If you put -1, this value will not be used and the focal length will not be bounded.",
value=-1.0, uid=[0], range=None),
desc.GroupAttribute(name="pxFocalLength", label="Focal Length", description="Known/Calibrated Focal Length (in pixels)", groupDesc=[
desc.FloatParam(name="x", label="x", description="", value=-1, uid=[], range=(0, 10000, 1)),
desc.FloatParam(name="y", label="y", description="", value=-1, uid=[], range=(0, 10000, 1)),
]),
desc.FloatParam(name="focalLength", label="Focal Length", description="Known/Calibrated Focal Length (in mm)", value=1000, uid=[], range=(0, 10000, 1)),
desc.FloatParam(name="pixelRatio", label="pixel Ratio", description="ratio between pixel width and pixel height", value=1, uid=[], range=(0, 10, 0.1)),
desc.BoolParam(name='pixelRatioLocked', label='Pixel ratio Locked',
description='the pixelRatio value is locked for estimation',
value=True, uid=[0]),
desc.ChoiceParam(name="type", label="Camera Type",
description="Mathematical Model used to represent a camera:\n"
" * pinhole: Simplest projective camera model without optical distortion (focal and optical center).\n"
Expand Down Expand Up @@ -107,11 +108,6 @@ def readSfMData(sfmFile):
intrinsic['principalPoint']['x'] = pp[0]
intrinsic['principalPoint']['y'] = pp[1]

f = intrinsic['pxFocalLength']
intrinsic['pxFocalLength'] = {}
intrinsic['pxFocalLength']['x'] = f[0]
intrinsic['pxFocalLength']['y'] = f[1]

# convert empty string distortionParams (i.e: Pinhole model) to empty list
if intrinsic['distortionParams'] == '':
intrinsic['distortionParams'] = list()
Expand Down Expand Up @@ -255,12 +251,6 @@ class CameraInit(desc.CommandLineNode):
]

def upgradeAttributeValues(self, attrValues, fromVersion):
# Starting with version 5, the focal length is now split on x and y
if fromVersion < Version(5, 0):
for intrinsic in attrValues['intrinsics']:
pxFocalLength = intrinsic['pxFocalLength']
if not isinstance(pxFocalLength, dict):
intrinsic['pxFocalLength'] = {"x": pxFocalLength, "y": pxFocalLength}

# Starting with version 6, the principal point is now relative to the image center
if fromVersion < Version(6, 0):
Expand All @@ -271,6 +261,20 @@ def upgradeAttributeValues(self, attrValues, fromVersion):
"y": int(principalPoint["y"] - 0.5 * intrinsic['height'])
}

# Starting with version 7, the focal length is now in mm
if fromVersion < Version(7, 0):
for intrinsic in attrValues['intrinsics']:
pxInitialFocalLength = intrinsic['pxInitialFocalLength']
pxFocalLength = intrinsic['pxFocalLength']
sensorWidth = intrinsic['sensorWidth']
width = intrinsic['width']
focalLength = (pxFocalLength / width) * sensorWidth
initialFocalLength = (pxInitialFocalLength / width) * sensorWidth
intrinsic['initialFocalLength'] = initialFocalLength
intrinsic['focalLength'] = focalLength
intrinsic['pixelRatio'] = 1.0
intrinsic['pixelRatioLocked'] = False

return attrValues

def readSfMData(self, sfmFile):
Expand Down Expand Up @@ -329,7 +333,6 @@ def createViewpointsFile(self, node, additionalViews=()):
intrinsics = node.intrinsics.getPrimitiveValue(exportDefault=True)
for intrinsic in intrinsics:
intrinsic['principalPoint'] = [intrinsic['principalPoint']['x'], intrinsic['principalPoint']['y']]
intrinsic['pxFocalLength'] = [intrinsic['pxFocalLength']['x'], intrinsic['pxFocalLength']['y']]
views = node.viewpoints.getPrimitiveValue(exportDefault=False)

# convert the metadata string into a map
Expand All @@ -338,7 +341,7 @@ def createViewpointsFile(self, node, additionalViews=()):
view['metadata'] = json.loads(view['metadata'])

sfmData = {
"version": [1, 2, 1],
"version": [1, 2, 2],
"views": views + newViews,
"intrinsics": intrinsics,
"featureFolder": "",
Expand Down
6 changes: 2 additions & 4 deletions meshroom/ui/qml/ImageGallery/ImageGallery.qml
Original file line number Diff line number Diff line change
Expand Up @@ -474,9 +474,8 @@ Panel {
property var columnWidths: [105, 75, 75, 75, 125, 60, 60, 45, 45, 200, 60, 60]
property var columnNames: [
"intrinsicId",
"pxInitialFocalLength",
"pxFocalLength.x",
"pxFocalLength.y",
"initialFocalLength",
"focalLength",
"type",
"width",
"height",
Expand All @@ -499,7 +498,6 @@ Panel {
TableModelColumn { display: function(modelIndex){return parsedIntrinsic[modelIndex.row][intrinsicModel.columnNames[9]]} }
TableModelColumn { display: function(modelIndex){return parsedIntrinsic[modelIndex.row][intrinsicModel.columnNames[10]]} }
TableModelColumn { display: function(modelIndex){return parsedIntrinsic[modelIndex.row][intrinsicModel.columnNames[11]]} }
TableModelColumn { display: function(modelIndex){return parsedIntrinsic[modelIndex.row][intrinsicModel.columnNames[12]]} }
//https://doc.qt.io/qt-5/qml-qt-labs-qmlmodels-tablemodel.html#appendRow-method
}

Expand Down
5 changes: 3 additions & 2 deletions meshroom/ui/reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,9 @@ def fieldOfView(self):
""" Get camera vertical field of view in degrees. """
if not self.solvedIntrinsics:
return None
pxFocalLength = self.solvedIntrinsics["pxFocalLength"]
return 2.0 * math.atan(self.orientedImageSize.height() / (2.0 * float(pxFocalLength[0]))) * 180 / math.pi
focalLength = self.solvedIntrinsics["focalLength"]
sensorHeight = self.solvedIntrinsics["sensorHeight"]
return 2.0 * math.atan(sensorHeight / (2.0 * float(focalLength))) * 180 / math.pi

@Property(type=QUrl, notify=denseSceneParamsChanged)
def undistortedImageSource(self):
Expand Down

0 comments on commit a1bd5bd

Please sign in to comment.