pythonc++opencvtriangulationscipy-spatial

how to apply a three point triangle gradient in opencv?


Say we have a Delaunay-triangulation like this one:

enter image description here

produced from fillConvexPoly on getVoronoiFacetList

Inside there are triangles that can be obtained via getTriangleList. I want to draw Delaunay-triangulation like it is a smooth gradient image composed of triangles like this:

enter image description here

How to do such thing in opencv?


Solution

  • This is how to do it in Python/OpenCV, but it will be slower than the Python/Wand version that I previously presented, because it has to loop and solve a linear least squares equation at each pixel for the barycentric coordinates.

    import cv2
    import numpy as np
    
    # References: 
    # https://stackoverflow.com/questions/31442826/increasing-efficiency-of-barycentric-coordinate-calculation-in-python
    # https://math.stackexchange.com/questions/81178/help-with-cramers-rule-and-barycentric-coordinates
    
    # create black background image
    result = np.zeros((500,500,3), dtype=np.uint8)
    
    # Specify (x,y) triangle vertices
    a = (250,100)
    b = (100,400)
    c = (400,400)
    
    # Specify colors
    red = (0,0,255)
    green = (0,255,0)
    blue = (255,0,0)
    
    # Make array of vertices
    # ax bx cx
    # ay by cy
    #  1  1  1
    triArr = np.asarray([a[0],b[0],c[0], a[1],b[1],c[1], 1,1,1]).reshape((3, 3))
    
    # Get bounding box of the triangle
    xleft = min(a[0], b[0], c[0])
    xright = max(a[0], b[0], c[0])
    ytop = min(a[1], b[1], c[1])
    ybottom = max(a[1], b[1], c[1])
    
    # loop over each pixel, compute barycentric coordinates and interpolate vertex colors
    for y in range(ytop, ybottom):
    
        for x in range(xleft, xright):
    
            # Store the current point as a matrix
            p = np.array([[x], [y], [1]])
    
            # Solve for least squares solution to get barycentric coordinates
            (alpha, beta, gamma) = np.linalg.lstsq(triArr, p, rcond=-1)[0]
    
            # The point is inside the triangle if all the following conditions are met; otherwise outside the triangle
            if alpha > 0 and beta > 0 and gamma > 0:
                # do barycentric interpolation on colors
                color = (red*alpha + green*beta + blue*gamma)
                result[y,x] = color
    
    # show results
    cv2.imshow('result', result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    # save results
    cv2.imwrite('barycentric_triange.png', result)
    


    Result:

    enter image description here