1. 程式人生 > >cv2 實現Delaunay三角剖分和Voronoi圖(Delaunay Triangulation and Voronoi Diagram)

cv2 實現Delaunay三角剖分和Voronoi圖(Delaunay Triangulation and Voronoi Diagram)

本文主要介紹使用cv2模組實現Delaunay三角剖分和Voronoi圖。

測試圖片:

示例程式碼:

# 匯入模組
import cv2
import numpy as np
import random

# 檢查點是否在長方形區域內
def rect_contains(rect, point):
    if point[0] < rect[0]:
        return False
    elif point[1] < rect[1]:
        return False
    elif point[0] > rect[2]:
        return False
    elif point[1] > rect[3]:
        return False
    return True

# 繪製點
def draw_point(img, p, color):
    cv2.circle(img, p, 2, color, 0)

# 繪製delaunay triangles
def draw_delaunay(img, subdiv, delaunary_color):
    triangleList = subdiv.getTriangleList()
    size = img.shape
    r = (0, 0, size[1], size[0])
    
    for t in triangleList:
        pt1 = (t[0], t[1])
        pt2 = (t[2], t[3])
        pt3 = (t[4], t[5])
    
        if rect_contains(r, pt1) and rect_contains(r, pt2) and rect_contains(r, pt3):
            cv2.line(img, pt1, pt2, delaunary_color, 1)
            cv2.line(img, pt2, pt3, delaunary_color, 1)
            cv2.line(img, pt3, pt1, delaunary_color, 1)

# 繪製 voroni diagram
def draw_voroni(img, subdiv):
    (facets, centers) = subdiv.getVoronoiFacetList([])
    
    for i in range(0, len(facets)):
        ifacet_arr = []
        for f in facets[i]:
            ifacet_arr.append(f)
        
        ifacet = np.array(ifacet_arr, np.int)
        color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
        
        cv2.fillConvexPoly(img, ifacet, color, 0)
        ifacets = np.array([ifacet])
        cv2.polylines(img, ifacets, True, (0, 0, 0), 1)
        cv2.circle(img, (centers[i][0], centers[i][1]), 3, (0, 0, 0), 0)

# 定義視窗名稱
win_delaunay = "Delaunay Triangulation"
win_voronoi = "Voronoi Diagram"

# 繪製三角形時開啟動畫
animats = True

# 定義繪製的顏色
delaunay_color = (255, 255, 255)
points_color = (0, 0, 255)

# 讀取圖片
img = cv2.imread('./obama.jpg')

# 複製圖片
img_orig = img.copy()

# 與Subdiv2D一起使用的矩形
size = img.shape
rect = (0, 0, size[1], size[0])

# 建立Subdic2D的一個例項
subdiv = cv2.Subdiv2D(rect)

# 建立一個數組用於儲存點
points = []


# 從文字檔案讀取點
with open('./obama.txt') as file:
    for line in file:
        x, y = line.split()
        points.append((int(x), int(y)))
    
    # 將點插入到subdiv
    for p in points:
        subdiv.insert(p)
        
        # 顯示animation 
        if animats:
            img_copy = img_orig.copy()
            # 繪製delaunay triangle
            draw_delaunay(img_copy, subdiv, (255, 255, 255))
            
            # 顯示結果
            # cv2.imshow(win_delaunay, img_copy)
            # cv2.waitKey(100)


# 繪製delaunay triangles
draw_delaunay( img, subdiv, (255, 255, 255) );

# 繪製點
for p in points :
    draw_point(img, p, (0,0,255))

# 為voronoi Diagram分配空間
img_voronoi = np.zeros(img.shape, dtype = img.dtype)

# 繪製voronoi diagram
draw_voroni(img_voronoi,subdiv)

# 儲存結果
#儲存結果
cv2.imwrite(win_delaunay + '.jpg', img)
cv2.imwrite(win_voronoi + '.jpg', img_voronoi)
# 顯示結果
# cv2.imshow(win_delaunay,img)
# cv2.imshow(win_voronoi,img_voronoi)
# cv2.waitKey(0)    

結果:

Delaunay Triangulation:

 

Voronoi Diagram