Find the corners of a polygon represented by a region mask

前端 未结 5 1617
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-09 13:01

BW = poly2mask(x, y, m, n) computes a binary region of interest (ROI) mask, BW, from an ROI polygon, represented by the vectors x and y. Th

5条回答
  •  既然无缘
    2020-12-09 13:45

    Here's an example using Ruby and HornetsEye. Basically the program creates a histogram of the quantised Sobel gradient orientation to find dominant orientations. If four dominant orientations are found, lines are fitted and the intersections between neighbouring lines are assumed to be the corners of the projected rectangle.

    #!/usr/bin/env ruby
    require 'hornetseye'
    include Hornetseye
    Q = 36
    img = MultiArray.load_ubyte 'http://imgur.com/oxyjj.png'
    dx, dy = 8, 6
    box = [ dx ... 688, dy ... 473 ]
    crop = img[ *box ]
    crop.show
    s0, s1 = crop.sobel( 0 ), crop.sobel( 1 )
    mag = Math.sqrt s0 ** 2 + s1 ** 2
    mag.normalise.show
    arg = Math.atan2 s1, s0
    msk = mag >= 500
    arg_q = ( ( arg.mask( msk ) / Math::PI + 1 ) * Q / 2 ).to_int % Q
    hist = arg_q.hist_weighted Q, mag.mask( msk )
    segments = ( hist >= hist.max / 4 ).components
    lines = arg_q.map segments
    lines.unmask( msk ).normalise.show
    if segments.max == 4
      pos = MultiArray.scomplex *crop.shape
      pos.real = MultiArray.int( *crop.shape ).indgen! % crop.shape[0]
      pos.imag = MultiArray.int( *crop.shape ).indgen! / crop.shape[0]
      weights = lines.hist( 5 ).major 1.0
      centre = lines.hist_weighted( 5, pos.mask( msk ) ) / weights
      vector = pos.mask( msk ) - lines.map( centre )
      orientation = lines.hist_weighted( 5, vector ** 2 ) ** 0.5
      corner = Sequence[ *( 0 ... 4 ).collect do |i|
        i1, i2 = i + 1, ( i + 1 ) % 4 + 1
        l1, a1, l2, a2 = centre[i1], orientation[i1], centre[i2], orientation[i2]
        ( l1 * a1.conj * a2 - l2 * a1 * a2.conj -
          l1.conj * a1 * a2 + l2.conj * a1 * a2 ) /
          ( a1.conj * a2 - a1 * a2.conj )
      end ] 
      result = MultiArray.ubytergb( *img.shape ).fill! 128
      result[ *box ] = crop
      corner.to_a.each do |c|
        result[ c.real.to_i + dx - 1 .. c.real.to_i + dx + 1,
                c.imag.to_i + dy - 1 .. c.imag.to_i + dy + 1 ] = RGB 255, 0, 0
      end
      result.show
    end
    

    Image with estimated position of corners

提交回复
热议问题