• delaunay和voronoi图 人脸三角剖分


    先获取人脸68个特征点坐标,其中使用了官方的预训练模型shape_predictor_68_face_landmarks.dat:

    1. import dlib
    2. import cv2
    3. predictor_path = "shape_predictor_68_face_landmarks.dat"
    4. png_path = "face.jpg"
    5. txt_path = "points.txt"
    6. f = open(txt_path, 'w+')
    7. # 与人脸检测相同,使用dlib自带的frontal_face_detector作为人脸检测器
    8. detector = dlib.get_frontal_face_detector()
    9. # 相撞
    10. # 使用官方提供的模型构建特征提取器
    11. predicator = dlib.shape_predictor(predictor_path)
    12. win = dlib.image_window()
    13. img1 = cv2.imread(png_path)
    14. dets = detector(img1, 1)
    15. print("Number of faces detected : {}".format(len(dets)))
    16. for k, d in enumerate(dets):
    17. print("Detection {} left:{} Top: {} Right {} Bottom {}".format(
    18. k, d.left(), d.top(), d.right(), d.bottom()
    19. ))
    20. lanmarks = [[p.x, p.y] for p in predicator(img1, d).parts()]
    21. for idx, point in enumerate(lanmarks):
    22. f.write(str(point[0]))
    23. f.write("\t")
    24. f.write(str(point[1]))
    25. f.write('\n')

    实现人脸三角剖分:

    1. # 日期: 2023/11/2 23:04
    2. import cv2
    3. import numpy as np
    4. import random
    5. # 检查点是否在矩形框内
    6. def rect_contains(rect, point):
    7. if point[0] < rect[0]:
    8. return False
    9. elif point[1] < rect[1]:
    10. return False
    11. elif point[0] > rect[2]:
    12. return False
    13. elif point[1] > rect[3]:
    14. return False
    15. return True
    16. # 画点
    17. def draw_point(img, p, color):
    18. cv2.circle(img, p, 2, color)
    19. # 绘制德劳内三角形
    20. def draw_delaunay(img, subdiv, delaunay_color):
    21. trangleList = subdiv.getTriangleList() # 获取Delaunay三角形的列表
    22. size = img.shape
    23. r = (0, 0, size[1], size[0])
    24. for t in trangleList:
    25. pt1 = (int(t[0]), int(t[1]))
    26. pt2 = (int(t[2]), int(t[3]))
    27. pt3 = (int(t[4]), int(t[5]))
    28. if rect_contains(r, pt1) and rect_contains(r, pt2) and rect_contains(r, pt3):
    29. cv2.line(img, pt1, pt2, delaunay_color, 1) # 源图像,线段的两个端点,颜色,线宽
    30. cv2.line(img, pt2, pt3, delaunay_color, 1)
    31. cv2.line(img, pt3, pt1, delaunay_color, 1)
    32. # Draw voronoi diagram
    33. def draw_voronoi(img: object, subdiv: object) -> object:
    34. (facets, centers) = subdiv.getVoronoiFacetList([]) # 获取Voronoi构面的列表
    35. # 对于每个voronoi多边形
    36. for i in range(0, len(facets)):
    37. ifacet_arr = []
    38. # 得到每个多边形的顶点
    39. for f in facets[i]:
    40. ifacet_arr.append(f)
    41. ifacet = np.array(ifacet_arr, dtype=np.int32)
    42. # 随机颜色
    43. color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
    44. # 填充颜色
    45. cv2.fillConvexPoly(img, ifacet, color) # 图像、多边形顶点、颜色
    46. vertex = np.array([ifacet])
    47. cv2.polylines(img, vertex, True, (0, 0, 0), 1) # 绘制多边形,参数包括图像、多边形的点、线条是否闭合、颜色和线条宽度
    48. cv2.circle(img, (centers[i][0], centers[i][1]), 3, (0, 0, 0)) # 绘制圆,参数包括图像、中心点、半径、颜色
    49. if __name__ == '__main__':
    50. # 定义窗口名称
    51. win_delaunary = "Delaunay Triangulation"
    52. win_voronoi = "Voronoi Diagram"
    53. # 在画三角形的时候开启动画
    54. animate = True
    55. # 定义画的颜色
    56. delaunary_color = (255, 255, 255)
    57. points_color = (0, 0, 255)
    58. # 读入图片
    59. img_path = "face.jpg"
    60. img = cv2.imread(img_path)
    61. # 复制
    62. img_orig = img.copy()
    63. # 矩形框用于Subdiv2D
    64. size = img.shape # h, w, channel
    65. # x,y,w,h
    66. rect = (0, 0, size[1], size[0])
    67. # 创建一个Subdiv2D的实例
    68. subdiv = cv2.Subdiv2D(rect)
    69. # 创建点的列表
    70. points = []
    71. # 从文档中读取点的坐标
    72. with open("points.txt") as file:
    73. for line in file:
    74. x, y = line.split()
    75. points.append((int(x), int(y)))
    76. # 向subdiv中插入点
    77. for p in points:
    78. subdiv.insert(p)
    79. # 展示动画效果
    80. if animate:
    81. img_copy = img_orig.copy()
    82. # 绘制德劳内三角形
    83. draw_delaunay(img_copy, subdiv, (255, 255, 255))
    84. cv2.imshow(win_delaunary, img_copy)
    85. cv2.waitKey(100)
    86. # 绘制德劳内三角形
    87. draw_delaunay(img, subdiv, (255, 255, 255))
    88. # 绘制点
    89. for p in points:
    90. draw_point(img, p, (0, 0, 255))
    91. # 为沃罗诺伊图分配空间
    92. img_voronoi = np.zeros(img.shape, dtype=img.dtype)
    93. # 绘制沃罗诺伊图
    94. draw_voronoi(img_voronoi, subdiv)
    95. # 展示结果
    96. cv2.imshow(win_delaunary, img)
    97. cv2.imshow(win_voronoi, img_voronoi)
    98. cv2.waitKey(0)

  • 相关阅读:
    奇怪的bug
    绘制三角波与梯形波
    SpringMVC—笔记总结
    有哨兵位双向循环链表
    PDF格式转换为翻页电子书,这种形式太酷辣!
    linux小技巧-如何修改IP(四种方法)
    SQL之mysql到hive批量生成建表语句
    【暑期每日一题】洛谷 P7398 [COCI2020-2021#5] Šifra~
    《动手学深度学习 Pytorch版》 4.3 多层感知机的简洁实现
    新一代 L1 公链Aptos:安全、可扩展和可升级的Web3基础设施 |Tokenview
  • 原文地址:https://blog.csdn.net/ThreeS_tones/article/details/134224153