2

我目前正在尝试实现一种生成TSP art的方法,为此我需要一个点列表 (x,y),其局部密度与给定图像的灰度像素值成正比。

我的第一个想法是:这很像统计的逆变换采样(您想绘制一个与给定概率密度函数匹配的样本,但您只能创建一个均匀分布的样本)。

我实现了这一点,它工作得相当好,通过执行以下代码可以明显看出:

%% Load image, adjust it for our needs
im=imread('http://goo.gl/DDwV3t');  %load random headshot from google
im=imadjust(im,stretchlim(im,[.01,.65]),[]);
im=im2double(rgb2gray(im));
im=im(10:end-5,50:end-5);
figure;imshow(im);title('original');

im=1-im; %we want black dots on white background
im=flipud(im); %and we want it the right way up

%% process per row
imrow = cumsum(im,2);
imrow=imrow*size(imrow,1)./repmat(max(imrow,[],2),1,size(imrow,2));
y=1:size(imrow,2);
ximrow_i = zeros(size(imrow));
for i = 1:size(imrow,1)
    mask =logical([diff(imrow(i,:))>=0.01,0]); %needed for interp
    ximrow_i(i,:) = interp1(imrow(i,mask),y(mask),y);
end
y=1:size(ximrow_i,1);
y=repmat(y',1,size(ximrow_i,2));

y1=y(1:5:end,1:5:end);   %downscale a bit
ximcol_i1=ximrow_i(1:5:end,1:5:end); %downscale a bit
figure('Color','w');plot(ximcol_i1(:),y1(:),'k.');title('Inverse Transform Sampling on rows');
axis equal;axis off;

%% process per column
imcol=cumsum(im,1);
imcol=imcol*size(imcol,2)./repmat(max(imcol,[],1),size(imcol,1),1);
y=1:size(imcol,1);

yimcol_i=zeros(size(imcol));
for i = 1:size(imcol,2)
    mask =logical([diff(imcol(:,i))>=0.01;0]);
    yimcol_i(:,i) = interp1(imcol(mask,i),y(mask),y);
end
y=1:size(imcol,2);
y=repmat(y,size(imcol,1),1);

y1=y(1:5:end,1:5:end);
yimcol_i1=yimcol_i(1:5:end,1:5:end);
figure('Color','w');plot(y1(:),yimcol_i1(:),'k.');title('Inverse Transform Sampling on cols');
axis equal;axis off;

它的缺点是我只能按行或按列使用,但不能同时使用。逆变换采样方法通常不适用于多变量 PDF,我很确定在这种情况下我无法让它工作。

有没有一种简单的方法可以实现我尚未见过的目标?

我知道一种称为 Voronoi Stippler 的算法已用于创建所需的结果,我将对此进行调查,但目前我喜欢逆变换采样的简单性,并想知道我是否可以扩展该方法以满足我的需要.

4

1 回答 1

1

事实证明,这相当简单,可以通过拒绝采样来完成。

对于工具分布为 U(0,1) 的特殊情况,它的工作方式如下(如果我理解正确的话):

im=imread('http://goo.gl/DDwV3t');  %load random headshot from google
im=imadjust(im,stretchlim(im,[.01,.65]),[]);
im=im2double(rgb2gray(im));
im=im(10:end-5,50:end-5);
im=1-flipud(im);

d = im > .9*rand(size(im));
d=d&(rand(size(d))>.95);  %randomly sieve out some more points
[i,j]=ind2sub(size(d),find(d));
figure('Color','w');plot(j,i,'k.');title('Rejection Sampling');
axis equal;axis off;

采样在一行中完成:

d = im > .9*rand(size(im));

由于我最终得到了太多点,因此我随机抽取了结果,从而将点数减少了大约 20 倍。

这几乎是我最初想要的结果。

于 2014-05-27T14:56:30.637 回答