개요
WSL
내 우분투 OS에서 컴퓨터 비전 관련 프로젝트를 테스트해 볼 일이 있어 작업 중 기본적으로는 WSL 내에서 노트북에 내장된 카메라 혹은 USB로 연결 된 장비를 사용하지 못한다는 것을 알았다. 아예 사용을 못하는 것은 아니고 어찌저찌 장비의 연결을 넘겨주고 WSL의 리눅스 커널을 USB 장치등을 사용할 수 있게 재 빌드해주고 커널을 교체해주면 사용할 수 있는 방법이 있다는 것을 보고 직접 수행해보았다. 결론은 뭔가 될 것 같음에 거의 도달한 것 같은데 최종적으로는 뭔가 제대로 작동하지 않는다.
환경
- Samsung Galaxy book 2 pro 360
- windows 11
- WSL2 Ubuntu 20.04
- Linux 5.15.90.1-microsoft-standard-WSL2
- Linux Kernal 5.10.60.1 이상 필요
usbipd install
Windows 에서
WSL의 리눅스 배포판이 아닌 호스트 Windows OS에서 우선 usbipd
프로그램을 설치한다.
Releases 페이지에 있는 .msi
파일을 통해 설치한다.
WSL2 에서
WSL 터미널로 들어가 Ubuntu 20.04 os 내에서 리눅스 사용자 도구 및 하드웨어 식별자 도구를 설치한다.
$ sudo apt install linux-tools-5.4.0-77-generic hwdata
$ sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/5.4.0-77-generic/usbip 20
usb 장치 확인
Windows 터미널을 열고 아래와 같이 명령어를 실행한다. 실행 된 결과로 Windows에 연결된 USB 버스를 통해 연결된 장치가 출력된다.
$ usbipd wsl list
>>>
BUSID VID:PID DEVICE STATE
2-5 1c7a:0582 EgisTec Touch Fingerprint Sensor Not attached
2-6 1bcf:2d05 1080p FHD Camera Not attached
2-10 8087:0033 인텔(R) 무선 Bluetooth(R) Not attached
6-1 046a:0077 USB 입력 장치 Not attached
6-5 2109:8817 USB Billboard Device Not attached
7-4 0bda:8152 Realtek USB FE Family Controller Not attached
위의 결과와 같이 노트북의 터치센서, 내장카메라, 블루투스 장치. USB 키보드 등의 여러 장치들이 보인다. 그리고 STATE
는 Not attached
라는 것을 확인할 수 있다.
장치 연결
위에서 각 usb장치의 busid
를 확인하였고 다음의 명령어를 통해 windows 터미널에서 wsl2 의 리눅스 배포판으로 장치를 연결해줄 수 있다.
# usbipd wsl attach --busid {busid}
$ usbipd wsl attach --busid 2-6
WSL에서 확인
WSL 의 리눅스 배포판으로 들어와 lsusb
명령어를 통해 연결해준 장비를 확인할 수 있다.
$ lsusb
>>>
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 1bcf:2d05 Sunplus Innovation Technology Inc. 1080p FHD Camera
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
위의 결과에서 Bus 001 Device 004
장비는 attach
작업을 해주기 전에는 보이지 않던 장비로 이제 인식이 되는 모양이다.
장치 연결 해제
WSL
내에서 장치를 다 사용했다면 attach
시와 마찬가지로 detach
명령어를 통해 장치를 다시 연결 해제할 수 있다.
# usbipd wsl detach --busid {busid}
$ usbipd wsl detach --busid 2-6
장치 사용 불가
위의 작업만으로는 lsusb
명령어 입력 시 인식된 장치에 출력은 되나 문제는 따로 있다.
/dev
파티션에 대해서 아무리 ls
명령어를 입력해봐도 /dev/video0
등의 카메라 장치가 인식되지 않는다. 혹은 꼼수를 피워 장치명이 Bus 001 Device 004
인것을 착안하여 /dev/bus/usb/001/004
로 접근해볼 수도 있으나 python3
및 opencv
모듈을 통해 카메라를 열어봐도 전혀 작동하지 않았다.
import cv2
# try 1
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
# fail to read frame
# try 2
cap = cv2.VideoCapture('/dev/bus/usb/001/004')
ret, frame = cap.read()
# fail to read frame
아래의 기술할 리눅스 커널 빌드 및 교체 내용을 통해 해결을 시도해보았다.
Linux Kernel Build and replace
패키지 설치 및 커널 버전 확인
WSL 터미널에서 다음 명령어를 통해 커널 빌드에 필요한 패키지를 설치하고 현재 설치되어 있는 커널 버전을 확인한다.
$ sudo apt install -y build-essential flex bison dwarves libssl-dev libelf-dev bc libncurses-dev
$ uname -a
>>> Linux DONGLE-BOOK2 5.15.90.1-microsoft-standard-WSL2 #1 SMP Fri Jan 27 02:56:13 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
uname
명령어의 실행 결과를 보면 일단 커널 버전은 5.15.90
인 것을 알 수 있고 빌드 시기는 2023년 2월 27일 임을 알 수 있다.
커널 소스 다운로드
해당 버전의 리눅스 커널을 빌드하기 위해 커널 소스를 내려받는다.
$ wget https://github.com/microsoft/WSL2-Linux-Kernel/archive/refs/tags/linux-msft-wsl-5.15.90.1.tar.gz
$ tar zxf linux-msft-wsl-5.15.90.1.tar.gz
$ cd WSL2-Linux-Kernel-linux-msft-wsl-5.15.90.1
커널 빌드 설정
커널을 빌드하기 위해 옵션 파일을 옮겨주고 적절한 설정을 잡는다.
$ sudo cp /proc/config.gz ./
$ gunzip config.gz
$ mv config .config
설정을 바꿔준다. 기존에 하위 메뉴가 없던 것은 스페이스바를 눌러 *
로 설정을 바꾸고 나면 하위메뉴로 들어갈 수 있게 바뀌는 경우가 있다.
$ make menuconfig
- Device Driver
enter
로 진입하여 Multimedia Support<*>
로 변경 - Multimedia Support
enter
로 진입- Filter media drivers
[*]
로 변경 - Media device types
enter
로 진입하여 Cameras and video grabbers[*]
로 변경 - Video4Linux options
enter
로 진입하여 V4L2 sub-device userspace API[*]
로 변경 - Media drivers
enter
로 진입하여 Media USB Adapters[*]
로 변경 - Media USB Adapters
enter
로 진입- USB Video Class (UVC)
<*>
로 변경 - GSPCA based webcams
<*>
로 변경
- USB Video Class (UVC)
- Filter media drivers
<save>
를 해주고 지속 적인 <exit>
선택을 통해 설정을 마친다.
커널 빌드
아래의 명령어를 통해 커널을 빌드한다. 빌드에 들어가는 cpu 코어 수는 최대로 땡겨왔지만 다른 작업과 동시에 한다면 사양을 생각해서 적절히 넣자.
$ make -j$(nproc)
...
...
Kernel: arch/x86/boot/bzImage is ready (#1)
빌드가 끝나면 현재 경로에 vmlinux
라는 파일이 생성된 것을 볼 수 있다. 해당 파일을 우선 wsl
저장공간이 아니라 windows os
에서 참조할 수 있는 경로에 복사 혹은 이동 시킨다. 이름을 어떻게 해도 상관없다.
$ cp vmlinux /mnt/c/Users/dongle94/wsl-kernel
WSL 종료 및 빌드 된 커널 적용
우선 wsl
을 아래와 같이 종료한다. 기존 wsl 내에서 하던 작업은 잘 정리하여 exit
으로 나오고 windows 터미널에서 실행한다.
$ wsl --shutdown
.wslconfig 유저경로에 적용
wsl의 글로벌 설정을 적용하여 커널의 경로를 인식하도록 특정 경로에 .wslconfig
라는 파일을 만들어야한다. 메모장으로 만든뒤 확장자를 없애줘도 되고 다른 텍스트 에디터를 통해 생성해도 된다.
아래 내용을 참고하여 적고 파일을 저장하자.
# PATH: C:\\Users\\dongle94\\.wslconfig
[wsl2]
kernel=C:\\Users\\dongle94\\Kernels
WSL 시작 및 확인
다시 WSL을 실행시켜 적용된 커널을 확인해보자. 다음의 명령어로 확인가능하다.
$ uname -a
>>> Linux DONGLE-BOOK2 5.15.90.1-microsoft-standard-WSL2 #1 SMP Mon May 15 18:57:55 KST 2023 x86_64 x86_64 x86_64 GNU/Linux
빌드 된 커널의 버전은 같지만 처음과는 다르게 빌드된 시각은 5월 15일로 찍혀있어서 정상적으로 교체된 것을 확인할 수 있다. 이 상태에서 해당 포스팅의 앞에 언급했던 usbipd
를 통한 장치 버스 연결을 해주면 내장 카메라 등의 장치가 정상 사용할 수 있음을 확인할 수 있다.
Windows 터미널에서
$ usbipd wsl list
>>>
BUSID VID:PID DEVICE STATE
2-5 1c7a:0582 EgisTec Touch Fingerprint Sensor Not attached
2-6 1bcf:2d05 1080p FHD Camera Not attached
2-10 8087:0033 인텔(R) 무선 Bluetooth(R) Not attached
6-1 046a:0077 USB 입력 장치 Not attached
6-5 2109:8817 USB Billboard Device Not attached
7-4 0bda:8152 Realtek USB FE Family Controller Not attached
$ usbipd wsl attach --busid 2-6
WSL 터미널에서
$ ls /dev/video*
>>>
/dev/video0 /dev/video1
최종 작동 불가 확인
python
기반의 cv2
라이브러리 혹은 우분투의 cheese
어플리케이션을 통해 노트북에 내장된 카메라의 영상을 받아와 그릴 수 있는지 확인해보았다.
import cv2
def main():
cap = cv2.VideoCapture('/dev/video0')
while True:
ret, frame = cap.read()
if not ret:
break
cv2.imshow('Camera', frame)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
위의 코드 실행 시 내장 카메라의 작동여부를 알리는 불은 들어오나 read()
메소드가 프레임을 정상적으로 가져오지 못하였다. ret
변수의 값은 False
였다.
VideoCapture()
인스턴스의 비디오를 가져오는 방식을 VideoCapture('/dev/video0', cv2.CAP_V4L)
, VideoCapture('/dev/video0', cv2.CAP_FFMPEG)
등으로 바꿔본 결과 비디오캡처 객체가 영상을 가져올 때 타임아웃 에러를 일으킨 다는 것을 일부 확인할 수 있었는데 왜 정확히 못가져오는지 좀 더 연구가 필요하다.
cheese
어플리케이션으로 카메라를 실행해보려하니 터미널 에러에는 인덱스 기반의 카메라 디바이스 이름을 가져올 수 없다는 alert가 발생하면서 장치를 찾을 수 없다는 이유로 정상적인 실행이 되지는 않았다.
댓글남기기