2017年3月6日 星期一

抓老鼠的文件說明


這個演算法基本上是去利用 老鼠的顏色和消去背景法去判斷出老鼠...

同時再利用老鼠的形狀幾何再判斷一次...

可以調的參數


1.    binary_thr_tor  :   老鼠顏色的容忍度,

2.   subtract_background_frame_cnt:   幾張之後背景演算法才會穩定

3.    area_thr   :  老鼠面積的低標

4.    area_thr_max :  老鼠面積的高標

5.    dist_thr      :  距離的高標

6.    mouse_end_en  :  老鼠跑到終點後要不要停止

7.   mouse_end_point_dist_thr  :   老鼠到終點的距離半徑, 越大越容易停止







程式碼的說明









一開始會先去抓  老鼠的顏色thr value

binary_thr = get_mouse_grayval(frame,sx,sy) + binary_thr_tor



binary_thr_tor = 20;
這個數值是  可以手動調整的


def get_mouse_grayval(frame,sx,sy):
     image = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
     val_c = image[sy,sx]
     val_r = image[sy,sx+1]
     val_l = image[sy,sx-1]
     val_t = image[sy-1,sx]
     val_b = image[sy+1,sx]
     val = (int(val_c) + int(val_r) + int(val_l) + int(val_t) + int(val_b))/5

這個類似一個low pass 取平均的做法...抓到老鼠的灰階數值...




接下來就一個大的loop 

去掃每一張 frame

while(1):

        ret, frame = cap.read()   ->    frame 就是input frame的地方

        if(ret == False):
            break


        # 利用  thr 去判斷老鼠在那裏
        im = image_preprocess(frame,file_index,binary_thr)

        #  利用 opencv subbackground algorithm 去除背景
        im2 = image_background_subtract(frame,file_index)

        #  把上述兩個方法一起判斷
        im_and = image_and(im,im2,file_index)

        (get_mouse, cx,cy,area)    = draw_contour(im_and,area_thr,area_thr_max,dist_thr,sx,sy)

.....




def image_preprocess(frame,file_index,thr):

        global kernel
        frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        filename = "./bg_subtract/source/out{0:05d}.jpg".format(file_index)
        cv2.imwrite(filename,frame)   #  debug used


        #  thr 就是一開始算出來的 thr,
        ret,fgmask = cv2.threshold(frame,thr,255,cv2.THRESH_BINARY_INV)

        #  THRESH_BINARY_INV,  就是說小於這個thr的pixel留下來,  大於這個thr移除掉


        #  remove noise
        fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
       #   dilate
        fgmask = cv2.dilate(fgmask,kernel,iterations = 1)


        filename = "./bg_subtract/result_binary/out{0:05d}.jpg".format(file_index)
        cv2.imwrite(filename,fgmask)
        return fgmask


def  image_background_subtract(frame,file_index):
        global kernel
        global fgbg
        frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)


        fgmask = fgbg.apply(frame)

        #  remove noise
        fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)


       #   dilate
        fgmask = cv2.dilate(fgmask,kernel,iterations = 1)

        #  remove some shadow
        ret,fgmask = cv2.threshold(fgmask,140,255,cv2.THRESH_BINARY)

        filename = "./bg_subtract/result_subtract/out{0:05d}.jpg".format(file_index)
        cv2.imwrite(filename,fgmask)
        return fgmask



def  image_background_subtract(frame,file_index):
        global kernel
        global fgbg
        frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)


        fgmask = fgbg.apply(frame)

        #  remove noise
        fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)


       #   dilate
        fgmask = cv2.dilate(fgmask,kernel,iterations = 1)

        #  remove some shadow

        #  這邊也是一個可以調的參數,  建議是不要去動他
        ret,fgmask = cv2.threshold(fgmask,140,255,cv2.THRESH_BINARY)

        filename = "./bg_subtract/result_subtract/out{0:05d}.jpg".format(file_index)
        cv2.imwrite(filename,fgmask)
        return fgmask


#  
def   image_and(frame1,frame2,file_index):
        global subtract_background_frame_cnt

        # 這個演算法是利用iteration的方式找出不會動的背景,
        #  所以一開始會找不到老鼠
        #  只好小於subtract_background_frame_cnt 的frame都判斷可以找到老鼠
        if(file_index < subtract_background_frame_cnt):
            fgmask = frame1
        else:
            ret,mask = cv2.threshold(frame1,10,255,cv2.THRESH_BINARY)
            fgmask = cv2.bitwise_and(frame2,frame2,mask = mask)
        filename = "./bg_subtract/result_and/out{0:05d}.jpg".format(file_index)
        cv2.imwrite(filename,fgmask)
        return fgmask


#   找出老鼠,  這裡還會用面積的方是在判斷一次
def    draw_contour(im,area_thr,area_thr_max,dist_thr,sx,sy):
        dst ,contours, hierarchy = cv2.findContours(im,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

        get_mouse = 0

        cx = 0
        cy = 0
        area = 0
        for i in range(len(contours)):
                cnt = contours[i]
                M = cv2.moments(cnt)
                area = cv2.contourArea(cnt)

                perimeter = cv2.arcLength(cnt,True)
                x,y,w,h = cv2.boundingRect(cnt)

                (cx,cy),radius = cv2.minEnclosingCircle(cnt)
                center = (int(cx),int(cy))
                start = (sx,sy)
                radius = int(radius)
                dist = distance(sx,sy,int(cx),int(cy))

                # area_thr  ->  一定要大於  area_thr,   
                #  這裏我假設老鼠有慣性,  不會這張找到的老鼠和上一張找到得老鼠
                #  跳太遠,  設了一個 高標 dist_thr,  一定要小於這個 dist_thr
                #   area_thr_max,  但是老鼠也不能太大隻,  所以設了一個thr
                if( (area > area_thr) & (dist < dist_thr) & (area < area_thr_max) ):
                        print "area : " + str(area)
                        get_mouse = 1









沒有留言:

張貼留言