首页
学习
活动
专区
圈层
工具
发布

贴图
EN

Code Golf用户
提问于 2016-01-29 22:06:46
回答 7查看 8.3K关注 0票数 119

在一个流行的图像编辑软件中,有一个特性,即补丁(用于图像处理的术语是修复,如@mınxomaτ所指出的那样)。图像的选定区域,基于该修补程序之外的信息。而且它做得很好,考虑到这只是一个程序。作为一个人,你有时会看到一些不对劲的地方,但是如果你挤一下眼睛,或者只是看一眼,这个补丁似乎就能很好地填补这个空白。

挑战

给定指定图像矩形区域的图像和掩码应该进行修补(也可以作为图像或任何其他首选格式),您的程序应该尝试在指定的区域填充一个修补程序,试图将其与图像的其余部分混合。程序不能使用位于指定区域内的原始图像的信息。

你可以假设这个贴片至少它的宽度远离侧面,它的高度远离图像的顶部和底部。这意味着补丁的最大面积是整个图像的1/9。

请简单介绍一下你的算法是如何工作的。

投票

投票人被要求判断算法执行得有多好,并据此投票。

关于如何判断的一些建议:(再次感谢@mınxomaτ提供更多的标准。)

  • 如果你眯着眼睛,照片看上去还好吗?
  • 你能准确地知道补丁在哪里吗?
  • 如何从图像背景和周围地区的结构和纹理继续?
  • 编辑的区域包含多少杂散的假彩色像素?
  • 该地区是否有任何颜色一致的斑点/区块似乎不属于那里?
  • 与图像的其他部分相比,编辑后的区域是否有任何强烈的颜色/对比度或亮度变化?

效度标准

为了使提交有效,输出映像必须与指定区域外的输入映像完全匹配。

测试用例

在左侧的源图像上,在右侧对应的掩码:

EN

回答 7

Code Golf用户

发布于 2016-01-30 00:11:31

Matlab

这是一种简单的插值方法。这个想法首先反映补丁两边的内容。然后,通过这些镜像像素离对应边缘的距离来插值:

最棘手的部分是找到一个很好的内插权重。在玩了几次之后,我想出了一个有理函数,除了我们镜像的那个外,所有边都是零。然后,用三次多项式来进行平滑:

这种简单的方法在“自然”图像上表现出奇的好,但一旦你面对锋利的边缘,游戏就结束了。在美国哥特式的例子中,干草叉的尖峰与像素网格很好地排列在一起,这使得它看起来相当漂亮,但如果不是这样的话,情况会更糟。

因此,这里的结果:

最后,守则:

代码语言:javascript
复制
imgfile= 'filename.png';
maskfile = [imgfile(1:end-4),'_mask.png'];
img = double(imread(imgfile));
mask = rgb2gray(imread(maskfile));
%% read mask
xmin = find(sum(mask,1),1,'first');
xmax = find(sum(mask,1),1,'last');
ymin = find(sum(mask,2),1,'first');
ymax = find(sum(mask,2),1,'last');
%% weight transformation functiosn
third = @(x)-2* x.^3 + 3* x.^2;
f=@(x)third(x);
w=@(x,y)y.*(x-1).*(y-1)./( (x+y).*(x+1-y));

for x=xmin:xmax
    for y=ymin:ymax
        %Left Right Up Down;
        P = [img(y,xmin-(x-xmin)-1,:);img(y,xmax+(xmax-x)+1,:);img(ymin-(y-ymin)-1,x,:);img(ymax+(ymax-y)+1,x,:)];
        % normalize coordinates
        rx = (x-xmin)/(xmax-xmin); 
        ry = (y-ymin)/(ymax-ymin);
        % calculate the weights
        W = [w(rx,ry),w(1-rx,ry),w(ry,rx),w(1-ry,rx)]';
        W = f(W);
        W(isnan(W))=1;
        img(y,x,:) = sum(bsxfun(@times,P,W),1)/sum(W); 
    end
end
imshow(img/255);
imwrite(img/255,[imgfile(1:end-4),'_out.png']);
票数 45
EN

Code Golf用户

发布于 2016-01-30 21:54:53

Mathematica

它使用Mathematica的Inpaint函数。因为Mathematica自己做所有的工作,这是一个社区wiki。

inPaint (以下)是Inpaint的简单改编。对于彩色绘画/照片,它使用默认的"TextureSynthesis“设置。如果它检测到图片是黑白的(因为图片的图像数据与图像的二进制格式的图像数据相同),那么它就对图像进行二值化,并应用"TotalVariation“补丁。If子句将BinarizeIdentity应用于图片。( Identity函数不改变地返回其参数。)

代码语言:javascript
复制
inPaint[picture_, mask_] :=  
 If[bw = ImageData@Rasterize[Binarize[picture]] == ImageData[picture], Binarize, Identity]@
  Inpaint[picture, mask, Method -> If[bw, "TotalVariation", "TextureSynthesis"]]

图像和掩码作为inPaint的参数输入。PartitionGrid只是用来格式化的。

产出已得到修补。inPaint后未进行图像修整。

票数 25
EN

Code Golf用户

发布于 2016-01-30 09:14:11

Python2和PIL

该程序混合了北、南、东和西区域的副本,以创建使用颜色、纹理和地方图像区域阴影的替换像素。

该示例输出:

代码首先找到修补程序的边界框。然后,对于要生成的每个像素,根据周围4个区域的加权和计算每个通道(RGB)的颜色。

代码语言:javascript
复制
import sys
from PIL import Image

infile, maskfile, outfile = sys.argv[1:4]
imageobj = Image.open(infile)
maskobj = Image.open(maskfile)
image = imageobj.load()
mask = maskobj.load()

assert imageobj.size == maskobj.size
W, H = imageobj.size
pixels = [(x,y) for x in range(W) for y in range(H)]
whitepart = [xy for xy in pixels if sum(mask[xy]) > 230*3]
xmin = min(x for x,y in whitepart)
xmax = max(x for x,y in whitepart)
ymin = min(y for x,y in whitepart)
ymax = max(y for x,y in whitepart)
xspan = xmax - xmin + 1
yspan = ymax - ymin + 1

def mkcolor(channel):
    value = image[(xmin-dx, y)][channel] * 0.5*(xspan - dx)/xspan
    value += image[(xmax+1 + xspan - dx, y)][channel] * 0.5*dx/xspan
    value += image[(x, ymin-dy)][channel] * 0.5*(yspan - dy)/yspan
    value += image[(x, ymax+1 + yspan - dy)][channel] * 0.5*dy/yspan
    return int(value)

for dx in range(xspan):
    for dy in range(yspan):
        x = xmin + dx
        y = ymin + dy
        image[(x, y)] = (mkcolor(0), mkcolor(1), mkcolor(2))

imageobj.save(outfile)
票数 20
EN
页面原文内容由Code Golf提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codegolf.stackexchange.com/questions/70483

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档