개요

Python 언어로 컴퓨터 비전 관련 프로그램을 작성할 때 다양한 영상 소스가 사용되고, 우리가 일반적으로 웹캠이라 부르는 USB 단자를 통해 연결되는 UVC 카메라가 상당히 많이 사용된다.

다양한 제조사에서 만드는 카메라들은 다양한 해상도를 지원하고 밝기, 채도, 색상 등 다양한 조절할 수 있는 프로퍼티가 많다. 하지만 이를 어떻게 조정하는지 잘 모르는 사람도 있고 구체적으로 어떻게 조정해야할 지 모르는 경우도 많아서 이에 대해 작성해 보고자 한다.

환경

아래에 기술할 방법론은 윈도우기반 os에서 확인이 불가능한 것은 아니지만 리눅스기반 os환경에선 쉽게 확인할 수 있다. 아래의 내용에선 Ubuntu OS를 전제로 서술한다.

v4l2-ctl

설치

우선 터미널에서 v4l2-ctl 명령어를 통해 연결된 카메라의 제어가능한 프로퍼티을 확인할 수 있다. v4l2-ctl 명령어가 없다면 터미널에서 아래의 명령어를 통해 설치한다.

$ sudo apt install v4l-utils

카메라 확인

설치가 완료되었다면 일단 아래의 명령어를 통해서 연결되어있고 사용가능한 카메라 목록을 볼 수 있다.

$ v4l2-ctl --list-devices

결과는 다음과 같이 나온다.

C270 HD WEBCAM (usb-0000:00:14.0-10.2):
	/dev/video0
	/dev/video1

HD USB Camera: HD USB Camera (usb-0000:00:14.0-10.4):
	/dev/video2
	/dev/video3

본인의 경우 로지텍의 C270카메라가 /dev/video0, /dev/video1 장치명을 할당, 개발환경을 위한 또 다른 USB 카메라가 /dev/video2, /dev/video3을 할당하는 것을 볼 수 있다.

카메라 프로퍼티 확인

지원해상도

v4l2-ctl 명령어와 장치명을 알려주는 -d 옵션 그리고 지원해상도를 보기위한 --list-formats-ext 옵션을 같이 사용하여 카메라가 지원하는 해상도와 프레임레이트를 알 수 있다. 명령어는 아래와 같다.

$ v4l2-ctl -d /dev/video0 --list-formats-ext

결과는 다음과 같이 나왔다.

ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture

	[0]: 'YUYV' (YUYV 4:2:2)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 160x120
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 176x144
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
    ...
    ...
    ...
		Size: Discrete 1024x576
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1184x656
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x960
			Interval: Discrete 0.133s (7.500 fps)
			Interval: Discrete 0.200s (5.000 fps)
	[1]: 'MJPG' (Motion-JPEG, compressed)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
    ...
    ...
    ...
		Size: Discrete 1024x576
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1184x656
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)
		Size: Discrete 1280x960
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.050s (20.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.200s (5.000 fps)

지원하는 해상도가 너무나 다양하므로 중간에 출력된 결과는 일부 생략하였다. 위의 결과를 보면 해당 /dev/video0 카메라의 지원하는 해상도는 160*120 부터 1280*960 까지 확인된다. 또한 각 해상도에 따른 프레임레이트도 확인된다. YUYV는 영상의 비디오 데이터 형식(format)이며 YUV420, YUV422등 색상공간을 나타내는 방법이 다양한데 여기서 설명은 굳이 하지 않는다. 영상의 원시 출력정도로 이해하면 된다. MJPG는 이에 비해 압축 알고리즘을 적용하여 픽셀을 표현한다. MJPG 포맷이 제공하는 프레임레이트(FPS)는 어느정도 고해상도로 올라가면 YUYV의 것보다 높음을 알 수 있다. 예를 들면 YUYV1280*720 해상도에서는 선택할 수 있는 FPS가 5, 7,5 인 반면에 MJPG로 선택하면 최대 30FPS까지 지원된다.

세부 프로퍼티

다시 해당 카메라의 프로퍼티를 보기 위해 v4l2-ctl 명령어와 디바이스를 지정하는 -d 옵션, 그리고 프로퍼티를 보기위한 --all 옵션을 사용한다. 아래의 명령어를 참조하여 실행한다.

$ v4l2-ctl -d /dev/video0 --all

결과는 아래와 같다.

Driver Info:
	Driver name      : uvcvideo
	Card type        : C270 HD WEBCAM
	Bus info         : usb-0000:00:14.0-10.2
	Driver version   : 5.15.131
	Capabilities     : 0x84a00001
		Video Capture
		Metadata Capture
		Streaming
		Extended Pix Format
		Device Capabilities
	Device Caps      : 0x04200001
		Video Capture
		Streaming
		Extended Pix Format
Priority: 2
Video input : 0 (Input 1: ok)
Format Video Capture:
	Width/Height      : 640/480
	Pixel Format      : 'YUYV' (YUYV 4:2:2)
	Field             : None
	Bytes per Line    : 1280
	Size Image        : 614400
	Colorspace        : sRGB
	Transfer Function : Rec. 709
	YCbCr/HSV Encoding: ITU-R 601
	Quantization      : Default (maps to Limited Range)
	Flags             : 
Crop Capability Video Capture:
	Bounds      : Left 0, Top 0, Width 640, Height 480
	Default     : Left 0, Top 0, Width 640, Height 480
	Pixel Aspect: 1/1
Selection Video Capture: crop_default, Left 0, Top 0, Width 640, Height 480, Flags: 
Selection Video Capture: crop_bounds, Left 0, Top 0, Width 640, Height 480, Flags: 
Streaming Parameters Video Capture:
	Capabilities     : timeperframe
	Frames per second: 30.000 (30/1)
	Read buffers     : 0

User Controls

                     brightness 0x00980900 (int)    : min=0 max=255 step=1 default=128 value=128
                       contrast 0x00980901 (int)    : min=0 max=255 step=1 default=32 value=32
                     saturation 0x00980902 (int)    : min=0 max=255 step=1 default=32 value=32
        white_balance_automatic 0x0098090c (bool)   : default=1 value=1
                           gain 0x00980913 (int)    : min=0 max=255 step=1 default=0 value=8
           power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=2 value=2
				0: Disabled
				1: 50 Hz
				2: 60 Hz
      white_balance_temperature 0x0098091a (int)    : min=0 max=10000 step=10 default=4000 value=0 flags=inactive
                      sharpness 0x0098091b (int)    : min=0 max=255 step=1 default=24 value=24
         backlight_compensation 0x0098091c (int)    : min=0 max=1 step=1 default=1 value=1

Camera Controls

                  auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=3 value=3
				1: Manual Mode
				3: Aperture Priority Mode
         exposure_time_absolute 0x009a0902 (int)    : min=1 max=10000 step=1 default=156 value=156 flags=inactive
     exposure_dynamic_framerate 0x009a0903 (bool)   : default=0 value=1

중간 쯤의 User Controls 출력 결과를 보면 다양한 프로퍼티들이 있는데 이들이 컨트롤 가능한 프로퍼티 들이다. 굳이 변경하지 않아도 카메라를 사용하는데 문제는 없지만 본인이 사용할 장비에서 무엇을 통제할 수 있는가를 아는 것은 중요하다. 위의 예시에서는 조절 가능한 프로퍼티는 아래 내용 등과 같다.

  • 밝기(brightness): 최솟값-0, 최댓값-255, 기본값-128, 현재값-128
  • 대조(contrast): 최솟값-0, 최댓값-255, 기본값-32, 현재값-32
  • 채도(saturation): 최솟값-0, 최댓값-255, 기본값-32, 현재값-32\
  • 게인(gain): 최솟값-0, 최댓값-255, 기본값-0, 현재값-8
  • 화이트밸런스 자동설정: 기본값-1, 현재값-1
  • 화이트밸런스(white_balance_temperature): 최솟값-0, 최댓값-10000, 기본값-4000, 현재값-0(자동설정이라 그렇다)

또한 Camera Controls 항목을 보면 카메라의 노출도 조정할 수 있는 것으로 보인다 기본은 자동노출로 되어있지만 이를 수동으로 바꾸면 카메라 프로퍼티 중 노출(exposure)에 대한 값을 조절할 수 있다.

Opencv-python

Property

위에서 알아본 프로퍼티들을 pythonopencv 라이브러리에서 cv2.Videocapture 클래스를 통해 제어한다. 비디오캡처라고 부르는 인스턴스를 통해 해당 클래스가 제공하는 메소드 중 set()get() 메소드를 통해 프로퍼티 값을 조회하고 설정할 수 있다. 이를 통제하기 위해선 opencv 모듈이 제공하는 카메라 프로퍼티의 상수값을 알아야한다. 이는 다음 링크(opencv-videoio flag)를 통해 확인 가능하다. 아래의 이미지만 참고해도 상당히 많은 것을 알 수 있다.

Control

아래의 코드를 참고하여 프로퍼티 값을 조회하고 설정한다. 아래의 예시는 카메라 해상도를 조회하고 설정하는 예시다. 특히 해상도를 그냥 올리면 YUYV 포맷이 유지되어 프레임레이트(FPS)가 낮게 설정되는 경우가 있으니 주의하자. 본인이 지정한 FPS가 YUYV에서도 지원한다면 문제없지만 지원하지 않는다면 명시적으로 데이터 포맷을 MJPG로 바꿔줘야한다.

  • get()
    import cv2
    cap = cv2.VideoCapture('/dev/video0')
    
    w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)   # cap.get(3)
    h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)  # cap.get(4)
    
    print(w, h)
    
    640 480
    

    위의 cv2.CAP_PROP_FRAME_WIDTH 등의 프로퍼티는 상수 값이기 때문의 아래의 3, 4 등의 정수로 입력해도 동작은 동일하다. 이어서 카메라의 기본 해상도가 640*480으로 확인되었고 1280*720으로 올려준뒤 FPS를 확인해본다.

  • set()
    import cv2
    cap = cv2.VideoCapture('/dev/video0')
    
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
    
    fps = cap.get(cv2.CAP_PROP_FPS)   # cap.get(5)
    print(fps)
    
    7.5
    

    1280*720 해상도의 YUYV 포맷은 7.5fps가 기본값이다. 이를 MJPG 포맷의 30FPS로 바꿔주기 위해 아래와 같이 다시 작업한다.

    import cv2
    cap = cv2.VideoCapture('/dev/video0')
    
    vid_fmt = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
    
    cap.set(cv2.CAP_PROP_FOURCC, vid_fmt)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
    cap.set(cv2.CAP_PROP_FPS, 30)
    
    fps = cap.get(cv2.CAP_PROP_FPS)   # cap.get(5)
    print(fps)
    
    30
    

    위와 같이 작성하면 프레임레이트(FPS)가 30이 나오는 것을 확인할 수 있다. cap.set(cv2.CAP_PROP_FPS, 30) 구문을 명시안해줘도 될 수도 있지만 해당 C270카메라의 경우 직접 명시하지 않으면 FPS 기본값이 15로 설정되어있으니 가급적이면 명시를 습관적으로 하는것이 좋다.

해상도나 FPS 뿐 아니라 위에서 알아본 채도, 밝기, 감마 등의 값도 조절 가능하다. 기본값의 사용이 문제가 없다면 일반적으로 변경할 일이 없지만 기본 카메라가 너무 밝다던지, 혹은 카메라 노출을 자동에서 수동으로 변경하여 밝기를 고정한다던지 할 때 유용하게 사용할 수 있다.

아래는 밝기(brightness)를 최소인 0과 최대인 255로 조절해본 결과 이미지의 차이다.

  import cv2
  cap = cv2.VideoCapture('/dev/video0')

  cap.set(cv2.CAP_PROP_BRIGHTNESS, 0)
  print(cap.get(cv2.CAP_PROP_BRIGHTNESS))
  for _ in range(30):
    cap.grab()
  ret, frame = cap.read()
  cv2.imshow('low_brightness', frame)
  cv2.waitKey(0)

  cap.set(cv2.CAP_PROP_BRIGHTNESS, 255)
  print(cap.get(cv2.CAP_PROP_BRIGHTNESS))
  for _ in range(30):
    cap.grab()
  ret, frame = cap.read()
  cv2.imshow('high_brightness', frame)
  cv2.waitKey(0)
  0
  255

중간의 for 구문과 cap.grab()은 카메라의 파라미터를 변경 후 1초 정도 변경값이 적용될 수 있는 시간 여유를 준 것 이라고 이해하면 된다. 적용된 값을 확인하였고 이미지를 출력해본 결과는 다음과 같다.
다른 파라미터들도 동일하게 적용해보고 확인해 볼 수 있으니 사용자의 필요에 맞게 사용하면 된다.

참고링크: Docs: opencv videoio flags

댓글남기기