Machine Learning

openCV를 이용한 motion detection 후 이미지 캡쳐 코드

oziguyo_ 2021. 2. 15. 17:57
728x90

def image(ipath,file, spath,name):
    global cnt,fp
    path = os.path.join(ipath, file)

    #file_name = file.split(".", 1)[0]

    #print(file_name)


    cap = cv.VideoCapture(path)
    firstframe = None
    fps = int(cap.get(5))
    # cap.set(cv.CAP_PROP_FRAME_WIDTH, 680)
    # cap.set(cv.CAP_PROP_FRAME_HEIGHT, 480)
    print("fps : %s"%fps)
    if (fp==0):
        fp=input("crop fps : ")
        int(fp)
    # 배경빼기
    fgbg = cv.createBackgroundSubtractorMOG2(varThreshold=300, detectShadows=False)
    kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3))
    while (cap.isOpened()):

        (ret, frame) = cap.read()
        if not ret:
            break

        (ret, frame2) = cap.read()
        if not ret:
            break
        output = frame2.copy()

        frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
        frame2 = cv.cvtColor(frame2, cv.COLOR_BGR2GRAY)

        gray = fgbg.apply(frame)
        gray2 = fgbg.apply(frame)

        if firstframe is None:
            firstframe = gray
            continue

        # 프레임 차이
        frameDelta = cv.absdiff(firstframe, gray)
        frameDelta2 = cv.absdiff(gray, gray2)
        # 임계값 25보다 크면 255 아니면 0
        thresh = cv.threshold(frameDelta, 25, 255, cv.THRESH_BINARY)[1]
        thresh2 = cv.threshold(frameDelta2, 25, 255, cv.THRESH_BINARY)[1]
        # 모폴로지기법, 필터내부의 가장 밝은(높은)값으로 변환-팽창연산
        thresh = cv.dilate(thresh, None, iterations=10)
        thresh2 = cv.dilate(thresh2, None, iterations=10)

        diff = cv.bitwise_and(thresh, thresh2)

        # 흰색 형태개선
        diff = cv.morphologyEx(diff, cv.MORPH_OPEN, kernel)

        # 특성검출
        contours = cv.findContours(diff.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
        contours = imutils.grab_contours(contours)
        cnt = cnt + 1
        if (cnt % fp == 0):

            for c in contours:
                if cv.contourArea(c) < 5:
                    continue
                # (x, y, w, h) = cv.boundingRect(c)
                # if x < 500 or x > 1000:
                #     continue

                cv.imwrite("%s/%s_%05d.jpg" % (spath,name, cnt/fp), output)


        cv.imshow("output", output)

        k = cv.waitKey(1) & 0xFF
        if k == ord('q'):
            break
    print("finish")
    cap.release()
    cv.destroyAllWindows()

if __name__ == '__main__':
    import os
    import imutils
    import sys, subprocess
    import argparse
    import shutil
    subprocess.call([sys.executable, '-m', 'pip', 'install', '--upgrade', 'opencv-contrib-python'])
    import cv2 as cv
    global cnt,fp
    cnt = 1
    fp=0
    parser = argparse.ArgumentParser(description='video crop')
    parser.add_argument('-i', '--input_dir', default='input', type=str, help='path to input directory')
    parser.add_argument('-s', '--save_dir', default='save', type=str, help='path to save directory')
    parser.add_argument('-n', '--file_name', default='name', type=str, help='naming to save file')

    args = parser.parse_args()
    INPUT_DIR = args.input_dir
    FILE_NAME=args.file_name
    if args.save_dir=='save':
        SAVE_DIR=INPUT_DIR+'/image'
    else :
        SAVE_DIR=args.save_dir


    files=os.listdir(INPUT_DIR)
    if (os.path.isdir(SAVE_DIR) == True):
        shutil.rmtree(SAVE_DIR)
    os.mkdir("%s" % (SAVE_DIR))
    for file in files:
        print(file)
        image(INPUT_DIR,file,SAVE_DIR,FILE_NAME)


 

위 코드를 video_cap.py 라고 저장했을 경우,

python video_cap.py -i <영상 디렉토리> -s <저장할 디렉토리> -n <캡쳐될 사진 이름>

이렇게 실행하면 된다.

728x90