我目前正在编写我自己的 Matlab 实现,该实现是 2003 年的一篇论文,在任意网格上的快速纹理合成。一切都很顺利,除了相似变换的旋转部分,这意味着在 3D 表面上创建一个矢量场。这是算法的一个非常重要的部分,因为它在整个 3D 表面上提供了更自然和连贯的纹理方面。
问题是,我只是不知道该怎么做。我发现的关于这个主题的文献对我来说非常模糊,所以我现在正在寻找一种更实用(和程序化)的方式来执行此操作。
任何想法 ?
[编辑] 以防万一,我尝试了这段代码,它使用重心插值将纹理图像映射到 3D 网格。但是,在示例中,给定的纹理顶点索引是事先已知的,因此,据我所知,我仍然坚持纹理图像和 3D 网格之间的相似性变换的旋转部分。我仍然需要在表面周围创建一个矢量场。
最后,这是我写的关于 Magda 和 Kriegman 算法的纹理预处理部分的代码:
%% Implementation inspired by the work of Magda & Kriegman(2003), "Fast Texture Synthesis on Arbitrary Mesh"
function [TextonImage, LUT, TextonBucket] = GenerateTextons( SampleImage, gaussianSize, nbKmeansCenters )
% Create Gaussian kernel
h = fspecial( 'gaussian', gaussianSize );
% Generate feature vectors
FeatureVectors = ComputeFeatureVectors( h, SampleImage );
% Perform k-mean clustering, classify feature vectors (i.e. assign labels)
[IDX,C] = kmeans( FeatureVectors, nbKmeansCenters );
% Create texton texture
LUT = randi( 255, size( C, 1 ), 3 );
[TextonImage, TextonBucket] = CreateTextonTexture( C, SampleImage, LUT, h );
end
function Vectors = ComputeFeatureVectors( Kernel, Image )
offset = floor( size( Kernel, 1 ) / 2 );
vectorsSize = ( size( Image, 1 ) - 2 * offset ) * ( size( Image, 2 ) - 2 * offset );
Vectors = zeros( vectorsSize, size( Kernel, 1 ) * size( Kernel, 1 ) );
kk = 1;
for ii = ( 1 + offset ):( size( Image, 1 ) - offset )
for jj = ( 1 + offset ):( size( Image, 2 ) - offset )
temp = Kernel .* double( Image( ii - offset:ii + offset, jj - offset:jj + offset ) );
Vectors( kk, : ) = reshape( temp, size( Kernel, 1 ) * size( Kernel, 1 ), 1 )';
kk = kk + 1;
end
end
end
function [ TextonImage, TextonBucket ] = CreateTextonTexture( Centroids, Image, LUT, Kernel )
offset = floor( size( Kernel, 1 ) / 2 );
TextonImage = zeros( size( Image, 1 ), size( Image, 2 ), 3 );
TextonBucket = struct;
IndexTable = zeros( size( Centroids, 1 ), 1 );
for ii = ( 1 + offset ):(size( Image, 1 ) - offset)
for jj = ( 1 + offset ):(size( Image, 2 ) - offset)
temp = Kernel .* double( Image( ii - offset:ii + offset, jj - offset:jj + offset ) );
Vector = reshape( temp, size( Kernel, 1 ) * size( Kernel, 1 ), 1 )';
minDist = 10000;
Index = 0;
for k=1:size( Centroids, 1 )
% Calculate distance of test point to training point.
d = sum( Vector - Centroids( k, : ) ) .^ 2;
% if smaller...
if d < minDist
minDist = d;
Index = k;
end
end
TextonImage( ii, jj, : ) = LUT( Index, : );
cellName = strcat('B',num2str(Index));
IndexTable( Index ) = IndexTable( Index ) + 1;
TextonBucket.(cellName){ IndexTable( Index ) } = [ jj, ii ];
end
end
end
谢谢你。