-
饮歌长啸
我修改了@ 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)结果: