【问题标题】:Custom CIKernel Displacement Map自定义 CIKernel 置换贴图
【发布时间】:2022-05-10 17:28:20
【问题描述】:

我正在尝试为 iOS 8 创建一个置换贴图 cikernel,它将像素从贴图 R 通道水平移动并从 G 通道垂直移动。 地图像素坐标必须相对于源图像大小 mapPixel = ((dest.x/source.width) * map.width, (dest.y / source.height) * map.height)

我测试的输入图像尺寸是 2048 x 2048 并且地图是红绿柏林噪声 2560 x 2560

在 Quartz Composer 中,cikernel 几乎可以正常工作,只是地图没有应用于整个图像

kernel vec4 coreImageKernel(sampler image, sampler displaceMap, float scaleX, float scaleY)
{
 vec2 destination = destCoord();

 vec2 imageSize = samplerSize(image);
 float xPercent = destination.x / imageSize.x;
 float yPercent = destination.y / imageSize.y;

 vec2 mapSize = samplerSize(displaceMap);
 vec2 mapCoord = vec2(mapSize.x * xPercent, mapSize.y * yPercent);

 vec4 mapPixel = sample(displaceMap, mapCoord);
 float ratioShiftX = ((mapPixel.x) * 2.0) - 1.0;
 float ratioShiftY = ((mapPixel.y) * 2.0) - 1.0;
 vec2 pixelShift = vec2(ratioShiftX * scaleX, ratioShiftY * scaleY);

 return sample(image, destination - pixelShift);
}

过滤器函数如下所示:

function __image main(__image image, __image displaceMap, __number scaleX, __number scaleY) {
  return coreImageKernel.apply(image.definition, null, image, displaceMap, scaleX, scaleY);
}

但是当我在 CIFilter 中加载 cikernel 时,结果与我在 Quartz Composer 中看到的相差甚远。 这是我的应用函数在 CIFilter 中的样子

override var outputImage:CIImage? {
    if let inputImage = inputImage {
        if let inputMap = inputMap {
            let args = [inputImage as AnyObject, inputMap as AnyObject, inputScaleX, inputScaleY]

            return CIDisplacementMapFilter.kernel?.applyWithExtent(inputImage.extent, roiCallback: {
                    (index, rect) in

                    if index == 0 {
                        return rect
                    }

                    return CGRectInfinite
                }, arguments: args)
        }
    }

    return nil
}

我猜 ROI 是错误的,采样器是平铺的,但我想不通。

【问题讨论】:

    标签: ios objective-c swift core-image cifilter


    【解决方案1】:

    事实证明内核是错误的。 这是一个完成这项工作的内核

    kernel vec4 displace(sampler source, sampler map, float scaleX, float scaleY)
    {
    
    vec2 d = destCoord();
    vec4 mapPixel = sample(map, samplerTransform(map, d));
    float shiftX = ((mapPixel.x * 2.0) - 1.0) * scaleX;
    float shiftY = ((mapPixel.y * 2.0) - 1.0) * scaleY;
    
    vec2 s = samplerTransform(source, d + vec2(shiftX, shiftY));
    
    return sample(source, s);
    }
    

    【讨论】:

    • 谢谢。如果有人感兴趣,我会用金属的代码发布答案。
    【解决方案2】:

    这与 Metal 的代码相同

    #include <metal_stdlib>
    using namespace metal;
    #include <CoreImage/CoreImage.h>
    
    extern "C" {
      namespace coreimage {
        float4 displaceFilterKernel(sampler source, sampler map, float scaleX, float scaleY)
        {
          float2 d = map.coord();
          float4 mapPixel = map.sample(d);
          float shiftX = ((mapPixel.x * 2.0) - 1.0) * scaleX;
          float shiftY = ((mapPixel.y * 2.0) - 1.0) * scaleY;
          float2 s = d + float2(shiftX, shiftY);
          return sample(source, s);
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-22
      • 2019-05-18
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-11
      • 1970-01-01
      相关资源
      最近更新 更多