Search code examples
pythonopencvimage-processingscikit-image

Divide an image into radial sections and select values in an individual section


This is what I would like to do in python: First, give a particular point on the image(shown in red), I would like to section it radially into any given number of equally spaced sections. Then I would like to select pixel intensities in each section one at a time(shown in blue). Any help would be really appreciated.

enter image description here


Solution

  • Rather than draw your background white and fill in the sector in red or blue, draw instead your background in black and fill your sector with white. Then you can use a multiplication, or bitwise-AND to select the pixels in your real image based on the sector mask.

    Now you just need to draw one sector at a time, filled with white. You know the centre, so you just need 2 more points to construct the triangle. As the longest line possible in any image is the diagonal, calculate the length of that. Now, using that as the length of each radial line emanating from the centre, you can use simple trigonometry to calculate the two lines, since you know the angle between them is 360/N where N is the number of sectors. Don't worry that you calculate two vertices outside your image's edges, all libraries will allow you to do that.

    Here is some code - not too thoroughly tested - but you get the idea:

    #!/usr/bin/env python3
    
    import cv2
    import math
    import numpy as np
    
    h, w   = 600, 1200   # image height and width
    cx, cy = 200, 300    # (x,y) coordinates of circle centre
    N      = 16          # number of slices in our pie
    l      = h + w       # length of radial lines - larger than necessary
    
    # Create each sector in white on black background
    for sector in range(N):
        startAngle = sector * 360/N
        endAngle   = startAngle + 360/N
        x1 = cx + l * math.sin(math.radians(startAngle))
        y1 = cy - l * math.cos(math.radians(startAngle))
        x2 = cx + l * math.sin(math.radians(endAngle))
        y2 = cy - l * math.cos(math.radians(endAngle))
        vertices = [(cy, cx), (y1, x1), (y2, x2)]
        print(f'DEBUG: sector={sector}, startAngle={startAngle}, endAngle={endAngle}')
        # Make empty black canvas
        im = np.zeros((h,w), np.uint8)
        # Draw this pie slice in white
        cv2.fillPoly(im, np.array([vertices],'int32'), 255)
        cv2.imwrite(f'DEBUG-{sector:03d}.png', im)
        cv2.imshow('title',im)
        cv2.waitKey(0)
    

    enter image description here

    If you start with this image:

    enter image description here

    and change the code to this:

    #!/usr/bin/env python3
    
    import cv2
    import math
    import numpy as np
    
    orig = cv2.imread('artistic-swirl.jpg', cv2.IMREAD_ANYCOLOR)
    print(orig.shape)
    
    h, w   = 600, 1200   # image height and width
    cx, cy = 200, 300    # (x,y) coordinates of circle centre
    N      = 16          # number of slices in our pie
    l      = h + w       # length of radial lines - larger than necessary
    
    # Create each sector in white on black background
    for sector in range(N):
        startAngle = sector * 360/N
        endAngle   = startAngle + 360/N
        x1 = cx + l * math.sin(math.radians(startAngle))
        y1 = cy - l * math.cos(math.radians(startAngle))
        x2 = cx + l * math.sin(math.radians(endAngle))
        y2 = cy - l * math.cos(math.radians(endAngle))
        vertices = [(cy, cx), (y1, x1), (y2, x2)]
        print(f'DEBUG: sector={sector}, startAngle={startAngle}, endAngle={endAngle}')
        # Make empty black canvas
        im = np.zeros((h,w), np.uint8)
        # Draw this pie slice in white
        cv2.fillPoly(im, np.array([vertices],'int32'), 255)
        cv2.imwrite(f'DEBUG-{sector:03d}.png', im)
        #cv2.imshow('title',im)
        #cv2.waitKey(0)
        mask = np.dstack((im,im,im))
        res = cv2.bitwise_and(mask,orig)
        cv2.imshow('image',res)
        cv2.waitKey(0)
    

    enter image description here