【问题标题】:Edge detection overlay with lines边缘检测覆盖线
【发布时间】:2018-10-05 04:59:00
【问题描述】:

我需要用我选择的颜色覆盖在实时视频预览中检测到的边缘(就像在 Lightroom CC 应用程序中调整焦点时所做的那样)。使用 Metal 或 CoreImage 实时绘制这些线条的最简单方法是什么?我可以使用 Sobel 边缘检测来使用 Metal Performance Shader 检测边缘,但不知道如何用我选择的颜色覆盖边缘。

【问题讨论】:

  • 我想你已经找到了一些东西——有几个关于使用 Sobel 并以你选择的颜色输出的例子......如果你在那里遇到问题,你能提供细节吗?如果问题是性能,你能提供细节吗?你现在正在做什么?你在做什么有什么问题?
  • 您能否指出他们使用 Sobel 并输出颜色的示例?我不知道如何使用 Metal 或 CoreImage 或 OpenGLES 来做到这一点。
  • 基本思想可能是用Sobel核对图像进行卷积,并使用阈值输出颜色。然而,这只是一个想法,我想可能会有更好和更精确的实现。唯一的问题是我无法在互联网上搜索它,可能是缺少合适的关键字!
  • 我明白了。这里有三个链接可以帮助您进行卷积和 Sobel。 (1) THE 资源就我而言 - github.com/FlexMonkey/Filterpedia 小心,它是 Swift 2。如果你想要更深入的解释,请查看他的书 CoreImage for Swift。 (2) 我使用的 Swift 3 分支(除了我轻松升级到 Swift 4 的 Metal 过滤器之外的所有)github.com/Norod/Filterpedia 这两个都将一个数组传递给CIConvolution5X5。如果您知道如何编写自己的内核,这里有一个 3x3 矩阵供您使用 coding-experiments.blogspot.com.au/2010/07/convolution.html

标签: ios core-image metal edge-detection


【解决方案1】:

这是一个金属边缘检测着色器

kernel void edge_detect(texture2d<half, access::read>  inTexture  [[ texture(0) ]],
                        texture2d<half, access::write> outTexture [[ texture(1) ]],
                        uint2                          gid        [[ thread_position_in_grid ]]) {
    constexpr int kernel_size = 3;
    constexpr int radius = kernel_size / 2;
    
    half3x3 horizontal_kernel = half3x3(-1./8., -1./8., -1./8.,
                                        -1./8.,  1.,    -1./8.,
                                        -1./8., -1./8., -1./8.);
    half3x3 vertical_kernel = half3x3(-1./8., -1./8., -1./8.,
                                      -1./8.,  1.,    -1./8.,
                                      -1./8., -1./8., -1./8.);
    
    half3 result_horizontal(0,0,0);
    half3 result_vertical(0,0,0);
    for(int j = 0; j <= kernel_size - 1; j++) {
        for(int i = 0; i <= kernel_size - 1; i++) {
            uint2 texture_index(gid.x + (i - radius), gid.y + (j - radius));
            result_horizontal += horizontal_kernel[i][j] * inTexture.read(texture_index).rgb;
            result_vertical += vertical_kernel[i][j] * inTexture.read(texture_index).rgb;
        }
    }
    
    half3 bt601 = half3(0.299, 0.587, 0.114);
    half gray_horizontal = dot(result_horizontal.rgb, bt601);
    half gray_vertical = dot(result_vertical.rgb, bt601);
    half magnitude = length(half2(gray_horizontal, gray_vertical));
    
    outTexture.write(half4(half3(magnitude), 1), gid);
}

【讨论】:

    【解决方案2】:

    我知道这已经晚了,但如果有人仍然需要它,我现在才知道。找到边缘检测着色器非常容易,但要弄清楚如何更改检测到的边缘的颜色并不容易,尤其是如果您是新手。这是我的内核:

    typedef struct {
        simd_float3 rgb;
    } AppliedColor;
    
    kernel void edgeEffect(texture2d<half, access::read>  inputTexture  [[ texture(0) ]],
                           texture2d<half, access::read_write> outputTexture [[ texture(1) ]],
                           constant float &edgeStrength [[ buffer(0) ]],
                           constant AppliedColor &newColor [[ buffer(1) ]],
                           uint2 gid [[thread_position_in_grid]]) {
        
        
        constexpr int kernelSize = 3;
        constexpr int radius = kernelSize / 2;
        
        half3x3 horizontalKernel = half3x3(-1, -2, -1,
                                           0, 0, 0,
                                           1, 2, 1);
        
        half3x3 verticalKernel = half3x3(1, 0, -1,
                                         2, 0, -2,
                                         1, 0, -1);
        
        half3 horizontalResult(0, 0, 0);
        half3 verticalResult(0, 0, 0);
        
        for(int j = 0; j <= kernelSize - 1; j++) {
            for(int i = 0; i <= kernelSize - 1; i++) {
                uint2 textureIndex(gid.x + (i - radius), gid.y + (j - radius));
                horizontalResult += horizontalKernel[i][j] * inputTexture.read(textureIndex).rgb;
                verticalResult += verticalKernel[i][j] * inputTexture.read(textureIndex).rgb;
            }
        }
        
        half horizontalWhite = dot(horizontalResult.rgb, half3(1.0));
        half verticalWhite = dot(verticalResult.rgb, half3(1.0));
        
        half magnitude = length(half2(horizontalWhite, verticalWhite)) * edgeStrength;
        
        outputTexture.write(half4(half3(newColor.rgb * magnitude), 1), gid);
    
    }//edgeEffect
    
    

    这是使用 Sobel 核来计算导数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 2012-11-20
      • 2014-06-12
      • 1970-01-01
      • 2015-08-29
      • 1970-01-01
      • 2021-03-01
      相关资源
      最近更新 更多