Sobel filter kernel of large size

后端 未结 9 801
渐次进展
渐次进展 2020-12-02 08:38

I am using a sobel filter of size 3x3 to calculate the image derivative. Looking at some articles on the internet, it seems that kernels for sobel filter for size 5x5 and 7x

9条回答
  •  情书的邮戳
    2020-12-02 09:27

    Sobel gradient filter generator

    (This answer refers to the analysis given by @Daniel, above.)

    Gx[i,j] = i / (i*i + j*j)
    
    Gy[i,j] = j / (i*i + j*j)
    

    This is an important result, and a better explanation than can be found in the original paper. It should be written up in Wikipedia, or somewhere, because it also seems superior to any other discussion of the issue available on the internet.

    However, it is not actually true that integer-valued representations are impractical for filters of size greater than 5*5, as claimed. Using 64-bit integers, Sobel filter sizes up to 15*15 can be exactly expressed.

    Here are the first four; the result should be divided by the "weight", so that the gradient of an image region such as the following, is normalized to a value of 1.

    1 2 3 4 5
    1 2 3 4 5
    1 2 3 4 5
    1 2 3 4 5
    1 2 3 4 5
    

    Gx(3) :

    -1/2  0/1  1/2           -1  0  1
    -1/1    0  1/1   * 2 =   -2  0  2
    -1/2  0/1  1/2           -1  0  1
    
    weight = 4               weight = 8
    

    Gx(5) :

    -2/8 -1/5  0/4  1/5  2/8             -5  -4   0   4   5
    -2/5 -1/2  0/1  1/2  2/5             -8 -10   0  10   8
    -2/4 -1/1    0  1/1  2/4   * 20 =   -10 -20   0  20  10
    -2/5 -1/2  0/1  1/2  2/5             -8 -10   0  10   8
    -2/8 -1/5  0/4  1/5  2/8             -5  -4   0   4   5
    
    weight = 12                          weight = 240
    

    Gx(7) :

    -3/18 -2/13 -1/10   0/9  1/10  2/13  3/18             -130 -120  -78    0   78  120  130
    -3/13  -2/8  -1/5   0/4   1/5   2/8  3/13             -180 -195 -156    0  156  195  180
    -3/10  -2/5  -1/2   0/1   1/2   2/5  3/10             -234 -312 -390    0  390  312  234
     -3/9  -2/4  -1/1     0   1/1   2/4   3/9   * 780 =   -260 -390 -780    0  780  390  260
    -3/10  -2/5  -1/2   0/1   1/2   2/5  3/10             -234 -312 -390    0  390  312  234
    -3/13  -2/8  -1/5   0/4   1/5   2/8  3/13             -180 -195 -156    0  156  195  180
    -3/18 -2/13 -1/10   0/9  1/10  2/13  3/18             -130 -120  -78    0   78  120  130
    
    weight = 24                                           weight = 18720
    

    Gx(9) :

    -4/32 -3/25 -2/20 -1/17  0/16  1/17  2/20  3/25  4/32                -16575  -15912  -13260   -7800       0    7800   13260   15912   16575
    -4/25 -3/18 -2/13 -1/10   0/9  1/10  2/13  3/18  4/25                -21216  -22100  -20400  -13260       0   13260   20400   22100   21216
    -4/20 -3/13  -2/8  -1/5   0/4   1/5   2/8  3/13  4/20                -26520  -30600  -33150  -26520       0   26520   33150   30600   26520
    -4/17 -3/10  -2/5  -1/2   0/1   1/2   2/5  3/10  4/17                -31200  -39780  -53040  -66300       0   66300   53040   39780   31200
    -4/16  -3/9  -2/4  -1/1     0   1/1   2/4   3/9  4/16   * 132600 =   -33150  -44200  -66300 -132600       0  132600   66300   44200   33150
    -4/17 -3/10  -2/5  -1/2   0/1   1/2   2/5  3/10  4/17                -31200  -39780  -53040  -66300       0   66300   53040   39780   31200
    -4/20 -3/13  -2/8  -1/5   0/4   1/5   2/8  3/13  4/20                -26520  -30600  -33150  -26520       0   26520   33150   30600   26520
    -4/25 -3/18 -2/13 -1/10   0/9  1/10  2/13  3/18  4/25                -21216  -22100  -20400  -13260       0   13260   20400   22100   21216
    -4/32 -3/25 -2/20 -1/17  0/16  1/17  2/20  3/25  4/32                -16575  -15912  -13260   -7800       0    7800   13260   15912   16575
    
    weight = 40                                                          weight = 5304000
    

    The Ruby program appended below, will calculate Sobel filters and corresponding weights of any size, although the integer-valued filters are not likely to be useful for sizes larger than 15*15.

    #!/usr/bin/ruby
    
    # Sobel image gradient filter generator
    # by  -- Sept 2017
    # reference:
    # https://stackoverflow.com/questions/9567882/sobel-filter-kernel-of-large-size
    
    
    if (s = ARGV[0].to_i) < 3 || (s % 2) == 0
        $stderr.puts "invalid size"
        exit false
    end
    
    s /= 2
    
    
    n = 1
    
    # find least-common-multiple of all fractional denominators
    (0..s).each { |j|
        (1..s).each { |i|
            d = i*i + j*j
            n = n.lcm(d / d.gcd(i))
        }
    }
    
    
    fw1 = format("%d/%d", s, 2*s*s).size + 2
    fw2 = format("%d", n).size + 2
    
    
    weight = 0
    s1 = ""
    s2 = ""
    
    (-s..s).each { |y|
        (-s..s).each { |x|
            i, j = x, y   # "i, j = y, x" for transpose
            d = i*i + j*j
            if (i != 0)
                if (n * i % d) != 0   # this should never happen
                    $stderr.puts "inexact division: #{n} * #{i} / ((#{i})^2 + (#{j})^2)"
                    exit false
                end
                w = n * i / d
                weight += i * w
            else
                w = 0
            end
            s1 += "%*s" % [fw1, d > 0 ? "%d/%d" % [i, d] : "0"]
            s2 += "%*d" % [fw2, w]
        }
        s1 += "\n" ; s2 += "\n"
    }
    
    
    f = n.gcd(weight)
    
    puts s1
    
    puts "\nweight = %d%s" % [weight/f, f < n ? "/%d" % (n/f) : ""]
    
    puts "\n* #{n} =\n\n"
    
    puts s2
    
    puts "\nweight = #{weight}"
    

提交回复
热议问题