数字图像处理-形态学

问题描述

编一个程序实现如下功能:
1、读入一幅指纹图像(自己找);
2、对图像进行二值化(方法自定,可以是阈值法);
3、采用形态学骨架提取和距离变换骨架提取两种算法分别提取图像骨架;
4、采用裁剪算法,并分析其效果。

问题求解

指纹图像
在这里插入图片描述
问题二 用阈值法对图像进行二值化,阈值采用的是全局阈值算法得到,然后令前景像素为 1,背景像素为 0。阈值算法代码如下所示:

def threshold(img):
    med = np.mean(img)
    med1 = 0
    while np.mean(med1-med)>=0.0001:
        miu1 = np.mean(img<=med)
        miu2 = np.mean(img>med)
        med1 = med
        med = 0.5*(miu1+miu2)
    return med

运行结果如下图所示:
在这里插入图片描述
问题三
在这里插入图片描述
腐蚀运算的实现代码为:

 x = cv2.erode(src, kernel, iterations=1)

骨架提取的实现代码为,其中的开运算拆开成了腐蚀和膨胀:

def morphology(src):
    # 生成卷积核
    kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
    # 进行腐蚀处理
    x = cv2.erode(src, kernel, iterations=1)
    img = src - cv2.dilate(x, kernel, iterations=1)
    while np.any(src == 1):
        src = cv2.erode(src, kernel, iterations=1)
        x = cv2.erode(src, kernel, iterations=1)
        src1 = src - cv2.dilate(x, kernel, iterations=1)
        img = UU(src1, img)
    return img

运行结果如下所示:
在这里插入图片描述
(2) 距离变换骨架提取
基本思想是把离散分布在空间中的目标根据一定的距离定义方式生成距离图, 其中每一点的距离值是到所有空间目标距离中最小的一个。本文采用的是欧式距 离,采用的串行距离变换算法,算法示意图如下所示,a=1,b=2。
在这里插入图片描述
算法步骤:
step1:求取二值图像的边界

img_o = img.copy()
# 边界图
img[img == 0.0] = 0.5
img[img == 1.0] = 0.0
img[img == 0.5] = 1.0

step2: 对边界二值图像求取距离变换

def distance(img):
    # 初始化 将1变为0 将0变为一个特别大的值(就可以赋值最小距离)
    img[img == 0.0] = 100
    img[img == 1.0] = 0.0
    # 图像左变换
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            # 上
            if InArea(i - 1, j, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i,j], 1 + img[i - 1,j]);
            # 左上
            if InArea(i - 1, j - 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 2 + img[i - 1, j - 1]);
            # 左
            if InArea(i, j - 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 1 + img[i, j - 1]);
            # 左下
            if InArea(i + 1, j - 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 2 + img[i + 1, j - 1]);
    # 图像右变换
    for i in range(img.shape[0]-1, -1, -1):
        for j in range(img.shape[1]-1, -1, -1):
            # 下
            if InArea(i + 1, j, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 1 + img[i + 1, j]);
            # 右下
            if InArea(i + 1, j + 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 2 + img[i + 1, j + 1]);
            # 右
            if InArea(i, j + 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 1 + img[i, j + 1]);
            # 右上
            if InArea(i - 1, j + 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 2 + img[i - 1, j + 1]);
    return img

step3:求距离变换图中的局部极大值
step4:落入原二值图像中的局部极大值就是图像的骨架

运行结果如下图所示
在这里插入图片描述
在这里插入图片描述
细化实现

def thin(A, B1, B2):
    return A - hit_miss(A,B1,B2)

击中击不中实现

def hit_miss(A, B1, B2):
    A1 = cv2.erode(A,B1,iterations=1)
    A2 = cv2.erode(1-A,B2,iterations=1)
    return NN(A1,A2)

裁剪算法实现

def Tailoring(img):
    A = img.copy()
    B11 = np.array([[0,0,0],[1,1,0],[0,0,0]], dtype='uint8')
    B12 = np.array([[0,1,1],[0,0,1],[0,1,1]], dtype='uint8')
    B21 = np.array([[1,0,0],[0,1,0],[0,0,0]], dtype='uint8')
    B22 = 1-B21
    for j in range(3):
        for i in range(4):
            img = thin(img, B11, B12)
            B11 = np.rot90(B11)
            B12 = np.rot90(B12)
        for i in range(4):
            img = thin(img, B21, B22)
            B21 = np.rot90(B21)
            B22 = np.rot90(B22)
    X1 = img
    X2 = hit_miss(X1, B11, B12)
    for i in range(3):
        B11 = np.rot90(B11)
        B12 = np.rot90(B12)
        X2 = UU(hit_miss(X1,B11, B12),X2)
    for i in range(4):
        X2 = UU(hit_miss(X1, B21, B22), X2)
        B21 = np.rot90(B21)
        B22 = np.rot90(B22)
    H = np.array([[1,1,1],[1,1,1],[1,1,1]], dtype='uint8')
    for i in range(3):
        X3 = NN(cv2.dilate(X2,H,iterations=1),A)
    X4 = UU(X1,X3)
    return X4

在这里插入图片描述
在这里插入图片描述

全部代码


import numpy as np
from scipy.ndimage import maximum_filter
import cv2


def normalization(img):
    img = (img - np.min(img))/(np.max(img)-np.min(img))
    return img


def threshold(img):
    med = np.mean(img)
    med1 = 0
    while np.mean(med1-med)>=0.0001:
        miu1 = np.mean(img<=med)
        miu2 = np.mean(img>med)
        med1 = med
        med = 0.5*(miu1+miu2)
    return med


def InArea(i, j, row, col):
    if i < 0 or i >= row or j < 0 or j >= col:
        return False
    return True


def min(a,b):
    if a>=b:
        return b
    else:
        return a


def distance(img):
    # 初始化 将1变为0 将0变为一个特别大的值(就可以赋值最小距离)
    img[img == 0.0] = 100
    img[img == 1.0] = 0.0
    # 图像左变换
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            # 上
            if InArea(i - 1, j, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i,j], 1 + img[i - 1,j]);
            # 左上
            if InArea(i - 1, j - 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 2 + img[i - 1, j - 1]);
            # 左
            if InArea(i, j - 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 1 + img[i, j - 1]);
            # 左下
            if InArea(i + 1, j - 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 2 + img[i + 1, j - 1]);
    # 图像右变换
    for i in range(img.shape[0]-1, -1, -1):
        for j in range(img.shape[1]-1, -1, -1):
            # 下
            if InArea(i + 1, j, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 1 + img[i + 1, j]);
            # 右下
            if InArea(i + 1, j + 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 2 + img[i + 1, j + 1]);
            # 右
            if InArea(i, j + 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 1 + img[i, j + 1]);
            # 右上
            if InArea(i - 1, j + 1, img.shape[0], img.shape[1]):
                img[i, j] = min(img[i, j], 2 + img[i - 1, j + 1]);
    return img


def UU(a, b):
    arr = np.zeros(a.shape)
    for i in range(a.shape[0]):
        for j in range(a.shape[1]):
            arr[i,j] = a[i,j] or b[i,j]
    return arr


def NN(a, b):
    arr = np.zeros(a.shape)
    for i in range(a.shape[0]):
        for j in range(a.shape[1]):
            arr[i, j] = a[i, j] and b[i, j]
    return arr



def morphology(src):
    # 生成卷积核
    kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
    # 进行腐蚀处理
    x = cv2.erode(src, kernel, iterations=1)
    img = src - cv2.dilate(x, kernel, iterations=1)
    while np.any(src == 1):
        src = cv2.erode(src, kernel, iterations=1)
        x = cv2.erode(src, kernel, iterations=1)
        src1 = src - cv2.dilate(x, kernel, iterations=1)
        img = UU(src1, img)
    return img



def distance_sk(img):
    img_o = img.copy()
    # 边界图
    img[img == 0.0] = 0.5
    img[img == 1.0] = 0.0
    img[img == 0.5] = 1.0
    img = distance(img)
    imgx = maximum_filter(img, size=3)
    imgy = np.where(img == imgx, 1.0, 0.0)
    return NN(img_o,imgy)


def hit_miss(A, B1, B2):
    A1 = cv2.erode(A,B1,iterations=1)
    A2 = cv2.erode(1-A,B2,iterations=1)
    return NN(A1,A2)


def thin(A, B1, B2):
    return A - hit_miss(A,B1,B2)


def Tailoring(img):
    A = img.copy()
    B11 = np.array([[0,0,0],[1,1,0],[0,0,0]], dtype='uint8')
    B12 = np.array([[0,1,1],[0,0,1],[0,1,1]], dtype='uint8')
    B21 = np.array([[1,0,0],[0,1,0],[0,0,0]], dtype='uint8')
    B22 = 1-B21
    for j in range(3):
        for i in range(4):
            img = thin(img, B11, B12)
            B11 = np.rot90(B11)
            B12 = np.rot90(B12)
        for i in range(4):
            img = thin(img, B21, B22)
            B21 = np.rot90(B21)
            B22 = np.rot90(B22)
    X1 = img
    X2 = hit_miss(X1, B11, B12)
    for i in range(3):
        B11 = np.rot90(B11)
        B12 = np.rot90(B12)
        X2 = UU(hit_miss(X1,B11, B12),X2)
    for i in range(4):
        X2 = UU(hit_miss(X1, B21, B22), X2)
        B21 = np.rot90(B21)
        B22 = np.rot90(B22)
    H = np.array([[1,1,1],[1,1,1],[1,1,1]], dtype='uint8')
    for i in range(3):
        X3 = NN(cv2.dilate(X2,H,iterations=1),A)
    X4 = UU(X1,X3)
    return X4


if __name__ == '__main__':
    img = cv2.imread('zw.jpg',cv2.IMREAD_GRAYSCALE)

    img = normalization(img)
    img_o = img.copy()
    cv2.imshow('original', img_o)
    med = threshold(img)
    img[img >= med] = 0.0
    img[img != 0.0] = 1.0
    cv2.imshow('binary', img)
    img1 = morphology(img)
    img2 = distance_sk(img)
    img3 = Tailoring(img1)
    img4 = Tailoring(img2)
    cv2.imshow('morphology', img1)
    cv2.imshow('distance', img2)
    cv2.imshow('tailoring_m', img3)
    cv2.imshow('tailoring_d', img4)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值