计算机视觉之目标跟踪(二) 稀疏表示及MP算法实现

稀疏表示及MP算法

天天在实验室划,回宿舍了就好好总结一下写篇博客吧
-----------------------------分割线--------------------------------
上一次介绍了用均值漂移(meanshift)算法来实现目标跟踪,有许多的局限性。同样是生成式的目标跟踪算法,稀疏表示(sparse coding)更加受到研究者的重视。
稀疏表示即将二维的图像用一个系数矩阵和稀疏字典来近似表示,打个比方:如果图象a是M×N的矩阵,我们只需一个M×K的系数矩阵b和一个K×N稀疏字典c,使得a近似于b×c。
那么参数不是更多使得信号更复杂了吗?
答案是NO,因为系数矩阵b的大部分参数都是为0的,而稀疏字典c是已知的,所以图像a就被压缩成了极少的数字。
这是借鉴了人类的大脑记忆方式(我猜的):我们在记住一个物体时,不可能记住该物体的全部图像信息,而只是记住了一个模糊的“印象”,使得我们下次见到它时能够识别出来。
回到我们的问题,我们需要找到一个稀疏字典,并让稀疏字典内尽可能少的向量来表示我们的原始图像。若我们一个一个去试的话,无疑会耗费大量的算力,所以这是一个np难的问题。所以我们只能找出一个尽可能优的解。
有如下方法解决:
1.贪婪算法
2.松弛算法
在这里只给出贪婪算法中的MP算法(因为暂时只学到这里hiahia)。
MP算法步骤:

  • step1 初始化系数矩阵为0,找到稀疏字典C(关于稀疏字典的学习以后再说,这里用随机正交矩阵代替)令要表示的图像的一个向量为误差f 。
  • step2 在稀疏字典中找出与f最为相近的向量m
  • step3 求出f在m向量上的投影与m的比值alpha,使得f=alpha*m+k,其中k为新的误差
  • step4 判断该误差是否小于误差阈值,若小于,则退出程序;否则,令f=k,回到step2

这样,经过多次迭代,最终得到初始向量:
f0=alpha1m1 + alpha2m2 + alpha3*m3 + c(c为可容忍的误差)
python实现如下:

import math
import numpy as np
import cv2

img = cv2.imread("./img/image.jpg")

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#生成稀疏基DCT矩阵
mat_dct_1d=np.zeros((60, 60))
v=range(60)
for k in range(0, 60):
    dct_1d=np.cos(np.dot(v,k*math.pi/60))
    if k>0:
        dct_1d=dct_1d-np.mean(dct_1d)
    mat_dct_1d[:,k]=dct_1d/np.linalg.norm(dct_1d)



#MP算法函数
def cs_omp(img_line, basemat):
    # 稀疏系数矩阵
    alpha = np.zeros((np.shape(basemat)[0]))
    # 残差初始值
    f = img_line
    # 阈值
    beta = beta  = np.linalg.norm(f)
    while(beta>50):
        # 定义最近值
        j_ = 0
        # 投影的模
        norm_fb = np.dot(basemat[0], f.T)/np.linalg.norm(basemat[0])
        # 勾股定理求出残差的模
        min_d = math.pow(np.linalg.norm(f)*np.linalg.norm(f) - norm_fb*norm_fb, 0.5)
        # 寻找离残差向量最近的向量
        for j in range(np.shape(basemat)[0]):
            # 投影的模
            norm_fb = np.dot(basemat[j], f.T)/np.linalg.norm(basemat[j])
            # 勾股定理求出残差的模
            norm_f = math.pow(np.linalg.norm(f)*np.linalg.norm(f) - norm_fb*norm_fb, 0.5)
            if(norm_f<min_d):
                min_d = norm_f
                j_ = j
        # 误差值
        beta  = np.linalg.norm(f)
        norm_fb = np.dot(basemat[j_], f.T)/np.linalg.norm(basemat[j_])
        # 稀疏系数等于投影模与最近向量的比
        alpha[j_] = norm_fb/np.linalg.norm(basemat[j_])
        # 更新残差
        f = f-alpha[j_]*basemat[j_]
    return alpha
zero_num = []
new_img = np.zeros((60, 60))
for i in range(np.shape(img)[0]):
    num = 0
    alpha = cs_omp(img[i], mat_dct_1d)
    for j in range(np.shape(alpha)[0]):
        if(alpha[j]!=0.):
            num = num+1
    zero_num.append(num)
    new_img[i] = np.dot(mat_dct_1d,alpha)

cv2.imwrite("./img/newimage.jpg", new_img)
print(zero_num)
print(sum(zero_num))

结果:
原图像:
在这里插入图片描述
经过稀疏表示后再次复原的图像:
在这里插入图片描述

可以看到模糊了很多
但是最后的非零值只有300多个,相比于原图像60×60的大小,稀疏表示能明显的减少参数数量,并尽量保留原图像的特征。
----------------------------分割线-----------------------
话说,最近发博客居然成为了我学习的动力了呢,好想有多几个关注啊(然鹅我在想peach)

你可能感兴趣的:(计算机视觉)