Многооконная Реконструкция
3D-объект может быть восстановлен на основе нескольких 2D изображений. Функция ImageDisplacements используется для определения параллакса от одного изображения к другому. Чем больше сдвиг параллакса, тем ближе объект позади соответствующего пикселя. С помощью этой информации, вы можете определить вершины объекта сетки, полученного с помощью функций ImageMesh и TriangulateMesh. Результат отображается путем наложения текстуры на 3D сетку.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_62.png)
Получим объект-маску центрального изображения.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_63.png)
mask = Erosion[Binarize[imgs[[2]], 0], 1];
Определим параллакс в левом и правом изображениях относительно центрального изображения.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_64.png)
parallaxL = First@ImageDisplacements[imgs[[{2, 1}]]];
![Click for copyable input](assets.ru/multi-view-reconstruction/In_65.png)
parallaxR = First@ImageDisplacements[imgs[[{2, 3}]]];
Сочетаем перемещения, выполненные в предыдущем шаге, в общем параллаксе.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_66.png)
parallax = parallaxL - parallaxR;
В данном случае, Х-компонент параллакса примерно пропорционален глубине соответствующего источника пикселей.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_67.png)
depth = Blur@
Opening[ImageMultiply[ImageAdjust@Image[parallax[[All, All, 1]]],
mask], DiskMatrix[4]]
![](assets.ru/multi-view-reconstruction/O_29.png)
Построим функцию глубины.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_68.png)
depthFunction = ListInterpolation[Transpose@Reverse@ImageData[depth]];
Получим более точный объект-сетку, с уточнением, зависящим от значимости этого объекта.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_69.png)
resolution = ImageAdjust@ImageSaliencyFilter[imgs[[2]]];
![Click for copyable input](assets.ru/multi-view-reconstruction/In_70.png)
resolutionFunction =
ListInterpolation[Transpose@Reverse@ImageData@resolution];
![Click for copyable input](assets.ru/multi-view-reconstruction/In_71.png)
\[CapitalOmega] = TriangulateMesh[
ImageMesh[Erosion[mask, DiskMatrix[2]]],
MeshRefinementFunction ->
Function[{vertices, area},
area > 32 + 512 (1 - resolutionFunction @@ Mean[vertices])^6]
]
![](assets.ru/multi-view-reconstruction/O_30.png)
Осуществим выдавливание объекта-сетки с помощью функции глубины.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_72.png)
Graphics3D[
GraphicsComplex[
Apply[{##, depthFunction[##]} &,
MeshCoordinates[\[CapitalOmega]], {1}],
{EdgeForm[], MeshCells[\[CapitalOmega], 2]}
],
PlotRange -> Append[Thread[{0, ImageDimensions[mask]}], {0, 1}],
BoxRatios -> {1, 1, 2/3},
ViewPoint -> Top
]
![](assets.ru/multi-view-reconstruction/O_31.png)
Определим текстуру объекта на основе центрального изображения.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_73.png)
texture = SetAlphaChannel[imgs[[2]], mask]
![](assets.ru/multi-view-reconstruction/O_32.png)
Наложим полученную текстуру на 3D объект.
![Click for copyable input](assets.ru/multi-view-reconstruction/In_74.png)
Graphics3D[
{Texture[texture],
GraphicsComplex[
Apply[{##, depthFunction[##]} &,
MeshCoordinates[\[CapitalOmega]], {1}],
{EdgeForm[], MeshCells[\[CapitalOmega], 2]},
VertexTextureCoordinates ->
Map[#/ImageDimensions[texture] &, MeshCoordinates[\[CapitalOmega]]]
]
},
PlotRange -> Append[Thread[{0, ImageDimensions[mask]}], {0, 1}],
BoxRatios -> {1, 1, 2/3},
Lighting -> {{"Ambient", White}},
ViewPoint -> Top,
Boxed -> False
]
![](assets.ru/multi-view-reconstruction/swf_7.png)