点点点点滴滴滴

一直想写个个人总结神马的,以告慰这一年多自己的所做所为,所学所获。今天终于开动了。

在研一上捣鼓了几个月的FPGA之后,接到导师的一个任务,做一个视觉定位软件,当然主要还是为他们公司服务。先上一张软件的界面图,毕竟 不是美工出身,界面长的可能比较抽象。大笑

                                                                                        图1定位软件


                                                                               图2 标刻软件中 待标刻文字ABCD的位置

由于该定位系统涉及到很多的图像处理算法,为此使用了开源的计算机视觉库opencv来辅助自己的一些算法。

既然是定位啦,那肯定要对相机进行标定了,以图通过物体上某点的像素坐标获得其真实的世界坐标。

对于相机标定我选择了保留一阶径向畸变的非线性模型,通过SVD求解模型的参数矩阵。同时为了提高标定精度,还特意在原来标定的基础上又加了一次标定,实验结果表明精度大大的提高啊大笑

标定完成后,我们就要进行采集一个标准的,位置正确的工件作为模板了,如上图所示。

接着,我们就通过相机获得待定位工件的图像,并进行定位如下图所示:


                                              图3 待定位工件


                                                              图4 定位后ABCD的位置

好吧,上面几个图太抽象了,但总的来说定位的效果达到了。

其实说来说去,在这种学到了什么东西才是最重要的。

让我印象最深刻的一个问题就是,我居然一不小心将临时变量作为了函数的返回值,这直接导致最后得到的定位数据古怪的很。当时看到出来的甚是奇怪的定位结果,硬是将定位的那段代码检查了一遍又一遍,语法没错啊,逻辑关系也没错啊。怎么就是得不到正确的数据呢,最后,我想是不是代码中的某些警告也得重视下呢?于是问题就逮出来了,我居然将一个临时内存的地址作为函数的返回值了。可想而知,一旦这个函数执行完了,这个临时开辟的内存也将被收回,这内存里的有用的值早就无影无踪了。哪儿还等着你来取呢?

还有个问题就是在实现相机标定功能时候,用到了排序。刚开始想着,毕竟定位的要求是要实时,于是就想都没想弄了个快速排序上去,结果发现程序在运行时老是出错,提示栈溢出,定位错误后恍然大悟,原来快速排序也是有死穴的,由于它是递归调用,一直在排序完成之前所有数据都往栈里塞,可想而知系统给函数分配的栈就那么大点,这数据量要是大的话,哪里还放得下呢,不溢出都不正常了。好吧,只能舍弃快速排序了,弄了个稳定空间复杂度较小的插入排序,时间复杂度先忍忍吧。

大家都知道,相机标定涉及到大量的数学计算,刚开始的时候我把标定的代码放到主线程里执行,结果好啊,一点那个相机标定,软件就死了,界面动弹不得,只是当时还不清楚多线程编程这回事儿,于是问同学,同学说你把标定的功能单独开个线程执行看看。真的是一语点醒梦中人啦,于是乎我将标定的功能单独开了个线程执行,从此,软件界面再也不用担心动弹不得了。

总之呢,在做的过程问题还是很多的,还是待我慢慢阅读自己的笔记吧。


二:多线程编程再续前缘与网络编程

数来惭愧,标题可能有点大,但真的只是做了个小小的东西,都有点不好意思了,有图由真相。


                                      图5 服务器端


                                        图6 客户端

先说说两个端的功能吧,客户端首先将标刻软件要标刻的条码传到另台电脑上的服务器端,服务器端得到条码后,访问数据库查询,看该条码是否已经被标刻过,如果不是就将该条码存入本地数据库,并告知客户端此条码可以标刻。如果是,就放弃该条码并告知客户端此条码之前已经被标刻过,让客户端通知本地标刻软件改变条码值。

由于客户端的数量不是很多,因此我选择了较为简单的多线程服务器模型,以提高服务器的并发响应能力。同时使用事件对象对数据库的读写进行保护,防止多个客户端对数据的访问发生冲突。

三:真的是膜拜机器学习,膜拜那些高大上的算法

一直觉得懂几个机器学习的算法,懂些个计算机视觉的算法是多么厉害的事儿。于是那个暑假,买了本机器学习实战的书看了起来,一时兴起,在网上翻天倒海的搜那些人脸库,在此挂上来。,有需要的人可以下载去用用,哈哈。(ORL人脸库)

下面是代码:SMO算法参考的是<<机器学习实战>>

faceRecong.py

# _*_ coding: utf-8 _*_

import SMO
import numpy as np
from os import listdir#listdir获取指定目录里的文件名称并存在列表中
import cv2
import math

trainfilelist = []
def vectortoimg(matrix,H,W):
    img = np.zeros((H,W),np.uint8)
    for i in xrange(H):
        for j in xrange(W):
            img[i,j] = int(np.abs(matrix[i*W + j]))
                           
    return img
def extractFiture(Xinput,W):
    alpha = W.T*Xinput
    return alpha

def faceRebuld(W,y):
    face = W*y
    return face

def calcos(alpha1,alpha2):
    inproduct = alpha1.T*alpha2
    longalpha1 = math.sqrt(alpha1.T*alpha1)
    longalpha2 = math.sqrt(alpha2.T*alpha2)
    cos        = float(inproduct)/(longalpha1*longalpha2)
    return cos

def caloujiDis(alpha1,alpha2):
    return math.sqrt((alpha1 - alpha2).T*(alpha1 - alpha2))

def imgtovector(img):
    c=[]
    for i in xrange(img.shape[0]):
        for j in xrange(img.shape[1]):
            c.append(img[i,j,1])
    img_vector = np.mat(c).transpose()
    return img_vector
            
    
def pca(dirname):
    global trainfilelist
    trainfilelist = listdir(dirname)
    number = len(trainfilelist)
    img = cv2.imread("%s/%s" %(dirname,trainfilelist[0]))
    Height = img.shape[0]
    Width  = img.shape[1]
    c=[]
    matrix = np.mat(np.zeros((Height*Width,1)))
    for n in range(number):
        filenamestr = trainfilelist[n]
        img = cv2.imread("%s/%s" %(dirname,filenamestr))
        for i in range(Height):
            for j in range(Width):
                c.append(img[i,j,1])
        matrix += np.mat(c).transpose()
        c=[]  
    average_matrix = matrix/float(number)

    A = np.mat(np.zeros((Height*Width,number)))
    for n in xrange(number):
        filenamestr = trainfilelist[n]
        img = cv2.imread("%s/%s" %(dirname,filenamestr))
        for i in xrange(Height):
            for j in xrange(Width):
                c.append(img[i,j,1])
        A[:,n] = (np.mat(c).transpose() - average_matrix)
        c= []
    u,s,v = np.linalg.svd(A,False)
    alpha = u[:,0:15].T*A#矩阵alpha的每一列为每张图片的特征,利用这些特征进行分类
    return alpha,average_matrix,u[:,0:15]#u为特征空间,alpha为提取的图像特征

fiture,aver_img,w = pca("E:/yaleB02/label2")
labelclass = [1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]
b1,alphas1 = SMO.smoSimple(fiture.T,labelclass,0.7,0.001,40)
#求权值向量W
W1 = np.mat(np.zeros((15,1)))
for i in xrange(15):
    W1 += alphas1[i,0]*labelclass[i]*fiture[:,i]

labelclass = [-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,-1,-1]
b2,alphas2 = SMO.smoSimple(fiture.T,labelclass,0.7,0.001,40)
#求权值向量W
W2 = np.mat(np.zeros((15,1)))
for i in xrange(15):
    W2 += alphas2[i,0]*labelclass[i]*fiture[:,i]

labelclass = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1]
b3,alphas3 = SMO.smoSimple(fiture.T,labelclass,0.7,0.001,40)
#求权值向量W
W3 = np.mat(np.zeros((15,1)))
for i in xrange(15):
    W3 += alphas3[i,0]*labelclass[i]*fiture[:,i]
#测试
test_img = cv2.imread("E:/yaleB02/test.bmp")
test_imgvec = imgtovector(test_img)
fiture_test = w.T*(test_imgvec - aver_img)

if (W1.T*fiture_test - b1) > 1:
    print u"属于第一类人脸"
elif (W2.T*fiture_test - b2) > 1:
    print u"属于第二类人脸"
else:
    print u"属于第三类人脸"












SMO.py

#_*_ coding:utf-8 _*_

from random import *
from numpy import *
import math


def selectJrand(i,m):#生成一个不为i 的随机数,随机选取一个不同的a值
         j=i
         while (j==i):
                  j = int(random.uniform(0,m))
         return j

def clipAlpha(aj,H,L):
         if aj > H:
                  aj = H
         if L > aj:
                  aj = L
         return aj

def kernel(X,A):#X是所有的样本,A是一个样本,内积在单个样本与所有样本之间计算是行向量
    delta = 1
    m = X.shape[0]
    K = mat(zeros((m,1)))
    for i in xrange(m):
        deltarow = A - X[i,:]
        K[i]     = deltarow*deltarow.T
    K = exp(-K/(2*delta**2))
    return K
        
    


def smoSimple(dataMatrix, classLabels, C, toler, maxIter):
         labelMat = mat(classLabels).transpose()#列表转化为矩阵可以相乘
         #transpose()将行向量变成列向量
         b =0; m,n = shape(dataMatrix)
         alphas = mat(zeros((m,1)))#产生alpha列向量行数为alpha的个数即数据点的个数
         iter = 0
         while (iter < maxIter):
                  alphaPairsChanged = 0
                  for i in range(m):
                           fXi = float(multiply(alphas,labelMat).T*\
                                       kernel(dataMatrix,dataMatrix[i,:])) - b
                           Ei = fXi - float(labelMat[i])
                           if((labelMat[i]*Ei < -toler) and (alphas[i] < C) or\
                              (labelMat[i]*Ei >toler) and (alphas[i] >0)):
                                    j = selectJrand(i,m)
                                    fXj = float(multiply(alphas,labelMat).T*\
                                       kernel(dataMatrix,dataMatrix[j,:])) - b
                                    Ej = fXj - float(labelMat[j])
                                    alphaIold = alphas[i].copy()
                                    alphaJold = alphas[j].copy()
                                    if(labelMat[i] != labelMat[j]):
                                             L = max(0, alphas[j] - alphas[i])
                                             H = max(C, C + alphas[j] - alphas[i])
                                    else:
                                             L = max(0, alphas[j] + alphas[i] - C)
                                             H = min(C, alphas[j] + alphas[i])
                                    if L==H: print "L==H"; continue
                                    eta = 2.0 * kernel(dataMatrix[i,:],dataMatrix[j,:])-\
                                          kernel(dataMatrix[i,:],dataMatrix[i,:]) - \
                                          kernel(dataMatrix[j,:],dataMatrix[j,:])
                                    if eta >=0: print "eta>=0"; continue
                                    alphas[j] -= labelMat[j]*(Ei - Ej)/eta
                                    alphas[j] = clipAlpha(alphas[j],H,L)
                                    if(abs(alphas[j] - alphaJold) < 0.00001):
                                             print "j not moving enough"; continue
                                    alphas[i] +=labelMat[j]*labelMat[i]*\
                                                 (alphaJold - alphas[j])
                                    b1 = b - Ei -labelMat[i]*(alphas[i]-alphaIold)*\
                                         kernel(dataMatrix[i,:],dataMatrix[i,:]) -\
                                         labelMat[j]*(alphas[j] -alphaJold)*\
                                         kernel(dataMatrix[i,:],dataMatrix[j,:])
                                    b2 = b - Ej -labelMat[i]*(alphas[i]-alphaIold)*\
                                         kernel(dataMatrix[i,:],dataMatrix[j,:])-\
                                         labelMat[j]*(alphas[j] -alphaJold)*\
                                         kernel(dataMatrix[j,:],dataMatrix[j,:])
                                    if(0 < alphas[i]) and (C > alphas[i]): b = b1
                                    elif (0 < alphas[j]) and (C > alphas[j]): b = b2
                                    else: b = (b1 + b2)/2.0
                                    alphaPairsChanged += 1
                                    print "iter: %d i:%d, pairs changed %d" %\
                                          (iter,i,alphaPairsChanged)
                  if(alphaPairsChanged == 0):
                           iter += 1
                  else:
                           iter = 0
                  print "iteration number: %d" % iter
                  return b,alphas




                  







                                    
                                             
                                    
                           
                           
         
 

我只用了三类人脸样本来训练,每类只是5个样本,估计没啥精度,下面是运行的结果,居然是对的,哈哈,虽然没啥精度,但作为理解人脸识别的相关算法还是有用的。



四:再说FPGA

说起FPGA一直是心中的痛,大约在本科大四的时候就开始接触了,但那时啥也不懂,稀里糊涂。思维还纯粹停留在简简单单 的编程上面,完全没有将FPGA这块硬件融入到自己的思维里,更别谈什么时序优化了。

直到最近想搞基于FPGA的jpeg编解码,(只是做了个一维DCT变换就放假回家了),总算是体会到了那种时序优化带来的乐趣,看着时序报告中红色的数字变黑还是很有成就感的,


只能说时序余量都变正了,再也不用忍受红色的负余量了。时序不满足,究其原因,确实是我设计有问题,DCT变换实际上也就是一系列的乘累加,问题就出在累加上,刚开始的时候我直接把N多个乘的结果用assign送到一个组合逻辑进行加了,导致加法链太长,从而引起建立时间得不到满足。为此我就试着加了一级寄存器,再看时序报告,负的时序余量再减小了,于是欣喜若狂,好吧那我继续用寄存器分割加法链,哈哈,终于时序得到满足了,可以跑到50M了。

下面是仿真结果,就是输出迟滞还是有点大



未完待续........


记录点滴

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mayo_ai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值