我希望在 Unity 中使用 EmguCV 插件在运行时实现全景图像拼接,针对移动设备。到目前为止,我可以使用高级 Stitcher API(Stitcher.stitch 方法),但是当源图像太大或太多时,该过程非常耗费资源。 我试过的:
但我仍然不确定如何正确使用并行化:/
这是我的并行作业尝试代码(Unity C#):
public struct ParallelStitchingJob : IJobParallelFor {
public NativeArray<Vector2Int> outputSize;
public NativeArray<IntPtr> outputData;
public NativeArray<int> outputStep;
public NativeArray<bool> failure;
[ReadOnly]
public NativeList<IntPtr> inputData;
[ReadOnly]
public NativeList<Vector2Int> inputSize;
[ReadOnly]
public NativeList<int> inputStep;
public float panoConfidenceThreshold;
public int iteration;
public void Execute (int outputIndex) {
bool jobFailed = false;
int inputIndex = outputIndex * 2;
int imgsCount = outputIndex == outputData.Length - 1 ? (inputData.Length % 2 == 1 ? 3 : 2) : 2;
//Debug.LogFormat ("Partial stitching job started (output index = {0}, input index = {1}, input data length = {3}, images count = {2})", outputIndex, inputIndex, imgsCount, inputData.Length);
Mat[] srcMatArray = new Mat[imgsCount];
Mat result = new Mat ();
try {
for (int i = 0; i < imgsCount; i++) {
Mat m = createIntermediateMatFromData (inputData[inputIndex + i], inputSize[inputIndex + i], inputStep[inputIndex + i]);
srcMatArray[i] = m;
// Debug.LogFormat("input Mat[{2}] (width: {0}, height: {1})", m.Cols, m.Rows, i);
/* if(Application.isEditor){
SaveIntermediateMatToFile (m, "StitchingPair" + inputIndex + "_img" + i);
} */
}
} catch (Exception e) {
jobFailed = true;
Debug.LogWarningFormat ("Error creating source images for prallel stitching job. {0}", e.Message);
result.Dispose ();
}
if (!jobFailed) {
using (Stitcher stitcher = new Stitcher (Mode.Panorama))
using (VectorOfMat vms = new VectorOfMat (srcMatArray)) {
stitcher.PanoConfidenceThresh = panoConfidenceThreshold;
Status status = stitcher.Stitch (vms, result);
if (status == Status.Ok) {
outputSize[outputIndex] = new Vector2Int (result.Cols, result.Rows);
outputData[outputIndex] = result.DataPointer;
outputStep[outputIndex] = result.Step;
} else {
//Debug.LogWarningFormat ("Hierarchical stitching job failed (output index = {0}, status = {1})", outputIndex, status);
jobFailed = true;
result.Dispose ();
}
}
}
failure[outputIndex] = jobFailed;
foreach (Mat m in srcMatArray) {
m.Dispose ();
}
/* if (!jobFailed && Application.isEditor) {
string output = string.Format ("Intermediate stitching output (iteration {0}, output index {1}", iteration, outputIndex);
SaveIntermediateMatToFile (result, output);
} */
}
}
这是调用它的 Unity 协程:
IEnumerator parallelStitchingCR (List<Texture2D> sourceImages, StitchingFinishedDelegate handler) {
CvInvoke.UseOpenCL = UseOpenCL;
CvInvoke.UseOptimized = UseOptimized;
bool failure = false;
NativeList<IntPtr> inputData = new NativeList<IntPtr> (Allocator.Persistent);
NativeList<Vector2Int> inputSize = new NativeList<Vector2Int> (Allocator.Persistent);
NativeList<int> inputStep = new NativeList<int> (Allocator.Persistent);
Mat[] initialMatArray = new Mat[sourceImages.Count];
try {
for (int i = 0; i < sourceImages.Count; i++) {
Texture2D tex = sourceImages[i];
Mat m = createIntermediateMatFromInputTexture (tex);
inputData.Add (m.DataPointer);
inputStep.Add (m.Step);
inputSize.Add (new Vector2Int (m.Cols, m.Rows));
initialMatArray[i] = m;
}
//SaveDataSnapshot (inputData, inputSize, inputStep);
} catch (Exception e) {
Debug.LogWarningFormat ("Hierarchical stitching error: {0}\n{1}", e.Message, e.StackTrace);
failure = true;
}
destroyInputImages (sourceImages);
if (!failure) {
int iterationsCount = getParallelStitchingIterationsCount (inputData.Length);
for (int i = 0; i < iterationsCount; i++) {
float thresh = 1 - i * ((1 - minPanoConfidenceThreshold) / (iterationsCount - 1));
//float thresh = PanoConfidenceThreshold;
int outputDataLength = (int) Mathf.Floor (inputData.Length / 2);
NativeArray<IntPtr> outputData = new NativeArray<IntPtr> (outputDataLength, Allocator.Persistent);
NativeArray<Vector2Int> outputSize = new NativeArray<Vector2Int> (outputDataLength, Allocator.Persistent);
NativeArray<int> outputStep = new NativeArray<int> (outputDataLength, Allocator.Persistent);
NativeArray<bool> jobFailure = new NativeArray<bool> (outputDataLength, Allocator.Persistent);
Debug.LogFormat ("Starting hierarchical stitching job (iteration {0}, confidence threshold = {1})", i, thresh);
ParallelStitchingJob job = new ParallelStitchingJob () {
inputData = inputData,
inputSize = inputSize,
inputStep = inputStep,
panoConfidenceThreshold = thresh,
outputData = outputData,
outputSize = outputSize,
outputStep = outputStep,
failure = jobFailure,
iteration = i
};
JobHandle handle = job.Schedule (outputDataLength, 1);
yield return new WaitUntil (() => handle.IsCompleted);
handle.Complete ();
Debug.LogFormat("Failures array at iteration {0}: {1}", i, string.Join(", ", jobFailure.ToArray()));
if (jobFailure.ToArray ().Any (f => f == true))
failure = true;
disposeMatsFromData (inputData, inputSize, inputStep);
if (!failure) {
inputData.Clear ();
inputSize.Clear ();
inputStep.Clear ();
inputData.CopyFrom (outputData.ToArray ());
inputSize.CopyFrom (outputSize.ToArray ());
inputStep.CopyFrom (outputStep.ToArray ());
/* if(Application.isEditor){
SaveDataSnapshot(inputData, inputSize, inputStep, "StitchingIntermediateOutput_iteration" + i + "_img");
} */
disposeMatsFromData (outputData, outputSize, outputStep);
}
outputData.Dispose ();
outputSize.Dispose ();
outputStep.Dispose ();
jobFailure.Dispose ();
if (i == 0) {
foreach (Mat m in initialMatArray) {
m.Dispose ();
}
}
if (failure) {
Debug.LogWarningFormat ("Hierarchical stitching failed at iteration {0}", i);
break;
}else{
Debug.LogFormat("Hierarchical stitching iteration {0} succeeded", i);
}
}
}
Texture2D resultTex = null;
if (!failure) {
resultTex = ImageStitching.createTextureFromData (inputData[0], inputSize[0], inputStep[0]);
}
inputData.Dispose ();
inputSize.Dispose ();
inputStep.Dispose ();
handler (!failure, resultTex);
GC.Collect();
}
显然,我对计算机视觉算法和/或 OpenCV/EmguCV 架构以及一般的并行化缺乏更深入的了解。
我的主要问题是:
任何建议将不胜感激!