/// <summary> /// Parses the camera setup from a directory containing an "images" folder with an image dataset from the Stanford Light Field Archive, and saves the parsed setup in this directory. /// </summary> public void ParseCameraSetup() { // Inform of process start. Debug.Log(GeneralToolkit.FormatScriptMessage(this.GetType(), "Started parsing camera setup for an image dataset from the Stanford Light Field Archive located at: " + dataHandler.colorDirectory + ".")); // Get the files in the "images" folder. FileInfo[] fileInfos = GeneralToolkit.GetFilesByExtension(dataHandler.colorDirectory, ".png"); // Determine the pixel resolution of the images. Texture2D tempTex = new Texture2D(1, 1); GeneralToolkit.LoadTexture(fileInfos[0].FullName, ref tempTex); Vector2Int pixelResolution = new Vector2Int(tempTex.width, tempTex.height); DestroyImmediate(tempTex); // Prepare repositioning around center if it is selected. Vector3 meanPos = Vector3.zero; // Reset the camera models to fit the color count. _cameraSetup.ResetCameraModels(); _cameraSetup.cameraModels = new CameraModel[dataHandler.sourceColorCount]; // Iteratively add each camera model to the setup. for (int iter = 0; iter < dataHandler.sourceColorCount; iter++) { CameraModel cameraModel = _cameraSetup.AddCameraModel(iter); // Store the image's pixel resolution in the camera model. cameraModel.pixelResolution = pixelResolution; // Store the image's name in the camera model. FileInfo fileInfo = fileInfos[iter]; cameraModel.SetCameraReferenceIndexAndImageName(cameraModel.cameraReferenceIndex, fileInfo.Name); // Store the image's position in the model. string[] split = fileInfo.Name.Split('_'); float positionY = -GeneralToolkit.ParseFloat(split[split.Length - 3]); float positionX = GeneralToolkit.ParseFloat(split[split.Length - 2]); Vector3 pos = scaleFactor * new Vector3(positionX, positionY, 0); cameraModel.transform.position = pos; meanPos += pos; } // If it is selected, reposition the camera setup around its center position. if (repositionAroundCenter) { meanPos /= dataHandler.sourceColorCount; for (int iter = 0; iter < dataHandler.sourceColorCount; iter++) { CameraModel cameraModel = _cameraSetup.cameraModels[iter]; cameraModel.transform.position = cameraModel.transform.position - meanPos; } } // Temporarily move the color images to a safe location. string tempDirectoryPath = Path.Combine(GeneralToolkit.GetDirectoryBefore(dataHandler.dataDirectory), "temp"); GeneralToolkit.Move(PathType.Directory, dataHandler.colorDirectory, tempDirectoryPath); // Save the camera setup information (this would also have cleared the "images" folder if it was still there). Acquisition.Acquisition.SaveAcquisitionInformation(dataHandler, cameraSetup); // Move the color images back into their original location. GeneralToolkit.Delete(dataHandler.colorDirectory); GeneralToolkit.Move(PathType.Directory, tempDirectoryPath, dataHandler.colorDirectory); // Update the camera models of the setup object. _cameraSetup.FindCameraModels(); // Inform of end of process. Debug.Log(GeneralToolkit.FormatScriptMessage(this.GetType(), "Finished parsing camera setup. Result can be previewed in the Scene view.")); }
/// <summary> /// Reads images information from a COLMAP "images.txt" file, and saves it into the referenced array. /// Note that the array contains a camera element for each image. Array elements will be initialized here. /// </summary> /// <param name="cameraSetup"></param> The camera setup to which to output the list of parsed camera models. /// <param name="workspace"></param> The workspace from which to work. public static void ReadImagesInformation(CameraSetup cameraSetup, string workspace) { List <Vector3> positionList = new List <Vector3>(); List <Quaternion> rotationList = new List <Quaternion>(); List <string> fileNameList = new List <string>(); List <int> cameraIDList = new List <int>(); // Read COLMAP's images file. using (StreamReader reader = File.OpenText(GetImagesFile(workspace))) { bool isOdd = false; string line; // Read the file line-by-line to the end. while ((line = reader.ReadLine()) != null) { // Skip the lines from the header, that start with #. if (!line.StartsWith("#")) { // If the line is odd, skip it, and indicate that the next line will be even. if (isOdd) { isOdd = false; } // If the line is even, parse it, and indicate that the next line will be odd. else { string[] split = line.Split(' '); // COLMAP's images should have 10 parameters. if (split.Length > 9) { // Parse position and rotation, and convert them to Unity's coordinate system. Quaternion rotation = new Quaternion(GeneralToolkit.ParseFloat(split[2]), GeneralToolkit.ParseFloat(split[3]), GeneralToolkit.ParseFloat(split[4]), GeneralToolkit.ParseFloat(split[1])); Vector3 position = new Vector3(GeneralToolkit.ParseFloat(split[5]), GeneralToolkit.ParseFloat(split[6]), GeneralToolkit.ParseFloat(split[7])); ConvertCoordinatesCOLMAPToUnity(ref position, ref rotation); // Add all the parameters to the dedicated lists. positionList.Add(position); rotationList.Add(rotation); fileNameList.Add(split[9]); cameraIDList.Add(GeneralToolkit.ParseInt(split[8])); // Indicate that the next line will be odd. isOdd = true; } } } } reader.Close(); } // Use these lists to create and fill the output array of camera models. cameraSetup.cameraModels = new CameraModel[positionList.Count]; for (int iter = 0; iter < positionList.Count; iter++) { CameraModel cameraModel = cameraSetup.AddCameraModel(iter); cameraModel.SetCameraReferenceIndexAndImageName(cameraIDList[iter], fileNameList[iter]); cameraModel.transform.localPosition = positionList[iter]; cameraModel.transform.localRotation = rotationList[iter]; } }
/// <summary> /// Reads the stored additional information. /// </summary> /// <param name="cameraSetup"></param> The camera setup to modify with the parsed information. public void ReadCOLIBRIVRAdditionalInformation(CameraSetup cameraSetup) { string[] lines = File.ReadAllLines(additionalInfoFile); foreach (string line in lines) { if (!line.StartsWith("#")) { string[] split = line.Split(' '); if (split.Length > 2) { Vector3 newInitialViewingPosition = new Vector3(GeneralToolkit.ParseFloat(split[0]), GeneralToolkit.ParseFloat(split[1]), GeneralToolkit.ParseFloat(split[2])); cameraSetup.SetAdditionalParameters(newInitialViewingPosition); } } } }
/// <summary> /// Reads the stored additional information. /// </summary> /// <param name="cameraSetup"></param> The camera setup to modify with the parsed information. public void ReadCOLIBRIVRAdditionalInformation(CameraSetup cameraSetup) { string[] lines = File.ReadAllLines(additionalInfoFile); for (int i = 0; i < lines.Length; ++i) { if (lines[i].Contains("INITIAL_VIEWING_POSITION")) { string[] split = lines[++i].Split(' '); if (split.Length == 3) { Vector3 newInitialViewingPosition = new Vector3(GeneralToolkit.ParseFloat(split[0]), GeneralToolkit.ParseFloat(split[1]), GeneralToolkit.ParseFloat(split[2])); cameraSetup.SetAdditionalParameters(newInitialViewingPosition); } continue; } if (lines[i].Contains("DISTANCE_RANGE")) { while (i + 1 < lines.Length && !lines[i + 1].StartsWith("#")) { string[] split = lines[++i].Split(' '); if (split.Length == 3) { int cameraReferenceIndex = GeneralToolkit.ParseInt(split[0]); Vector2 newDistanceRange = new Vector2(GeneralToolkit.ParseFloat(split[1]), GeneralToolkit.ParseFloat(split[2])); // Find the referenced camera and set its distance range foreach (CameraModel camera in cameraSetup.cameraModels) { if (camera.cameraReferenceIndex == cameraReferenceIndex) { camera.distanceRange = newDistanceRange; } } } } } } }
/// <summary> /// Parses camera parameters for a COLMAP camera of the SIMPLE_PINHOLE or PINHOLE type. /// </summary> /// <param name="split"></param> The split string from which to parse information. /// <returns></returns> A camera model containing the parsed parameters. private static CameraModel ParsePinhole(string[] split, bool isSimple) { // Parse basic parameters for a perspective camera. CameraModel cameraModel = BasicParse(split, false); // Parse focal length based on whether this is a SIMPLE_PINHOLE or PINHOLE camera model. Vector2 focalLength = Vector2.zero; if (isSimple) { focalLength = GeneralToolkit.ParseFloat(split[4]) * Vector2.one; } else { focalLength = new Vector2(GeneralToolkit.ParseFloat(split[4]), GeneralToolkit.ParseFloat(split[5])); } // Compute field of view based on the focal length. float fieldOfViewX = Camera.FocalLengthToFieldOfView(focalLength.x, cameraModel.pixelResolution.x); float fieldOfViewY = Camera.FocalLengthToFieldOfView(focalLength.y, cameraModel.pixelResolution.y); cameraModel.fieldOfView = new Vector2(fieldOfViewX, fieldOfViewY); // Return the camera model. return(cameraModel); }