-3

Here is the python code I have written :-

import cv2
import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",
help = "path to the (optional) video file")
args = vars(ap.parse_args())

if not args.get("video", False):
    cap = cv2.VideoCapture(0)
else:
    cap = cv2.VideoCapture(args["video"])
fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()
while True:
    ret, frame = cap.read()
    fgmask = fgbg.apply(frame)
    cv2.imshow('frame',fgmask)
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()

How to put bounding box around the detected human outline and improve efficiency of the python code to perform background subtraction on the live video feed taken from webcam. Can someone help?

Ritwik
  • 1
  • 1
  • 4

2 Answers2

2

Drawing Contour Using Background Subtraction

import cv2
import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",
help = "path to the (optional) video file")
args = vars(ap.parse_args())

if not args.get("video", False):
    cap = cv2.VideoCapture(0)
else:
    cap = cv2.VideoCapture(args["video"])
fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()
while True:
    ret, frame = cap.read()
    fgmask = fgbg.apply(frame)

    gray=cv2.cvtColor(fgmask,cv2.COLOR_BGR2GRAY)
    ret,th1 = cv2.threshold(gray,25,255,cv2.THRESH_BINARY)
    _,contours,hierarchy = cv2.findContours(th1,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area > 1000 and area < 40000:
            x,y,w,h = cv2.boundingRect(cnt)
            cv2.rectangle(fgmask,(x,y),(x+w,y+h),(255,0,0),2)

    cv2.imshow('frame',fgmask)
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()

Drawing Contour using HSV Masking and Convex Hull
Set value for hsv mask.

import cv2
import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",
help = "path to the (optional) video file")
args = vars(ap.parse_args())

if not args.get("video", False):
    cap = cv2.VideoCapture(0)
else:
    cap = cv2.VideoCapture(args["video"])
    fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()
while True:
    ret, frame = cap.read()

    frame = cv2.imread(frame)
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    lower = np.array([50,103,40])
    upper = np.array([255,255, 255])

    mask = cv2.inRange(hsv, lower, upper)
    fg = cv2.bitwise_and(frame, frame, mask=255-mask)

    fg = cv2.cvtColor(fg.copy(),cv2.COLOR_HSV2BGR)
    fg = cv2.cvtColor(fg,cv2.COLOR_BGR2GRAY)

    fg = cv2.threshold(fg, 120,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
    #plt.imshow(fg)
    #plt.show()


    fgclosing = cv2.morphologyEx(fg.copy(), cv2.MORPH_CLOSE, kernel)
    se = np.ones((3,3),np.uint8)
    #fgdilated = cv2.morphologyEx(fgclosing, cv2.MORPH_CLOSE,cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (4,4)))
    fgdilated = cv2.dilate(fgclosing, kernel = se , iterations = 8)

    img = frame.copy()
    ret, threshed_img = cv2.threshold(fgdilated,
                    127, 255, cv2.THRESH_BINARY)
    image, contours, hier = cv2.findContours(threshed_img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

    for cnt in contours:
        #print(cv2.contourArea(cnt))
        if cv2.contourArea(cnt) > 44000:
            # get convex hull
            hull = cv2.convexHull(cnt)
            #cv2.drawContours(img, [hull], -1, (0, 0, 255), 1)
            #print(hull)
            (x,y,w,h) = cv2.boundingRect(cnt)
            #cv2.rectangle(img, (x,y), (x+w,y+h), (255, 0, 0), 2)
            contours = hull
            #c1 = max(contours, key=cv2.contourArea)
            hull = cv2.convexHull(cnt)
            c = hull
            #print(c)
            cv2.drawContours(img, [hull], -1, (0, 0, 255), 1)
            # determine the most extreme points along the contour
            extLeft = tuple(c[c[:, :, 0].argmin()][0])
            extRight = tuple(c[c[:, :, 0].argmax()][0])
            extTop = tuple(c[c[:, :, 1].argmin()][0])
            extBot = tuple(c[c[:, :, 1].argmax()][0])

            cv2.drawContours(img, [c], -1, (0, 255, 255), 2)
            cv2.circle(img, extLeft, 8, (0, 0, 255), -1)
            cv2.circle(img, extRight, 8, (0, 255, 0), -1)
            cv2.circle(img, extTop, 8, (255, 0, 0), -1)
            cv2.circle(img, extBot, 8, (255, 255, 0), -1)

            lx = extLeft[1]
            ly = extLeft[0]
            rx = extRight[1]
            ry = extRight[0]
            tx = extTop[1]
            ty = extTop[0]
            bx = extBot[1]
            by = extBot[0]   

            x,y = lx,by
            w,h = abs(rx-lx),abs(ty-by)

            #cv2.rectangle(img, (x,y), (x+w,y+h), (255, 0, 0), 2)
            font = cv2.FONT_HERSHEY_SIMPLEX
            cv2.putText(img,str(extLeft[0])+','+str(extLeft[1]),(extLeft), font, 2,(0, 0, 255),2,cv2.LINE_AA)
            cv2.putText(img,str(extRight[0])+','+str(extRight[1]),(extRight), font, 2,(0, 255, 0),2,cv2.LINE_AA)
            cv2.putText(img,str(extTop[0])+','+str(extTop[1]),(extTop), font, 2,(255, 0, 0),2,cv2.LINE_AA)
            cv2.putText(img,str(extBot[0])+','+str(extBot[1]),(extBot), font, 2,(255, 255, 0),2,cv2.LINE_AA)

            im = frame[tx:bx,ly:ry,:]
            cx = im.shape[1]//2
            cy = im.shape[0]//2
            cv2.circle(im, (cx,cy), 15, (0, 255, 0))

    plt.imshow(img)
    plt.show()
Pygirl
  • 12,969
  • 5
  • 30
  • 43
0

You can use findContours.

import cv2
import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",
help = "path to the (optional) video file")
args = vars(ap.parse_args())

if not args.get("video", False):
    cap = cv2.VideoCapture(0)
else:
    cap = cv2.VideoCapture(args["video"])
fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()
while True:
    ret, frame = cap.read()
    fgmask = fgbg.apply(frame)

    mask = 255 - fgmask
    _, contours, _ = cv2.findContours(
        mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    fgmask = cv2.cvtColor(fgmask, cv2.COLOR_GRAY2BGR)
    for contour in contours:
        area = cv2.contourArea(contour)

        #only show contours that match area criterea
        if area > 500 and area < 20000:
            rect = cv2.boundingRect(contour)
            x, y, w, h = rect
            cv2.rectangle(fgmask, (x, y), (x+w, y+h), (0, 255, 0), 3)

    cv2.imshow('frame',fgmask)
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()

I have tested with the video https://github.com/opencv/opencv/blob/master/samples/data/vtest.avi

Fred Guth
  • 1,537
  • 1
  • 15
  • 27