Logistical Regression and Fatigue Detection —— 疲劳驾驶检测装置

OpenCV ali ⋅ 于 2017-01-21 14:59:20 ⋅ 1759 阅读

作者:汤小聪
当今存在着很多疲劳驾驶的问题,同时此问题也酿成很多交通事故。对于上班族,结束了一天繁忙的工作,身心疲惫,不乏存在有疲劳驾驶的可能;再者,对于长途司机,货车司机,连夜的驾驶,疲劳驾驶肯定存在。毋庸置疑,疲劳驾驶存在着巨大的安全隐患,如果有那么一种声音在警惕驾驶员,不断地提醒他,我想安全问题会大大降低。
Today!!!我们带来机器学习的案例,来解决此类问题-------你困了吗?

那么,什么是机器学习?

机器学习是一种让计算机在没有事先明确的编程的情况下做出正确反应的科学。通俗的讲,就像教小孩子知识一样,只不过在这里对象换成了“机器”,我们教它对数据的分析能力从而让它具有判断力。

  • 教它掌握知识的过程--------fit( )/train( )
  • 让它运用它的能力去判断--------predict( )
下面,我们就要开始代码实战啦!

首先,我们将导入haarcascade的xml文件。

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')

Haarcascade是训练好的分类器,我们可以利用它捕获相应的内容,本例中我们需要捕获的是人脸和眼睛,所以我们导入了脸部识别和眼睛识别的分类器。
然后,我们就要开始创建我们的模型,再训练它,本例中我们选择的模型为lr(logistic regression),我们设定为通过判断驾驶员的眼睛的大小来判断他是否睡着,所以我们需要提供eyeopen和eyeclose两种情况的图片来训练我们的模型,让它具有识别的能力和准确率。

    # N x dim matrix to store the vectorized data (aka feature space)       
    phi = np.zeros((len(eyeopenfiles) + len(eyeclosedfiles), dim))
    # 1 x N vector to store binary labels of the data: 1 for eyeopen and 0 for eyeclosed
    labels = []

    # load eyeopen data
    PATH = "../data/eyeopen/"
    for idx, filename in enumerate(eyeopenfiles):
        phi[idx] = vectorize(PATH + filename)
        labels.append(1)

    # load eyeclosed data    
    PATH = "../data/eyeclose/"
    offset = idx + 1
    for idx, filename in enumerate(eyeclosedfiles):
        phi[idx + offset] = vectorize(PATH + filename)
        labels.append(0)

    """
    training the data with logistic regression
    """
    lr = logistic.Logistic(dim)
    lr.train(phi, labels)
    s=float(d.datetime.strftime(d.datetime.now(), '%S')) 

明确一个feature对应一个label,从上述代码中可以看出phi[ ]存放的是一个个feature,而labels[ ]存放的是一个个与之对应的label。我们遍历eyeopen和eyeclose两个文件夹,获得已采取的睁着眼睛和闭着眼睛的图文样例的矢量化对象,每读取读取一个feature就要在labels[ ]列表后追加1或0(“1”代表open;“0”代表close)。最后创建lr模型,运用lr.train(feature,label);进行训练。
训练完成了之后,就该对未知的数据进行预测和判断了。

    while rval:
        cv2.imshow("preview", frame)
        rval, frame = vc.read()

        key = cv2.waitKey(40)
        if key == 27: # exit on ESC
            break
        if float(d.datetime.strftime(d.datetime.now(), '%S')) %4==0: # press space to save images
            cv.SaveImage("webcam.jpg", cv.fromarray(frame))
            img = cv.LoadImage("webcam.jpg") # input image
            img1 = e.findeye(img)
            img2=m.findmouth(img)
            # show(mouth)
            if img1 != 2: # did not return error
                eyeing = crop(img1)
                cv.SaveImage("webcam-eye.jpg", eyeing)
                # predict the captured emotion

                result = lr.predict(vectorize('webcam-eye.jpg'))
                if result == 1:
                    print "your eye is open! :-) "
                else:
                    print "your eye is close :-| "
                    k=k+1
                    print k
            else:
                #print "failed to detect mouth. Try hold your head straight and make sure there is only one face."
                print "your eye is close :-| "
                k=k+1
            if k :

                espeak.synth("Watch out")
                espeak.synth("It is dangerous")
                k = 0
                continue

可以看到代码中很明确的运用了result=lr.predict(vectorize(“xxx.jpg”));这句代码就是对录取到的驾驶员的图像的矢量化对象进行预测判断,当lr模型判断为0时,将会输出“your eye is close :-|”同时还会使用python中的espeak包,将文字转化为音频,来警惕驾驶员。但对于result=lr.predict(vectorize(“xxx.jpg”));之前的那些代码,它阐述的是首先从视频的录制获取当前的一帧图像并且保存为“webcam.jpg”,然后使用分类器找到图像中的眼睛部分,然后使用crop(area)方法来进行具体的分割,最终将其矢量化,传给predict()函数。
Crop( )代码以及矢量化vectorize( )代码

"""
given an area to be cropped, crop() returns a cropped image
"""
def crop(area): 
    crop = img[area[0][1]:area[0][1] + area[0][3], area[0][0]:area[0][0]+area[0][2]] #img[y: y + h , x: x + w]
    return crop

"""
given a jpg image, vectorize the grayscale pixels to 
a (width * height, 1) np array
it is used to preprocess the data and transform it to feature space
"""
def vectorize(filename):
    size = WIDTH, HEIGHT # (width, height)
    im = Image.open(filename) 
    resized_im = im.resize(size, Image.ANTIALIAS) # resize image
    im_grey = resized_im.convert('L') # convert the image to *greyscale*
    im_array = np.array(im_grey) # convert to np array
    oned_array = im_array.reshape(1, size[0] * size[1])
    return oned_array

对于lr模型对于图片处理的步骤简单解释:
file
先将一个图片分成很多小块,像素为0-255之间的任意值,然后将这个图片如图进行时矢量化,其矢量化的步骤就如代码所述,先将其调整为符合需求的大小,然后再将其灰度化,最终写入numpy array中,在规定相应的numpy array的属性。
前面我们提到了训练模型时的train(feature,label)方法,其中feature就是一个图片样例矢量化的数组,我们将这些矢量化的对象传入,lr'模型会对其进行左乘一个矩阵将其投影到低纬的空间,这样,通过大量的样本数据训练,可以将模型的相关参数得到,这样我们就得到了一个逻辑回归的模型。对于未知的数据我们就可以代入模型,根据计算的概率判断预测的结果是眼睛睁开还是闭合。这就是我们predict()方法所做的事情。
简单的代码思路讲解完啦,有没有体会到机器学习的魅力呢。快来加入机器学习的队伍吧!用代码改变世界!

本帖已被设为精华帖!
本帖由 YXZhu 于 3年前 加精
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter