猿问

如何在opencv中应用三点三角形渐变?

假设我们有像这样的 Delaunay 三角剖分:

产生fillConvexPolygetVoronoiFacetList

里面有三角形,可以通过 得到getTriangleList。我想绘制 Delaunay-triangulation,就像它是一个由三角形组成的平滑渐变图像,如下所示:

http://img2.mukewang.com/637f17630001a16603130187.jpg

如何在 opencv 中做这样的事情?



哈士奇WWW
浏览 144回答 3
3回答

饮歌长啸

我修改了@ fmw42的答案以利用向量计算(由 支持)并删除循环以获得更好的性能。np.linalg.lstsqfor    #!/usr/bon/env python    import cv2    import numpy as np        # 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 = np.array([0,0,255])    green = np.array([0,255,0])    blue = np.array([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])        # Build np arrays of coordinates of the bounding box    xs = range(xleft, xright)    ys = range(ytop, ybottom)    xv, yv = np.meshgrid(xs, ys)    xv = xv.flatten()    yv = yv.flatten()        # Compute all least-squares /    p = np.array([xv, yv, [1] * len(xv)])    alphas, betas, gammas = np.linalg.lstsq(triArr, p, rcond=-1)[0]        # Apply mask for pixels within the triangle only    mask = (alphas > 0) & (betas > 0) & (gammas > 0)    alphas_m = alphas[mask]    betas_m = betas[mask]    gammas_m = gammas[mask]    xv_m = xv[mask]    yv_m = yv[mask]        def mul(a, b) :        # Multiply two vectors into a matrix        return np.asmatrix(b).T @ np.asmatrix(a)        # Compute and assign colors    colors = mul(red, alphas_m) + mul(green, betas_m) + mul(blue, gammas_m)    result[xv_m, yv_m] = colors        # show results    cv2.imshow('result', result)    cv2.waitKey(0)    cv2.destroyAllWindows()

慕田峪4524236

这是在 Python/OpenCV 中执行此操作的方法,但它会比我之前介绍的 Python/Wand 版本慢,因为它必须循环并在重心坐标的每个像素处求解线性最小二乘方程。import cv2import 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 imageresult = np.zeros((500,500,3), dtype=np.uint8)# Specify (x,y) triangle verticesa = (250,100)b = (100,400)c = (400,400)# Specify colorsred = (0,0,255)green = (0,255,0)blue = (255,0,0)# Make array of vertices# ax bx cx# ay by cy#  1  1  1triArr = 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 trianglexleft = 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 colorsfor 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 resultscv2.imshow('result', result)cv2.waitKey(0)cv2.destroyAllWindows()# save resultscv2.imwrite('barycentric_triange.png', result)结果:

白板的微信

在 OpenCV 中,我认为没有任何现成的函数可以做到这一点。您将不得不遍历图像中的每个像素并计算重心(区域)插值。参见例如https://codeplea.com/triangular-interpolation但是,在 Python/Wand(基于 ImageMagick)中,您可以按如下方式进行:import numpy as npfrom wand.image import Imagefrom wand.color import Colorfrom wand.drawing import Drawingfrom wand.display import display# define vertices of trianglep1 = (250, 100)p2 = (100, 400)p3 = (400, 400)# define barycentric colors and verticescolors = {    Color('RED'): p1,    Color('GREEN1'): p2,    Color('BLUE'): p3}# create black imageblack = np.zeros([500, 500, 3], dtype=np.uint8)with Image.from_array(black) as img:    with img.clone() as mask:        with Drawing() as draw:            points = [p1, p2, p3]            draw.fill_color = Color('white')            draw.polygon(points)            draw.draw(mask)            img.sparse_color('barycentric', colors)            img.composite_channel('all_channels', mask, 'multiply', 0, 0)               img.format = 'png'            img.save(filename='barycentric_image.png')            display(img)结果:
随时随地看视频慕课网APP

相关分类

Python
我要回答