Skip to content

This is the bigining of the idea of how to make an open-source somnolence detector. Any help will be appreciated

Notifications You must be signed in to change notification settings

CarlosLunaGit/Somnolence-Detector

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

Somnolence-Detector

#This is the bigining of the idea of how to make an open-source somnolence detector. Any help will be appreciated #The main target is that it could be used embebed in a raspberry pi 2, but there are a lot of computational limitations yet. #This programa has been wrote in Python 2.7 and it makes use of Libraries as OpenCV. #The last commented lines are from the uses of a SEN10171P digital light sensor. #As code is presented here is posible to run it in a Laptop with Windows 8 as well as in raspbian. #¿how to extract face landmarks once detected the region of interest of the face?

import numpy as np
import cv2
import video
##import smbus
import math
from common import draw_str, RectSelector

def rnd_warp(a):
    	h, w = a.shape[:2]
    	T = np.zeros((2, 3))
    	coef = 0.2
    	ang = (np.random.rand()-0.5)*coef
    	c, s = np.cos(ang), np.sin(ang)
    	T[:2, :2] = [[c,-s], [s, c]]
    	T[:2, :2] += (np.random.rand(2, 2) - 0.5)*coef
		c = (w/2, h/2)
    	T[:,2] = c - np.dot(T[:2, :2], c)
    	return cv2.warpAffine(a, T, (w, h), borderMode = cv2.BORDER_REFLECT)

ef divSpec(A, B):
    	Ar, Ai = A[...,0], A[...,1]
    	Br, Bi = B[...,0], B[...,1]
    	C = (Ar+1j*Ai)/(Br+1j*Bi)
     	C = np.dstack([np.real(C), np.imag(C)]).copy()
	 	return C
 
e ps = 1e-5
 
        

class MOSSE():
    def __init__(self, frame, rect):
        x1, y1, x2, y2 = rect
        w, h = map(cv2.getOptimalDFTSize, [x2-x1, y2-y1])
        x1, y1 = (x1+x2-w)//2, (y1+y2-h)//2
        self.pos = x, y = x1+0.5*(w-1), y1+0.5*(h-1)
        self.size = w, h
        img = cv2.getRectSubPix(frame, (w, h), (x, y))
    
        self.win = cv2.createHanningWindow((w, h), cv2.CV_32F)
        g = np.zeros((h, w), np.float32)
        g[h//2, w//2] = 1
        g = cv2.GaussianBlur(g, (-1, -1), 2.0)
        g /= g.max()

        self.G = cv2.dft(g, flags=cv2.DFT_COMPLEX_OUTPUT)
        self.H1 = np.zeros_like(self.G)
        self.H2 = np.zeros_like(self.G)
        for i in xrange(3):
            a = self.preprocess(rnd_warp(img))
            A = cv2.dft(a, flags=cv2.DFT_COMPLEX_OUTPUT)
            
            self.H1 += cv2.mulSpectrums(self.G, A, 0, conjB=True)
            self.H2 += cv2.mulSpectrums(     A, A, 0, conjB=True)
         
        self.update_kernel()
        self.update(frame)

    def update(self, frame, rate = 0.125):
        global psr_
        (x, y), (w, h) = self.pos, self.size
        self.last_img = img = cv2.getRectSubPix(frame, (w, h), (x, y))
        img = self.preprocess(img)
        self.last_resp, (dx, dy), self.psr = self.correlate(img)
        psr_=self.psr
        self.good = self.psr > 8.0
        if not self.good:
            return
        self.pos = x+dx, y+dy
        self.last_img = img = cv2.getRectSubPix(frame, (w, h), self.pos)
        img = self.preprocess(img)
##        A = cv2.dft(img, flags=cv2.DFT_COMPLEX_OUTPUT)
##        H1 = cv2.mulSpectrums(self.G, A, 0, conjB=True)
##        H2 = cv2.mulSpectrums(     A, A, 0, conjB=True)
##        self.H1 = self.H1 * (1.0-rate) + H1 * rate
##        self.H2 = self.H2 * (1.0-rate) + H2 * rate
##        self.update_kernel()

    @property
    def state_vis(self):
        f = cv2.idft(self.H, flags=cv2.DFT_SCALE | cv2.DFT_REAL_OUTPUT )
        h, w = f.shape
        f = np.roll(f, -h//2, 0)
        f = np.roll(f, -w//2, 1)
        kernel = np.uint8( (f-f.min()) / f.ptp()*255 )
        resp = self.last_resp
        resp = np.uint8(np.clip(resp/resp.max(), 0, 1)*255)

##        write(0x29,0x03)
##        value=(readWORD(address,0xAC))
##        print value
##        if value < 38:
##            diff=38-value
##            value=value+diff
##        if value > 39:
##            diff=value-39
##            value=value-diff
        #print value
        ret,crop_frameB = cv2.threshold(self.last_img,15,255,cv2.THRESH_BINARY)
        crop_frameB=smallmask1 & crop_frameB
        ret,crop_frameD = cv2.threshold(self.last_img,15,255,cv2.THRESH_BINARY)
        crop_frameD=smallmask & crop_frameD
        
        cv2.imshow("ojos",crop_frameD)
        cv2.imshow("boca",crop_frameB)
##        if circles is not None:
##                for i in circles[0,:]:
##                    cv2.circle(self.last_img,(i[0],i[1]),i[2],(0,0,255),2)
##                    cv2.circle(self.last_img,(i[0],i[1]),2,(255,0,0),3)
##                    print (i[0],i[1],i[2])
        vis = np.hstack([self.last_img, kernel, resp])
        self.last_img = cv2.cvtColor(self.last_img, cv2.COLOR_GRAY2BGR)
##        sum=crop_frameB.sum()
##        print  sum
        
        return vis

    def draw_state(self, vis):   
        (x, y), (w, h) = self.pos, self.size
        x1, y1, x2, y2 = int(x-0.5*w), int(y-0.5*h), int(x+0.5*w), int(y+0.5*h)
        cv2.rectangle(vis, (x1, y1), (x2, y2), (0, 0, 255))
        
        
        if self.good:
            cv2.circle(vis, (int(x), int(y)), 2, (0, 0, 255), -1)
        else:
            cv2.line(vis, (x1, y1), (x2, y2), (0, 0, 255))	
            cv2.line(vis, (x2, y1), (x1, y2), (0, 0, 255))
        draw_str(vis, (x1, y2+16), 'PSR: %.2f' % self.psr)
        
    def preprocess(self, img):
        img = np.log(np.float32(img)+1.0)
        img = (img-img.mean()) / (img.std()+eps)
        return img*self.win

    def correlate(self, img):
        C = cv2.mulSpectrums(cv2.dft(img, flags=cv2.DFT_COMPLEX_OUTPUT), self.H, 0, conjB=True)
        resp = cv2.idft(C, flags=cv2.DFT_SCALE | cv2.DFT_REAL_OUTPUT)
        h, w = resp.shape
        _, mval, _, (mx, my) = cv2.minMaxLoc(resp)
        side_resp = resp.copy()
        cv2.rectangle(side_resp, (mx-5, my-5), (mx+5, my+5), 0, -1)
        smean, sstd = side_resp.mean(), side_resp.std()
        psr = (mval-smean) / (sstd+eps)
        return resp, (mx-w//2, my-h//2), psr

    def update_kernel(self):
        self.H = divSpec(self.H1, self.H2)
        self.H[...,1] *= -1

class App :
    def __init__(self, video_src):
        steady=1
        while True:
            ret, frame = video_capture.read() 
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            heigth,width=gray.shape
            print heigth,width
            faces = faceCascade.detectMultiScale(gray, scaleFactor=3.2,minNeighbors=4, minSize=(150, 160), flags = cv2.CASCADE_SCALE_IMAGE)
            steady=steady+1
            if steady==11:
                steady=0
            if ( len(faces)>0) & (steady==10):
                break
            print "Not face detected"
        for (x, y, w, h) in faces:
            print 'Localizado'
##            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
##            cv2.putText(frame,'w: ' +str(heigth)+ ' h: '+str(width),(5,20),cv2.FONT_HERSHEY_SIMPLEX, .5,(0,0,0),2)
##            cv2.imshow('Localización de rostro', frame)	
        _, self.frame = video_capture.read()
        self.trackers = []
##        X=50
##        Y=80
##        W=40
##        H=50
##        self.onrect([x+X,y+Y,x+W+X,y+H+Y])
##
##        X=140
##        Y=80
##        W=40
##        H=50
##        self.onrect([x+X,y+Y,x+W+X,y+H+Y])
        
        Xm=80
        Ym=160
        Wm=90
        Hm=55
        self.onrect([x+Xm,y+Ym,x+Wm+Xm,y+Hm+Ym])
        self.onrect([x,y,w+x,h+y])
       
      
        

    def onrect(self, rect):
        frame_gray = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
        tracker = MOSSE(frame_gray, rect)
        self.trackers.append(tracker)
        
 
    def run(self):
        while True:
            global psr_
            ret, self.frame = video_capture.read()
            frame_gray = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
            for tracker in self.trackers:
                    tracker.update(frame_gray)
            vis = self.frame.copy()
            for tracker in self.trackers:
                tracker.draw_state(vis)
            if len(self.trackers) > 0:
                cv2.imshow('tracker state', self.trackers[-1].state_vis)
            cv2.imshow('frame', vis)
            ch = cv2.waitKey(1) & 0xFF
            if ch == 27:
                break
            if psr_<=8:
                break

##bus = smbus.SMBus(1)
##address = 0x29
##
##
##cv2.imshow('Mask',smallmask)
##cv2.imshow('Mask1',smallmask1)
##
##
##def write(ADD,value):
##        bus.write_byte(ADD,value)
##        return -1
##
##def readWORD(ADD,value):
##        word=bus.read_word_data(ADD,value)
##        return word
##
##def readsen():
##        light = bus.read_byte(address)
##        return light
##cv2.waitKey(100)
##print 'Conectado sensor de Luz......'
##cv2.waitKey(100)
##print'..............'
##value=readsen()
##if value != 3:
##
##    print (value)
##    print ('Localizando')
##    cv2.waitKey(100)
##print'..............'
##cv2.waitKey(100)
##print'......'
##
##while value == 3:
##    write(0x29,0x03)
##    value=readWORD(address,0xAC)
##    print (value)
##    print ('Hecho')
##print (value)
##cv2.waitKey(100)
##print'Ok'
##cv2.waitKey(100)
##

mask=cv2.imread('C:/Users/Carlos Luna/Desktop/tablero_sencillo_blanco_y_negro.jpg')      
smallmask = cv2.resize(mask, (250,250))
smallmask=cv2.cvtColor(smallmask,cv2.COLOR_BGR2GRAY)
smallmask = cv2.GaussianBlur(smallmask,(5,5),3)

mask1=cv2.imread('C:/Users/Carlos Luna/Desktop/tablero_sencillo_blanco_y_negro.jpg')
smallmask1= cv2.resize(mask1, (250,250))
smallmask1=cv2.cvtColor(smallmask1,cv2.COLOR_BGR2GRAY)
smallmask1 = cv2.GaussianBlur(smallmask1,(5,5),3)

faceCascade = cv2.CascadeClassifier('../../data/haarcascades/haarcascade_frontalface_default.xml')
video_capture=cv2.VideoCapture(0)


while (1) :
        App(0).run()
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
video_capture.release()
cv2.destroyAllWindows()

About

This is the bigining of the idea of how to make an open-source somnolence detector. Any help will be appreciated

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published