Skip to content
章节导航

变化检测 PCA OTSU寻找阈值

🕒 Published at: a few seconds ago

变化检测 PCA OTSU寻找阈值

py
import cv2
import matplotlib.pyplot as plt
import numpy as np
import math

img1 = cv2.imread(
    'C:\\Users\dell\Desktop\RXX-2020-CVA\RXX-2020-CVA\Testing dataset\TianJing-SPOT/09BMP.bmp')
img2 = cv2.imread(
    'C:\\Users\dell\Desktop\RXX-2020-CVA\RXX-2020-CVA\Testing dataset\TianJing-SPOT/10BMP.bmp')


def Find_Threshold(delta):  # OTSU寻找阈值
    # 求灰度方差最大的那个数
    val = np.zeros([256])
    for th in range(256):
        loc1 = delta > th
        loc2 = delta <= th
        '''delta[loc1]=255
        delta[loc2]=0'''
        if delta[loc1].size == 0:
            mu1 = 0
            omega1 = 0
        else:
            mu1 = np.mean(delta[loc1])
            omega1 = delta[loc1].size/delta.size

        if delta[loc2].size == 0:
            mu2 = 0
            omega2 = 0
        else:
            mu2 = np.mean(delta[loc2])
            omega2 = delta[loc2].size/delta.size
        val[th] = omega1*omega2*np.power((mu1-mu2), 2)

    # print("val=",val.shape)
    plt.figure()
    loc = np.where(val == np.max(val))
    # x=np.arange(0,256,1)
    # x=x.reshape([1,256])
    plt.plot(val)
    plt.ylabel("Var")
    plt.xlabel("Threshold")
    plt.grid("on")

    print("\nThe best OTSU Threshold: ", loc[0])
    return loc[0]


def CD_diff(img1, img2):  # 影像差值法

    delta = np.subtract(img2, img1)
    # delta=np.abs(delta)
    # delta.min()
    sh = delta.shape
    delta += np.abs(delta.min())
    th = Find_Threshold(delta)
    delta = cv2.cvtColor(delta, cv2.COLOR_BGR2GRAY)
    # print(delta.min())
    if np.size(th) > 1:
        th = th[0]
    for i1 in range(sh[0]):
        for i2 in range(sh[1]):
            if delta[i1][i2] >= th:
                delta[i1][i2] = 0
            else:
                delta[i1][i2] = 255
    return delta


def divede(img1, img2):
    delta = cv2.divide(img2, img1)
    # delta=np.abs(delta)
    # delta.min()
    (mean1, stddv1) = cv2.meanStdDev(delta)
    gray2 = cv2.cvtColor(delta, cv2.COLOR_BGR2GRAY)

    ret2, thread2 = cv2.threshold(gray2, mean1[0]+1, 255, cv2.THRESH_BINARY)
    return thread2


def cva(img1, img2):
    b, g, r = cv2.split(img1)
    b1, g1, r1 = cv2.split(img2)
    sh = img1.shape

    (row, col) = b1.shape
    d_1 = np.subtract(b, b1)
    d_1 += np.abs(d_1.min())
    d_2 = np.subtract(g, g1)
    d_2 += np.abs(d_2.min())
    d_3 = np.subtract(r, r1)
    d_3 += np.abs(d_3.min())

    d_1 = cv2.pow(d_1, 2)
    d_2 = cv2.pow(d_2, 2)
    d_3 = cv2.pow(d_3, 2)
    delta = cv2.add(d_1, d_2, d_3)
    for i in range(sh[0]):
        for j in range(sh[1]):
            delta[i, j] = math.sqrt(delta[i, j])+10
    th = Find_Threshold(delta)
    delta = cv2.cvtColor(delta, cv2.COLOR_BGR2GRAY)
    # print(delta.min())
    if np.size(th) > 1:
        th = th[0]
    for i1 in range(sh[0]):
        for i2 in range(sh[1]):
            if delta[i1][i2] >= th:
                delta[i1][i2] = 0
            else:
                delta[i1][i2] = 255
    return delta


# rcva 方法
def rcva(img1, img2):
    # 代码实现2w+1 w采用的是1


def rcva(img1, img2):
    b, g, red = cv2.split(img1)
    b1, g1, red1 = cv2.split(img2)

    (row, cloumn) = b.shape
    # 上下左右 左上 右上 左下 右下的坐标变化
    x = [-1, 1, 0, 0, -1, -1, 1, 1]
    y = [0, 0, -1, 1, -1, 1, -1, 1]

    # 保存变化后的差异图
    img_a = np.zeros((row, cloumn))
    img_b = np.zeros((row, cloumn))
    print("正在计算")
    for i in range(row):
        for j in range(cloumn):
            if i != 0 and j != 0 and i != row and j != cloumn:
                r = i
                c = j
                res1 = 1000000.0
                res2 = 1000000.0
                res3 = 1000000.0
                for k in range(8):
                    if(0 < r and r < row and c > 0 and c < cloumn):
                        kk1 = (math.pow(abs(int(b[i, j])-int(b1[r, c])), 2))
                        if(kk1 < res1):
                            res1 = kk1
                        kk2 = (math.pow(abs(int(g[i, j])-int(g1[r, c])), 2))
                        if(kk2 < res2):
                            res2 = kk2
                        kk3 = (
                            math.pow(abs(int(red[i, j])-int(red1[r, c])), 2))
                        if(kk3 < res3):
                            res3 = kk3
                    r = i
                    c = j
                    r += x[k]
                    c += y[k]
                img_a[i][j] = math.sqrt(res1+res2+res3)

        # 考虑四个边角 和四个边界
            else:
                img_a[i, j] = abs(int(b[i, j])-int(b1[i, j]))

    print("正在计算中请稍等")

    for i in range(row):
        for j in range(cloumn):
            if i != 0 and j != 0 and i != row and j != cloumn:
                r = i
                c = j
                res1 = 1000000.0
                res2 = 1000000.0
                res3 = 1000000.0
                for k in range(8):
                    if(0 < r and r < row and c > 0 and c < cloumn):
                        kk1 = (math.pow(abs(int(b[i, j])-int(b1[r, c])), 2))
                        if(kk1 < res1):
                            res1 = kk1
                        kk2 = (math.pow(abs(int(g[i, j])-int(g1[r, c])), 2))
                        if(kk2 < res2):
                            res2 = kk2
                        kk3 = (
                            math.pow(abs(int(red[i, j])-int(red1[r, c])), 2))
                        if(kk3 < res3):
                            res3 = kk3
                    r = i
                    c = j
                    r += x[k]
                    c += y[k]
                img_b[i][j] = math.sqrt(res1+res2+res3)
        # 考虑四个边角 和四个边界
            else:
                img_b[i, j] = abs(int(b1[i, j])-int(b[i, j]))

    img_b_change = np.zeros((row, cloumn))
    for i in range(row):
        for j in range(cloumn):
            if img_a[i, j] > img_b[i, j]:
                img_b_change[i, j] = img_b[i, j]
            else:
                img_b_change[i, j] = img_a[i, j]

    print("计算完成正在二值化")
    th = Find_Threshold(img_b_change)

    for i1 in range(row):
        for i2 in range(cloumn):
            if img_b_change[i1][i2] <= th:
                img_b_change[i1][i2] = 0
            else:
                img_b_change[i1][i2] = 255
    cv2.imshow('diff3', img_b_change)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 主成向量分析法

# 这个是二维


def Img_PCA(delta):
    U, S, V = np.linalg.svd(delta)
    SS = np.zeros(U.shape)
    print(SS.shape)

    for i in range(S.shape[0]):
        SS[i][i] = S[i]

    def Pick_k(S):
        sval = np.sum(S)
        for i in range(S.shape[0]):
            if np.sum(S[:i]) >= 0.6*sval:
                break
        return i+1

    k = Pick_k(S)
    print("\nNumber of vectors to reserve: k= ", k)
    Uk = U[:, 0:k]
    Sk = SS[0:k, 0:k]
    Vk = V[0:k, :]
    im = np.dot(np.dot(Uk, Sk), Vk)
   # im=np.dot(im,delta)
    return im


# 差值pca 法
# 先做插值再做PCA
i = Img_PCA(CD_diff(img1, img2))

# PCA 插值法

# ii=CD_diff(Img_PCA(img1[0]),Img_PCA(img2[0]))

cv2.imshow('diff', i)
cv2.waitKey(0)
cv2.destroyAllWindows()