최근 랩실에서 에어로젤과 관련된 실험을 하고 있습니다. 이때, 온도와 압력이 중요한데, 사용하는 압력계는 디지털이 아니라 아날로그라 시간에 따른 압력을 추적하기가 어려웠습니다. 그래서 인터넷에서 조사를 하던 중, 라즈베리 파이와 OpenCV 라이브러리를 이용하면 아날로그 게이지를 읽을 수 있는 프로그램을 만들 수 있다고 하여, 관련 자료를 아래 글에 정리하기 시작하였습니다.
1.1 문제상황
현재 제가 디지털화를 해야하는 것들은 두 가지입니다; 온도계와 압력계. 온도계의 경우 소수점 한자리를 포함한 4자리 디지털숫자로 표기가 되고 압력계의 경우 원형 아날로그 게이지입니다. 따라서, 현재의 목표는 라즈베리파리와 연결된 카메라를 이용하여 두 물리량을 하나의 사진에 캡쳐를 합니다. 그 후 그 사진을 기반으로 OpenCV를 이용하여 우리가 원하는 물리량을 읽는 것입니다.
1.2. 워크 플로우
2.
아래는 파이썬에서 필요한 모듈들입니다;
▪ `os`:
▪ `glob`:
▪ `cv2`: `OpenCV`의 모듈로 이미지 데이터를 다룰 때 필요
▪ `numpy`:
▪ `pandas`: 구조화된 데이터들을 다룰 때 사용되는 라이브러리
2.1. OpenCV
OpenCV란 Open Computer Vision의 약자로 이미지 프로세싱 분야의 다양한 프로젝트에서 사용되고 있는 강력한 라이브러리 중 하나입니다. OpenCV를 사용하기 위해선, 먼저 (1) 라즈베리 파이에 Linux기반 OS가 설치되어야 하며, (즉, 일반적으로 Raspbian이 이미 라즈베리파이에 기본적인 OS로 설치가 되어있을 것입니다.) (2) 카메라가 라즈베리 파이에 연결이 되어야 하고, (3) OpenCV가 설치되어야 합니다.
▪ 카메라 설정:
1) $ sudo raspi-config
: 터미널에서 해당 명령어를 입력 후, `Interface Options` > `Legacy Camera` > `YES`를 선택하여 카메라 모듈이 가능하도록 설정한 후 재부팅한다.
2) `$ raspistill -o test.jpg`: 카메라가
▪ OpenCV 설치:
1) `$ pip3 install opencv-python`
https://stackoverflow.com/questions/46513323/how-to-read-utility-meter-needle-with-opencv
https://sdsawtelle.github.io/blog/output/automated-gauge-readout-with-opencv.html
https://www.weigu.lu/other_projects/python_coding/read_analogue_gauge/index.html
https://stackoverflow.com/questions/46513323/how-to-read-utility-meter-needle-with-opencv
3. Python 코드
만약 여기까지 왔다면, 이제 남은 일은 파이썬 코드를 작성 후 이 코드가 정상적으로 작동하는지를 확인하는 것입니다.
3.1. 원형 게이지 읽기
원형 게이지를 읽기 위해선 OpenCV를 통해 크게 두 가지 작업을 해야합니다
▪ 원형 게이지의 경계를 찾는 것
▪ 니들(needle)의 중심과 끝 점을 찾는 것
원형 게이지의 경계를 찾는 것: OpenCV는 이미지에서 원을 찾을 때, "Hough Circle Transform"이라는 것을 사용합니다[1]. 알고리즘에 대한 자세한 설명은 [1]을 참조하시길 바랍니다. 일반적으로 경계를 찾기 위해선 다음과 같은 단계를 거칩니다.
(1) 이미지를 `cv2` 모듈의 `imread`를 이용하여 불러오기
- `cv2.imread()`: https://docs.opencv.org/3.4/d4/da8/group__imgcodecs.html#
(2) 해당 이미지를 `cv2` 모듈의 `cvtColor`를 사용하여 회색으로 변환
(3) 변환된 이미지에서 `HoughCircles`을 사용하여 원들의 x,y 좌표와 반지름을 찾기
- 이 단계에서는 파라미터들을 조절하면서 최적화된 파라미터들을 찾아야 한다.
- `HoughCircles`: https://docs.opencv.org/3.4/dd/d1a/group__imgproc__feature.html#
NOTE: `HoughCircles`의 매개변수들: `HoughCircles(image, method, dp, minDist, circles, param1, param2, minRadius, maxRadius)`
▪ `image`: `HoughCirlces()` 에 입력되는 이미지 (단, 그레이스케일이여야 함)
▪ `method`: 현재 opencv에서 사용할 수 있는 방법은 `cv2.Hough_GRADIENT`만 가능
▪ `dp`: 감지하는 원의 중심위치의 해상도를 조절하는 매개 변수
- `dp=1`이면 입력 이미지와 동일한 해상도로 원을 감지, `dp=2`이면 해상도가 절반으로 감소
▪ `minDist`: 감지된 원들의 최소 거리
- 해당 값을 너무 작게 설정할 경우, 여러 원들이 중복될 수 있음
- 해당 값이 너무 클 경우, 일부 원이 감지되지 않을 수 있음
▪ `circles`:
▪ `param1`: 엣지검출에서 사용하는 Canny 엣지 검출기의 임계값
▪ `param2`: 중심과 반지름을 결정하는데 사용하는 임계값
- 값이 작을수록 더 많은 원들이 감지
▪ `minRadius`: 감지할 원의 최소 반지름
▪ `maxRadius`: 감지할 원의 최대 반지름
3.2. 눈금 읽기
게이지의 눈금을 읽는 것 역시 3.1에서 소개한 것처럼 Hough 알고리즘을 기반으로 한다. 이때 사용되는 openCV의 함수는 `HoughLinesP()`라는 함수이다. 함수에 대한 자세한 설명은 아래 레퍼런스[4]를 참고하면 된다.
3.2.1. `HoughLinesP(dst, rho, theta, threshold, minLineLength, maxLineGap)` 파라미터 설명
▪ `dst`: Hough 알고리즘을 적용할 이미지. (단, 이미지는 반드시 gray scale이어야 한다.)
▪ `rho`: 파라미터 r의 해상도
▪ `theta`: 각도 $\theta$의 해상도 (Radian 단위)
▪ `threshold`: 하나의 선을 검출하기 위한 교점의 최소 갯수*
▪ `minLenLength`: 하나의 선을 형성하기 위한 점들의 최소 갯수
▪ `maxLineGap`: 같은 선으로 고려가 되는 두 점 사이의 최대 간격
* `threshold`가 증가할수록 하나의 선을 정의하기 위해 더 많은 점들이 필요하므로, 결과적으로 적은 갯수의 선들이 검출된다.
[1] https://docs.opencv.org/3.4/d4/d70/tutorial_hough_circle.html
[2] https://docs.opencv.org/3.4/d9/db0/tutorial_hough_lines.html
[3] https://www.weigu.lu/other_projects/python_coding/read_analogue_gauge/index.html
[4] https://docs.opencv.org/3.4/d9/db0/tutorial_hough_lines.html
3.2. 디지털 숫자 읽기
[1] https://github.com/intel-iot-devkit/python-cv-samples/tree/master/examples/analog-gauge-reader
'컴퓨터 & IT (Computer & IT) > Raspberry pi 3' 카테고리의 다른 글
[Rasberry pi] 라즈베리 파이를 이용한 서버실 온도 체크 (0) | 2021.07.28 |
---|---|
라즈베리파이를 노트북과 내부망으로 연결하고 노트북 와이파이를 통해 인터넷 연결하는 방법 (12) | 2020.11.03 |
댓글