基于块的纹理合成 matlab程序,基于块拼接的纹理合成算法

此篇博客详细介绍了如何使用MATLAB进行图像缝接,涉及参数设置如块大小、交迭、缩放等,以及关键函数如`findmatch`和`mincut`在合成纹理过程中的应用。通过示例代码展示了如何处理源纹理、生成合成纹理,并展示了边界优化选项。
摘要由CSDN通过智能技术生成

% 设置 MATLAB 初始环境.

clear; clc; randseed(0);

% 设置图像缝接的参数.

sourceTexture = './textures/examples/synthetic.jpg'; % 源纹理

blockSize = [15

15]; % 块大小

blockOverlap =

ceil(blockSize/5); % 块交迭大小

scaleFactor =

3; % scale factor for synthesized texture

preCache =

false; % enable/disable source block caching

errorTol =

0.1; % 容忍的匹配错误值

colorSpace =

'RGB'; % 选择的颜色空间是 RGB或者L*A*B

bndCut =

true; % 是否开启边界最优化

% 源纹理处理之前 (对合成的每个块进行摘录)

% 载入源纹理.

S.image =

im2double(imread(sourceTexture));

S.nrows =

size(S.image,1);

S.ncols =

size(S.image,2);

S.ncolors = size(S.image,3);

S.nblocks = [S.nrows S.ncols]-blockSize+1;

% 转换成 L*A*B* 颜色空间 (如果需要).

if strcmp(colorSpace,'LAB')

S.image =

applycform(S.image,makecform('srgb2lab'));

end

% 显示源纹理.

figure(1); clf;

if strcmp(colorSpace,'RGB')

imagesc(S.image);

else

imagesc(applycform(S.image,makecform('lab2srgb')));

end

set(gcf,'Name','Source Texture');

if S.ncolors == 1

colormap gray;

end

axis image; drawnow;

% 判断块大小和交迭块是否属于正常情况.

if (blockSize(1) > S.nrows) || (blockSize(2) > S.ncols)

error(['The output texture

does not support ',...

int2str(blockSize(1)),'x',int2str(blockSize(2)),' blocks.']);

end

if (blockOverlap(1) >= blockSize(1)) || (blockOverlap(2) >=

blockSize(2))

error(['A

',int2str(blockSize(1)),'x',int2str(blockSize(2)),...

' block does not support ',...

int2str(blockOverlap(1)),'x',int2str(blockOverlap(2)),'

overlaps.']);

end

%取源块的决定性区域.

[C,R] = meshgrid(1:S.nblocks(2),1:S.nblocks(1));

R = R'; C = C'; S.blockIndex = [R(:) C(:)];

blockRows = 0:blockSize(1)-1;

blockCols = 0:blockSize(2)-1;

% 连接源块到单个矩阵.

if preCache

S.blocks =

zeros(S.ncolors*prod(blockSize),prod(S.nblocks));

for i = 1:S.nblocks(1)

for j =1:S.nblocks(2)

S.blocks(:,(i-1)*S.nblocks(2)+j) = ...

reshape(S.image(i+blockRows,j+blockCols,:),[],1);

end

end

end

% 用图像缝合(IQ)产生一个合成纹理.

% Allocate storage for the synthesized output image/mask.

% 分配存储

% Note: Increase size to prevent clipped blocks at edges.

% 注意: 为保证省略块边缘增加大小,合成后修剪输出图像

% Remember to crop output image after synthesis.

% 合成后保存输出图像

overlapSize = blockSize-blockOverlap;

T.nrows =

overlapSize(1)*(ceil(scaleFactor*S.nrows/overlapSize(1))-1)+blockSize(1);

T.ncols =

overlapSize(2)*(ceil(scaleFactor*S.ncols/overlapSize(2))-1)+blockSize(2);

T.ncolors = S.ncolors;

T.nblocks = floor([T.nrows T.ncols]./overlapSize);

T.image =

zeros(T.nrows,T.ncols,T.ncolors);

T.mask =

false(T.nrows,T.ncols,T.ncolors);

T.cut = false(T.nrows,T.ncols);

% Determine locations of overlapping output blocks.

% 确定重叠输出块的位置

[C,R] = meshgrid(overlapSize(2)*(0:T.nblocks(2)-1)+1,...

overlapSize(1)*(0:T.nblocks(1)-1)+1);

R = R'; C = C'; T.blockIndex = [R(:) C(:)];

% Seed the synthesized texture with a random block.

i = ceil(prod(S.nblocks)*rand);

B = S.image(S.blockIndex(i,1)+blockRows,...

S.blockIndex(i,2)+blockCols,:);

T.image(blockRows+1,blockCols+1,:) = B;

T.mask(blockRows+1,blockCols+1,:) = 1;

% Display synthesized texture.

figure(2); clf;

if strcmp(colorSpace,'RGB')

imagesc(T.image);

else

imagesc(applycform(T.image,makecform('lab2srgb')));

end

set(gcf,'Name','Synthesized Texture');

if S.ncolors == 1

colormap gray;

end

axis image; drawnow;

% Synthesize the remaining pixels using IQ.

for i = 2:prod(T.nblocks)

% Extract current value

(i.e., the overlapping region).

B1 =

T.image(T.blockIndex(i,1)+blockRows,...

T.blockIndex(i,2)+blockCols,:);

M =

T.mask(T.blockIndex(i,1)+blockRows,...

T.blockIndex(i,2)+blockCols,:);

% 在源纹理中寻找相似块.

% Note: Either use pre-cached

blocks or draw from input texture.

B2 =

findmatch(S,B1,M,preCache,errorTol);

% Evaluate minimum boundary

cut.

if bndCut

[B3,C] = mincut(B1,B2,M);

T.cut(T.blockIndex(i,1)+blockRows,...

T.blockIndex(i,2)+blockCols,:) = ...

T.cut(T.blockIndex(i,1)+blockRows,...

T.blockIndex(i,2)+blockCols,:) | C;

else

B3 = B2;

end

% Update output/mask values

for this block.

T.image(T.blockIndex(i,1)+blockRows,...

T.blockIndex(i,2)+blockCols,:) = B3;

T.mask(T.blockIndex(i,1)+blockRows,...

T.blockIndex(i,2)+blockCols,:) = 1;

% Display synthesis

progress.

figure(2);

clf; % 关闭进程体

if

strcmp(colorSpace,'RGB')

imagesc(T.image);

else

imagesc(applycform(T.image,makecform('lab2srgb')));

end

axis image; drawnow;

end % End of IQ synthesis.

% 显示结果.

% Display synthesized texture.

figure(2); clf; %

关闭进程体

if strcmp(colorSpace,'RGB')

imagesc(T.image);

else

imagesc(applycform(T.image,makecform('lab2srgb')));

end

axis image; set(gcf,'Name','Synthesized Texture');

if S.ncolors == 1

colormap gray;

end

% 显示合成纹理的分割分界线.

if bndCut

figure(3); clf;

if

strcmp(colorSpace,'RGB')

I = T.image;

else

I = applycform(T.image,makecform('lab2srgb'));

end

if S.ncolors ==1

I = repmat(I,[1 1 3]);

end

R = I(:,:,1); G = I(:,:,2); B

= I(:,:,3);

idx = find(T.cut); R(idx) =

1*T.cut(idx) + 0*R(idx);

G(idx) = 0; B(idx) = 0;

I = cat(3,R,G,B); imagesc(I);

axis image;

axis image;

set(gcf,'Name','Synthesized Texture and Boundary Cuts');

end

findmatch.m:

function B =

findmatch(S,B1,M,preCache,errorTol)

% Vectorize search block (using input

mask).

blockRows = 0:size(B1,1)-1;

blockCols = 0:size(B1,2)-1;

B1 = B1(M);

% Perform exhaustive search to determine

similar blocks.

E = zeros(1,prod(S.nblocks));

if preCache

E =

sum((repmat(B1,1,prod(S.nblocks))-S.blocks(M,:)).^2,1);

else

for i =

1:prod(S.nblocks)

B2 =

S.image(S.blockIndex(i,1)+blockRows,S.blockIndex(i,2)+blockCols,:);

E(i) = sum((B1-B2(M)).^2);

end

end

% Randomly select output block among

matches.

% 随机选择一个匹配输出块

match_index = find(E <= (1+errorTol^2)*min(E));

i = ceil(length(match_index)*rand);

B = S.image(S.blockIndex(match_index(i),1)+blockRows,...

S.blockIndex(match_index(i),2)+blockCols,:);

mincut.m:

function [B,C] = mincut(B1,B2,M)

% Part I: Evaluate overlap error and extract horizontal/vertical

regions.

% 第一部分:

% Evaluate overlap error (using L2 norm).

E = M(:,:,1).*sum((B1-B2).^2,3);

% Extract horizontal and vertical overlap regions.

if M(1,end,1) == 1

blockOverlap(1) =

find(M(:,end,1),1,'last');

H =

E(1:blockOverlap(1),:);

else

H = [];

end

if M(end,1,1) == 1

blockOverlap(2) =

find(M(end,:,1),1,'last');

V =

E(:,1:blockOverlap(2));

else

V = [];

end

% Part II: minimum-error horizontal boundary cut (if

necessary).

% 第二部分:

% Evaluate minimum-error horizontal boundary cut.

if ~isempty(H)

% Recursively compute path

costs.

% 递归计算路径开销

CH = zeros(size(H));

CH(:,end) = H(:,end);

for j =

(size(H,2)-1):-1:1

for i = 1:size(H,1)

if i == 1

CH(i,j) = H(i,j) + min(CH(i+(0:1),j+1));

elseif i == size(H,1)

CH(i,j) = H(i,j) + min(CH(i+(-1:0),j+1));

else

CH(i,j) = H(i,j) + min(CH(i+(-1:1),j+1));

end

end

end

end % End of horizontal boundary cut.

% Part III: minimum-error vertical boundary cut (if

necessary).

% 第三部分:

% Evaluate minimum-error vertical boundary cut.

if ~isempty(V)

% Recursively compute path

costs.

% 递归计算路径开销

CV = zeros(size(V));

CV(end,:) = V(end,:);

for i =

(size(V,1)-1):-1:1

for j = 1:size(V,2)

if j == 1

CV(i,j) = V(i,j) + min(CV(i+1,j+(0:1)));

elseif j == size(V,2)

CV(i,j) = V(i,j) + min(CV(i+1,j+(-1:0)));

else

CV(i,j) = V(i,j) + min(CV(i+1,j+(-1:1)));

end

end

end

end % End of vertical boundary cut.

% Part IV: Evaluate total minimum-error boundary cut (if

necessary).

% 第四部分:

% Allocate storage for image mask (i.e., filled

boundaries).

C = false(size(E));

M = false(size(B1));

% Determine total minimum-error boundary cut.

% 确定总最小误差分割分界线

% Case 1: Only horizonal overlap (e.g., along first scan

column).

if (~isempty(H) && isempty(V))

% Trace cost matrix to

determine boundary cut.

[ignore,i] =

min(CH(:,1));

C(i,1) = 1; M(i:end,1,:) =

1;

for j = 2:size(H,2)

if i == 1

[ignore,i] = min(CH(i+(0:1),j));

elseif i == size(H,1)

[ignore,di] = min(CH(i+(-1:0),j));

i = i+(di-2);

else

[ignore,di] = min(CH(i+(-1:1),j));

i = i+(di-2);

end

C(i,j) = 1; M(i:end,j,:) = 1;

end

% Case 2: Only vertical overlap (e.g., along first scan row).

elseif (isempty(H) && ~isempty(V))

% Trace cost matrix to

determine boundary cut.

[ignore,j] =

min(CV(1,:));

C(1,j) = 1; M(1,j:end,:) =

1;

for i = 2:size(V,1)

if j == 1

[ignore,j] = min(CV(i,j+(0:1)));

elseif j == size(V,2)

[ignore,dj] = min(CV(i,j+(-1:0)));

j = j+(dj-2);

else

[ignore,dj] = min(CV(i,j+(-1:1)));

j = j+(dj-2);

end

C(i,j) = 1; M(i,j:end,:) = 1;

end

% Case 3: Both vertical and horizontal overlaps.

else

% Determine pixel where

vertical/horizontal cuts intersect.

CC =

CH(1:blockOverlap(1),1:blockOverlap(2)) + ...

CV(1:blockOverlap(1),1:blockOverlap(2)) - ...

E(1:blockOverlap(1),1:blockOverlap(2));

% Invert pixel assignment

mask.

M = ~M;

% Trace back from intersection

to determine horizontal boundary cut.

[ignore,p] = min(CC(:)); [i,j]

= ind2sub(blockOverlap,p);

C(i,j) = 1; M(1:i,j,:) =

0;

for j = (j+1):size(H,2)

if i == 1

[ignore,i] = min(CH(i+(0:1),j));

elseif i == size(H,1)

[ignore,di] = min(CH(i+(-1:0),j));

i = i+(di-2);

else

[ignore,di] = min(CH(i+(-1:1),j));

i = i+(di-2);

end

C(i,j) = 1; M(1:i,j,:) = 0;

end

% Trace back from intersection

to determine vertical boundary cut.

[ignore,p] = min(CC(:)); [i,j]

= ind2sub(blockOverlap,p);

C(i,j) = 1; M(i,1:j,:) =

0;

for i = (i+1):size(V,1)

if j == 1

[ignore,j] = min(CV(i,j+(0:1)));

elseif j == size(V,2)

[ignore,dj] = min(CV(i,j+(-1:0)));

j = j+(dj-2);

else

[ignore,dj] = min(CV(i,j+(-1:1)));

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值