Zhang-Suen 圖像細化算法python實現


算法流程

首先要反轉原圖像,因為算法之后所有的操作都將0作為前景,將1作為背景。
中心像素x_1(x,y)的8-近鄰定義如下所示:
中心像素x_1(x,y)的8-近鄰

考慮以下兩個步驟

  • 步驟1:執行光柵掃描並標記滿足以下5個條件的所有像素:
    • 這是一個黑色像素;
    • 順時針查看x2、x3、...、x9、x2時,從0到1的變化次數僅為1;
    • x2、x3、...、x9中1的個數在2個以上6個以下;
    • x2、x4、x6中至少有1個為1;
    • x4、x6、x8中至少有1個為1;
      將滿足條件的所有像素標為1
  • 步驟2:執行光柵掃描並標記滿足以下5個條件的所有像素:
    • 這是一個黑色像素;
    • 順時針查看x2、x3、...、x9、x2時,從0到1的變化次數僅為1;
    • x2、x3、...、x9中1的個數在2個以上6個以下;
    • x2、x4、x8中至少有1個為1;
    • x2、x6、x8中至少有1個為1;
      將滿足條件的所有像素標為1
  • 反復執行步驟1和步驟2,直到沒有點發生變化。
    python實現:
import cv2
import numpy as np
import matplotlib.pyplot as plt

# Zhang Suen thining algorythm
def Zhang_Suen_thining(img):
    # get shape
    H, W, C = img.shape

    # prepare out image
    out = np.zeros((H, W), dtype=np.int)
    out[img[..., 0] > 0] = 1

    # inverse
    out = 1 - out

    while True:
        s1 = []
        s2 = []

        # step 1 ( rasta scan )
        for y in range(1, H-1):
            for x in range(1, W-1):
                
                # condition 1
                if out[y, x] > 0:
                    continue

                # condition 2
                f1 = 0
                if (out[y-1, x+1] - out[y-1, x]) == 1:
                    f1 += 1
                if (out[y, x+1] - out[y-1, x+1]) == 1:
                    f1 += 1
                if (out[y+1, x+1] - out[y, x+1]) == 1:
                    f1 += 1
                if (out[y+1, x] - out[y+1,x+1]) == 1:
                    f1 += 1
                if (out[y+1, x-1] - out[y+1, x]) == 1:
                    f1 += 1
                if (out[y, x-1] - out[y+1, x-1]) == 1:
                    f1 += 1
                if (out[y-1, x-1] - out[y, x-1]) == 1:
                    f1 += 1
                if (out[y-1, x] - out[y-1, x-1]) == 1:
                    f1 += 1

                if f1 != 1:
                    continue
                    
                # condition 3
                f2 = np.sum(out[y-1:y+2, x-1:x+2])
                if f2 < 2 or f2 > 6:
                    continue
                
                # condition 4
                # x2 x4 x6
                if (out[y-1, x] + out[y, x+1] + out[y+1, x]) < 1 :
                    continue

                # condition 5
                # x4 x6 x8
                if (out[y, x+1] + out[y+1, x] + out[y, x-1]) < 1 :
                    continue
                    
                s1.append([y, x])

        for v in s1:
            out[v[0], v[1]] = 1

        # step 2 ( rasta scan )
        for y in range(1, H-1):
            for x in range(1, W-1):
                
                # condition 1
                if out[y, x] > 0:
                    continue

                # condition 2
                f1 = 0
                if (out[y-1, x+1] - out[y-1, x]) == 1:
                    f1 += 1
                if (out[y, x+1] - out[y-1, x+1]) == 1:
                    f1 += 1
                if (out[y+1, x+1] - out[y, x+1]) == 1:
                    f1 += 1
                if (out[y+1, x] - out[y+1,x+1]) == 1:
                    f1 += 1
                if (out[y+1, x-1] - out[y+1, x]) == 1:
                    f1 += 1
                if (out[y, x-1] - out[y+1, x-1]) == 1:
                    f1 += 1
                if (out[y-1, x-1] - out[y, x-1]) == 1:
                    f1 += 1
                if (out[y-1, x] - out[y-1, x-1]) == 1:
                    f1 += 1

                if f1 != 1:
                    continue
                    
                # condition 3
                f2 = np.sum(out[y-1:y+2, x-1:x+2])
                if f2 < 2 or f2 > 6:
                    continue
                
                # condition 4
                # x2 x4 x8
                if (out[y-1, x] + out[y, x+1] + out[y, x-1]) < 1 :
                    continue

                # condition 5
                # x2 x6 x8
                if (out[y-1, x] + out[y+1, x] + out[y, x-1]) < 1 :
                    continue
                    
                s2.append([y, x])

        for v in s2:
            out[v[0], v[1]] = 1

        # if not any pixel is changed
        if len(s1) < 1 and len(s2) < 1:
            break

    out = 1 - out
    out = out.astype(np.uint8) * 255

    return out


# Read image
img = cv2.imread("../thin.png").astype(np.float32)

# Zhang Suen thining
out = Zhang_Suen_thining(img)


# Save result
cv2.imwrite("out.png", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

實驗結果:
原圖
Zhang-Suen細化算法結果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM