drawing a bounding box in large images

前端 未结 2 1294
予麋鹿
予麋鹿 2021-01-22 02:22

I have a large binary image (4k x 7k pix) from which I want to extract the entire yellow portion as a single rectangle. I tried binary erosion to even out features insi

2条回答
  •  误落风尘
    2021-01-22 03:02

    As the image you provided includes distracting axes, and is the wrong colour and too small, I created as realistic a version as I could with ImageMagick like this in Terminal:

    convert bbox.png -alpha off -crop 120x215+40+13 -colorspace gray -normalize -threshold 50% -scale 4200x7200\! bbox.png
    

    The full-size version is 4200x7200.

    I then wrote a numpy-based version of bbox as follows

    #!/usr/local/bin/python3
    import numpy as np
    from PIL import Image
    
    def bbox(image):
        """Find bounding box of image"""
        # Project all columns into row same width as image
        proj=np.any(image,axis=0)
        # Find first non-zero value from Left
        L=np.argmax(proj)
        # And right
        R=image.shape[1]-np.argmax(np.flipud(proj))-1
        # Project all rows into column same height as image
        proj=np.any(image,axis=1)
        # Find first non-zero value from Top
        T=np.argmax(proj)
        # And Bottom
        B=image.shape[0]-np.argmax(np.flipud(proj))-1
        return T,L,B,R
    
    image=np.array(Image.open("a.png").convert("L"))
    print(bbox(image))
    

    That runs in 5.3ms on my Mac. Just for fun, I threaded it and ran the horizontal projection and vertical projection on separate parallel threads and it came down to 3.6ms with the same results.

    #!/usr/local/bin/python3
    import numpy as np
    from PIL import Image
    
    import threading
    import queue
    
    def DoOneDim(image,axis,q):
        """Find bounding box of image"""
        proj=np.any(image,axis=axis)
        # Find first non-zero value
        A=np.argmax(proj)
        # And and last
        B=image.shape[1-axis]-np.argmax(np.flipud(proj))-1
        q.put({axis:(A,B)})
    
    
    def bboxTh(image):
        """Threaded version of bbox() that does vertical and horizontal on their own theads"""
        q = queue.Queue()
        Hthread=threading.Thread(target=DoOneDim, args=(image,0,q))
        Vthread=threading.Thread(target=DoOneDim, args=(image,1,q))
        Hthread.start()
        Vthread.start()
        Hthread.join()
        Vthread.join()
        results=dict()
        while not q.empty():
           results.update(q.get())
        return results
    
    image=np.array(Image.open("a.png").convert("L"))
    print(bboxTh(image))
    

    The identified box looks likes this:

提交回复
热议问题