Python独習!

習得したPython知識をペイフォワード

PythonでUSBカメラのスナップショットを大量に取得する!

USBカメラから自動で大量に画像を取得するプログラムを作った。

用途

機械学習用に大量に画像データを取得するときなど。

プログラムの概要

  • 実行すると、フォルダダイアログが立ち上がるので保存先を指定する。保存先に自動的に新規フォルダが作成される。名前にその時の時刻が含まれる。
  • そのまま指定した枚数の撮像&保存が始まる。
  • 枚数の指定は以下の"10"の部分。上限を1000にしてある。
acquire_save(10, specify_destination())
  • While文の中のSleepを調整することで、撮像の間隔を変えられる。

ソースコード

#python 3.8.1
#opencv-contrib-python 4.2.0.32

"""
This script acquires and saves a large amount of images from a camera.
"""

import sys
import os
from time import sleep
from datetime import datetime
import tkinter as tk
from tkinter import filedialog

import cv2


class MyException(Exception):
    pass


def specify_destination():

    #Define name of a folder where images will be stored. 
    now = datetime.now()
    new_folder_name = 'Images_{:%Y%m%d%H%M%S}'.format(now)

    try:
        print("Specify a directory to make a new folder to store images.")

        #Let users specify a directory where a new folder will be made.    
        idir = os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + "\\Desktop"
        dst = filedialog.askdirectory(initialdir = idir)

        #If users canceled when specifying the directory, raise MyException.
        if dst == "":
            raise MyException("Cancel clicked!")

        #Then, make the folder for storing images.
        dst_path = os.path.join(dst, new_folder_name)
        os.mkdir(dst_path) 

    except MyException as e:
        print(e)
        sys.exit()

    except Exception:
        print("Unexpected error occurred.")
        sys.exit()

    else:
        print("The folder was successfully created.")
       
    return dst_path


def acquire_save(num_acquisition, save_path):
    try:     
        #Make a camera instance.
        cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
 
        #Check if the camera instance is sure to be opened.
        if not cap.isOpened():
            raise MyException("Camera Not Found!")

        #Check if num_acquisition is integer.
        if not isinstance(num_acquisition, int):
            raise MyException("Num of acquisitoin is wrong.")

        #Check if num_acquisition is less than 1000.
        if num_acquisition > 1000:
            raise MyException("Too much number you requested!")

        #Check if save_path is sure to exist.
        if not os.path.isdir(save_path):
            raise MyException("The directory does not exist.")

        print("Start to acquire and save images repeatedly.")    

        num = num_acquisition
        while num > 0:
            print(num)
            sleep(0.1)

            _, frame = cap.read()

            #Define name of images including sequential number.
            file_name = "sample_{:04}.jpg".format(num)
            cv2.imwrite(os.path.join(save_path, file_name), frame)

            num -= 1
    
    except MyException as e:
        print(e)
        sys.exit()

    except Exception:
        print("Unexpected error occurred.")
        sys.exit()

    else:
        print("Successfully completed!")

    finally:
        cv2.destroyAllWindows()
        cap.release()


if __name__ == '__main__':
    root = tk.Tk()
    root.withdraw()
    acquire_save(10, specify_destination())

ちょっとした気づき

except句にsys.exit()が含まれていても、ちゃんとfinally句は実行されるようだ。

/* -----codeの行番号----- */