먼저 webcam으로 camera calibration을 해야 합니다.

 

 

웹캠으로 50장 정도의 사진을 찍었고 calibration을 시도하였습니다.

그런데 calibration을 해야 하는데 사진이 왜 다 인식할 수 없다고 하는지 모르겠네요.

 

sparo1@sparo1:~/catkin_ws/src/aruco/src/image_web$ python cameracalibration.py --image_dir ~/catkin_ws/src/aruco/src/image_web --image_format png --prefix opencv_frame* --square_size 25 --width 8 --height 6 --save_file ~/test/image_web/ost1.yaml

 

이 오류는 알고 보니 *를 빼면 되는 거였습니다. 코드상에서 *을 넣어줬기 때문에 **이렇게 겹쳐져서 안됐던 거 같아요. 그런데 realsense calibration 할 때는 *을 넣어도 됐었는데 왜 지금은 안 되는 것일까요...

 

calibration 한 결과입니다.

%YAML:1.0
---
K: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 4.9350028035371434e+02, 0., 3.1889472537064762e+02, 0.,
       4.9752379240241839e+02, 2.3323580951832940e+02, 0., 0., 1. ]
D: !!opencv-matrix
   rows: 1
   cols: 5
   dt: d
   data: [ 1.3514513045692980e-01, -4.8663060594638929e-01,
       6.3572242938879548e-04, 5.6972282484044220e-04,
       5.4433200932025450e-01 ]

 

ArUco 마커 만드는 사이트 입니다.

https://chev.me/arucogen/

 

x, y, z 축 띄우는 거 까지 성공했는데 이제는 translation vector가 맞지 않는 거 같네요.

줄자로 z 축을 20cm거리 에서 쟀는데 행렬에는 0.03m 라고 뜨네요 이건 캘리브레이션 문제일까요?

 

 

 

x축 : 빨간색

y축 : 초록색

z축 : 파란색

 

 

 

이유를 찾았습니다. 알고 보니 마커의 길이를 안 맞춘 거였더라고요... 코딩의 길은 멀다...

 

이제 파이썬으로 짠 코드를 ros에서 돌아가도록 하려고 하는데요. numpy가 왜 없다고 뜨는 걸까요..

numpy tutorial을 실행시켰을 때는 되는데 제 코드를 실행시키니까 안 되는 이유가 뭘까요

 

알고 보니 모든 import 가 다 안되는 거였더라구요. 뭐가 문제일까요

 

 

위 오류는 알고보니 코드에서 띄어쓰기를 잘못한 거였더라고요.. 오류가 뜨면 무조건 코드 띄어쓰기부터 봐야 될 거 같아요. import 에러는 package가 없다고 뜨지 저렇게 뜨지 않는다고 합니다.

 

다음 블로그

2021.06.23 - [ROS] - 마커 인식한 후 로봇 위치 인식, 조정하기

 

*참고

웹캠으로 사진 찍기 : 

https://stackoverflow.com/questions/34588464/python-how-to-capture-image-from-webcam-on-click-using-opencv

camera calibration 코드 :

https://aliyasineser.medium.com/opencv-camera-calibration-e9a48bdd1844

aruco marker generator :

https://chev.me/arucogen/

이전 블로그

2021.06.30 - [ROS] - Webcam으로 Aruco 마커 인식하기

 

마커를 인식했으면 카메라로부터 마커의 위치를 알 수 있습니다.

그럼 이를 반대로 하여 카메라의 위치도 알 수 있죠.

제가 해볼 것은 로봇이 마커를 인식하면 마커를 정면으로 바라보도록 위치시키는 것입니다.

 

마커를 정면으로 보도록 하려면 어떤 조건이 필요할까요

먼저 x좌표가 원점과 최대한 가까워야 하고 마커의 x축과 카메라의 x축이 평행해야 한다고 생각합니다.

 

정면을 볼뿐만 아니라 마커와 어느 정도 가까워지도록 해야 하기 때문에 z좌표도 정해주겠습니다.

 

로봇이 마커를 찾으면 마커의 위치를 알 수 있는데 로봇 입장에서는 로봇이 마커를 찾으면 마커로부터 로봇이 어느 정도 위치에 있는지 알 수 있습니다. 그 위치를 어떻게 뽑아낼 수 있을까요

 

로봇의 위치를 알고 조종한다는 것은 x좌표가 0이면 로봇이 정면이다 이게 아니라 x좌표가 0이 될 때까지 로봇이 움직여야 한다입니다.

 

로봇의 rotation vector와 translation vector를 출력하고 translation의 x좌표인 첫 번째 숫자가 0.01m 사이에 카메라가 들어오면 --------------를 출력하도록 하였습니다.

 

 

**x좌표를 출력할 때 발생한 오류**

tvec 행렬을  tvec.shape 하면 1x1x3 행렬이라고 떠서 그냥 tvec [0]을 출력하라고 하니까 출력되지 않았던 것입니다.

tvec [0][0][0]으로 행렬을 맞춰주니까 잘 나오네요.

 

 

이제는 0점 가까이에 위치할 수 있도록 로봇이 움직여야 될 방향을 알려주기 위해 화살표를 그려보도록 하겠습니다.

 

 

빨간색이 x 축인데 x축의 원점이 카메라의 왼쪽으로 치우쳐져 있으면 왼쪽 화살표를 오른쪽으로 치우쳐져 있으면 오른쪽 화살표를 그리도록 하였습니다.

 

위 과정은 ros환경이 아닌 python코드를 사용한 것으로 제대로 ros를 사용하고 있지는 않았어요.

그럼 ros환경에서 마커를 인식해보겠습니다.

과정은 usb camera를 이용해서 ros img를 받아오고 cv.bridge를 통해 opencv이미지로 변환하여 마커를 인식하는 것입니다.

 

먼저 아래 명령어로 usb camera를 깔아야 합니다.

 

sudo apt-get install ros-melodic-usb-cam

 

그다음 아래 명령어를 통해 usb cam을 실행시켜 subscriber에 사용할 토픽 이름을 찾습니다.

 

$ rosrun usb_cam usb_cam_node

 

**usb cam 실행 오류**

 

 

위 오류는 다음 과정으로 해결할 수 있습니다.

 

$ ls -al
$ sudo umount /home/사용자계정/.gvfs
$ sudo chmod 777 .gvfs

 

위 명령어들을 실행시킨 후 다시 rosrun을 실행시키면 실행될 겁니다.

 

 

rqt_graph로 topic을 확인한 결과입니다.

 

rqt_image_view를 이용하여 화면이 제대로 실행이 되는지 확인해보겠습니다.

 

 

상단에 적힌 /usb_cam/image_raw를 subscriber의 topic으로 받아오면 됩니다.

 

먼저 usb cam으로 rospy를 써서  image를 받아오는 거 먼저 해보겠습니다.

아래 코드로 usb cam을 설치합니다.

 

$ sudo apt-get install ros-melodic-usb-cam

 

다음으로 할 거는 이미지를 불러와서 현재 코드에서 videocapture와 while문을 사용하지 않고 cvbridge로 opencv를 작동시키는 것입니다. cvbridge는 아래 그림과 같은 역할을 합니다.

 

 

ros image를 불러와서 opencv와 연결할 수 있도록 도와줍니다.

 

먼저 cvbridge를 이해하기 위해서 roswiki에 있는 예제를 실행시켜보려고 합니다.

roswiki 사이트 : http://wiki.ros.org/cv_bridge/Tutorials/ConvertingBetweenROSImagesAndOpenCVImagesPython

catkin_make에서 opencv2 오류가 발생해서 cvbridge 예제를 못하고 있는 중입니다...

 

 

opencv2의 path를 찾지 못해서 나는 오류라고 하는데 버전은 있으면서 package는 왜 없는지 모르겠네요..

먼저 제가 가지고 있는 opencv버전이 무엇인지 확인해보았습니다.

 

 

예제에서 패키지를 만들 때 의존성으로 opencv2를 사용하라고 했는데 제가 가지고 있는 것은 그냥 opencv였습니다.

 

 

제 노트북에 있던 opencv폴더의 이름이 OpenCV였기 때문에 CMakeLists.txt 파일에 의존성 이름을 아래와 같이 바꾸니까 catkin_make오류는 이제 뜨지 않네요. opencv2 오류가 완벽하게 해결된 건지는 모르겠습니다.

 

 

**또 다른 오류 해결법**

알고 보니 wiki사이트 맨 아래에 kinetic 버전 이후로는 의존성 패키지에 opencv를 빼도 된다고 적혀있더라고요.

안 적어도 실행이 됩니다!  저는 나중에 발견했네요ㅠㅠ

 

 

코드를 작성할 때는 publisher로 rospy를 import 하여 이미지를 받아오고 subscriber의 callback 함수에서 원래 있던 코드의 while 문을 실행시키면 됩니다.

 

 

cv_example.py 코드를 실행시켰을 때 이렇게 나왔는데 제대로 나온 건지 잘 모르겠네요.

위 rqt_graph는 카메라 노드를 실행시키지 않았을 때입니다.

 

 

실행시키니까 위처럼 print 하라고 한 거만 뜨고 실행이 되지 않길래 뭔가 싶었는데 topic을 잘못 적었더라고요.

바꾸고 나니까 node가 하나로 나오는데 이걸 publisher랑 subscriber각각 다른 이름으로 나오게 하고 싶은데 그리고 converter는 중간에 있어야 하는 게 아닌가 싶은데 어떻게 하는 걸까요

 

 

코드에서 rospy.init_node()는 노드의 이름을 한 번만 지정할 수 있게 해 주더라고요. 만약 여러 노드를 쓰려면 코드를 나눠서 실행을 해야 할 거 같아요. 그럼 주는 거 이름을 publisher로 하고 받는 거 이름을 subscriber로 하면 converter는 어디에 들어가야 하는 걸까요.. 

 

제가 아예 publisher와 subscriber 개념을 이해를 잘못하고 있었던 것 같아요.

굳이 코드를 나눌필요도 없고 한 코드에서 실행하면 되는데 주는 노드가 usb cam이니까 publisher는 이름이 usb cam으로 정해져 있고 받는 노드의 이름만 지정해주면 되는데 그것이 image_converter였습니다.

 

cv_example 코드를 실행시켜보려고 하는데 왜 카메라 창이 뜨지 않는 걸까요.

cv2.imshow 에서 잘못 불러온 건가

 

위 오류는 callback 함수 자체를 못 들어가는 거였습니다. 실수로 camera node를 안 키고 실행시켰더라고요ㅋㅋㅋㅋ

그런데 callback함수에 들어가고 나서 또 오류가 발생했는데 이는 CompressedImage에서 Image로 import를 바꿔주니까 해결이 됐습니다.

 

 

잘못된 영상

 

ros 이미지를 opencv이미지로 전환하여 영상을 내보내도록 하였는데 왜 이렇게 영상이 끊기는 걸까요

토픽을 받아오는데 시간이 걸려서 그런가

아래 그림은 위 영상처럼 나타날 때의 rqt_graph입니다.

 

 

해결 완료!

 

오류 해결한 영상

 

publisher 랑 subscriber에 토픽 이름이 같아서 그런 거였습니다.

받아오는 이미지가 같으니까 보여주는 이미지가 시간차로 계속 끊겨서 보이는 거죠

publisher 이름은 그냥 내 마음대로 지으면 되는 거였습니다. 받아오는 subscriber 이름만 카메라 토픽으로 써주면 되는 거였어요

 

 

이거였습니다! 이미지 변환 성공!!

 

그럼 이제 실시간 영상에서 마커 인식을 해보겠습니다.

 

 

마커 인식하는 코드와 이미지 변환해주는 코드를 합쳐서 ros 환경에서 마커 인식을 하였습니다.

 

 

그런데 로봇이 정면을 보고 있을 때 화살표를 표시하고 싶은데 위 영상을 보면 정면을 보지 않아도 화살표 방향을 표시하는 것을 볼 수 있습니다. 정면을 보도록 하고 싶으면 어떻게 해야 할까요... 축을 평행하게 만드는 방법이 뭘까요

방법은 마커의 xy평면과 카메라의 xy평면을 평행하도록 하는 것입니다.

블로그 맨 아래 질문란에 자세히 적혀있습니다.

 

 

rvec 행렬에 값 순서대로 x, y, z 축으로 얼마만큼 회전했는지 라디안 각도를 의미합니다.

마커의 x축이 180도 돌면 마커의 xy평면과 카메라의 xy평면이 평행하게 됩니다.  이를 조건으로 사용하여 rvec의 0번 값은 3~3.2 사이로 오고 1번 값은 0~0.02 사이로 오도록 하고 tvec에 x, y 값이 0에 가까우면 정면을 보는 것으로 인식하고 'front'라고 출력하도록 하였습니다.

카메라가 로봇에 부착될 것이기 때문에고 rvec에 z는 0도와 가까울 것으로 생각하여 조건을 넣지 않았습니다.

 

다음으로 할 것은 마커의 위치로부터 카메라의 위치를 구해야 합니다.

-회전구하기

  1. 구한 rvec(회전벡터)를 cv2.Rodrigues 함수를 이용하여 회전행렬로 만들기 

  2. 그 행렬의 역행렬 구하기(전치)

  3. 마커에 대한 카메라의 회전 구하기 완료

 

-위치구하기

  1. 마커의 회전행렬과 위치벡터를 이용하여 4x4 동차변환행렬을 만들기

  2. 역동차변환행렬 구하기

  3. 그 중에 위치벡터만 뽑아오기

 

다음은 마커인식에 성공한 영상입니다.

 

https://youtu.be/D2ihFEbgVBo

 

이것은 제가 사용한 소스코드입니다.

https://github.com/yehjin00/ArUco-marker-detection

 

yehjin00/ArUco-marker-detection

Contribute to yehjin00/ArUco-marker-detection development by creating an account on GitHub.

github.com

 

주로 공장에서 로봇을 사용할 때 마커 인식을 통해 로봇의 위치를 인식하도록 하는데요. 그럼 공장 내부 곳곳에 마커가 부착되어있어야 하는데 마커의 크기가 크면 보기 싫지 않을까요? 저는 여 러크기의 마커를 부착한 후 카메라와의 거리에 따라 변화하는 인식 정도를 알아보았습니다.

 

마커의 크기를 줄이거나 카메라와의 거리를 멀게 하여 언제 마커가 가장 잘 인식이 되는가를 보았습니다.

이때까지 위에서 사용한 마커의 크기는 100mm였습니다.

 

아래 측정에 사용된 마커 정보입니다.

 

마커 번호 : 100

마커 크기(mm) : 10, 30, 50

 

마커 크기가 100일 때는 상당히 먼 거리에서도 인식이 가능한 것을 확인하였습니다.

10일 때는 25cm 정도까지, 30일 때는 60cm 정도까지, 50일 때는 100cm 정도까지 인식은 가능한데 좌표축이 엄청 작게 나왔습니다.

측정 결과 거의 마커 크기에 두배 정도 거리까지 인식이 가능한 것 같습니다.

크기 10mm 거리 25cm                                               크기 30mm 거리 60cm                                        크기 50mm 거리 100cm   

 

거리가 멀어졌을 때 인식률을 확인해 봤으니까 다음으로 거리가 어느 정도 이상 가까워지면 인식이 되지 않는지 확인해 보겠습니다.

10일 때는 4cm 30일 때는 4cm로 거의 동일하게 나왔는데요.

가까운 정도는 창안에 마커가 다 들어오면 되는 거라서 로봇이 마커에 아예 밀착하지 않는 이상 웬만하면 마커를 인식할 수 있을 것 같습니다.

 

마커의 크기는 카메라를 로봇에 부착해본 후 마커를 발견하고 로봇이 마커를 정면으로 바라보기까지 움직일 수 있는 반경을 고려해서 정해야 할 것 같습니다.

 

마커에 대해 더 찾아보고 현재 사용되는 마커는 어떤 것 이 있는지 왜 그 마커가 사용되는지 등등 여러 장단점을 비교해 본 후 어떤 마커를 쓰는 것이 가장 좋을지 조사해보겠습니다.

 

또한 카메라의 위치도 고민을 해봐야 합니다.

로봇의 전면부가 어떤 축인 지 확인한 후 그 축에 카메라를 설치할 경우 오랫동안 마커를 볼 수 있습니다.

그 위치가 가장 좋은 위치 아닌가 생각합니다.

 

마커를 인식한 후 로봇이 움직이도록 해보겠습니다.

먼저 웹캠에서 마커의 위치를 뽑아내서 토픽으로 내보내보겠습니다.

orientation : 방향

 

 

 

아래 영상은 뽑아낸 위치를 이용해 마커와 카메라사이 거리와 축의 각도를 토픽으로 알려주는 것 입니다.

 

 

 

마커를 인식했으니 그 위치를 이용해 속도를 publish해서 로봇을 움직여 보겠습니다.

로봇은 실행시키지 않고 realsense로 마커를 인식하라고 했을 때 입니다.

 

 

 

로봇을 실행시켜본 결과 아래 두 영상과 같이 나왔는데 각도값을 변경하거나 축이 맞는지 다시 봐야할 것 같습니다.

5x5 사이즈의 마커를 인식하고 마커와 로봇이 정면을 보도록 cmd_vel를 publish한 결과입니다.

 

 

 

 

4x4 사이즈의 마커를 인식했을때 입니다.

 

 

 

위 launch를 실행했을때 rqt_grpah입니다.

 

 

카메라가 마커를 인식했을 때 반대로 움직이는 것을 확인한 후 로봇의 z축값에 마커로부터 구한 angle그대로의 값을 넣은 것이 아니라 -angle로 넣어봤습니다.

또한 저는 로봇과 마커사이를 본 것이 아니라 카메라에서 본 마커의 위치를 이용해 거리와 각도를 계산했습니다.

그랬더니 위 오류를 해결할 수 있었습니다. 이와 관련된 영상은 아래에 있습니다.

 

마커를 문에 붙이지 않고 마커가 움직이면 로봇이 따라가도록 해보았습니다.

 

 

 

 

마커가 멀리있을때, 각이 클때 로봇이 조금더 빨리 움직이도록 하였고 마커와 카메라사이 거리가 10cm정도 떨어지게되면 더이상 가까이 오지않도록 하였습니다.

 

줄자로 재봤을때 실제로 10cm 떨어져있는지 확인한 후 다시 글을 쓰도록 하겠습니다....

 

영상이 어두워지면 마커를 인식하지못해서 이를 HE(histogram equalization)을 통해 이미지대조비를 높혀서 인식률을 높여보았습니다.

제가 사용한 것은 CLAHE (Contrast Limited Adaptive Histogram Equalization)입니다.

HE를 사용하면 이미지전체가 밝아져서 영상이 잘 안보이는 부분이 발생할수있기때문에 CLAHE를 사용하여 clip limit(histogram의 높이를 제한하는 값)값이상이 되는 부분만 밝게 하는 방법을 사용했습니다.

 

이는 계산시간이 길다는 단점이 있는데 얼마나 느린지, 인식속도에 문제가 없는지 확인해보겠습니다.

 

 

질문

Q1. import image 랑 compressedimage 랑 차이점?

A1. compressed 가 압축한다는 뜻인데 받아오는 이미지를 압축해서 쓸 것인지 그대로 쓸 것인지 묻는 것입니다. 카메라가 여러 대여서 받아와야 하는 이미지가 많고 용량이 크다면 압축을 해서 풀어서 사용하는 경우가 있는데 저는 카메라가 한대라 image를 셔요 하였습니다. compressed 이미지를 토픽으로 받아왔는데 엔코딩이 잘못됐다는 오류가 떴었는데 해결하는 방법은 더 찾아봐야 할 것 같습니다.

 

Q2. CmakeList에 의존성으로 opencv2를 사용하라고 했는데 가지고 있는 것이 opencv라서 그냥 opencv를 사용하였는데 같은 건가요?

A2. 예전 버전이 아마 opencv2일 텐데 그냥 opencv를 써도 상관없습니다.

 

Q3. 지금은 x축 원점에 가까워졌을 때만 방향을 표시하였는데 정면을 보지는 않습니다. 카메라를 정면으로 보게 만들고 싶으면 어떤 조건이 들어가야 할까요?

A3. 정면을 보려면 마커의 xy평면과 카메라의 xy평면이 평행하다는 조건을 넣어줘야 하는데 이는 rvec 값을 조정하면 됩니다. 정면을 보고 싶을 때 마커가 카메라의 중앙에 왔으면 할 때 rvec를 (3.14 , 0, 0)로 만들어 주고 tvec를 (0,0, z)로 만들어 주면 됩니다. rvec는 라디안 값입니다. (좌표의 부호는 상관없습니다.)

 

 

참고 코드

https://deepdeepit.tistory.com/118

http://wiki.ros.org/rospy_tutorials/Tutorials/WritingImagePublisherSubscriber

http://wiki.ros.org/cv_bridge/Tutorials/ConvertingBetweenROSImagesAndOpenCVImagesPython

https://blog.daum.net/pg365/295

 

'ROS' 카테고리의 다른 글

Ros melodic 설치방법  (0) 2021.12.02
Webcam으로 Aruco 마커인식하기  (0) 2021.06.30
Realsense로 camera calibration하기(2)  (0) 2021.05.21
Realsense 카메라로 Aruco 마커인식하기  (0) 2021.05.13
Kobuki 실행해보기  (0) 2021.04.28

아래 코드는 camera calibration을 하기위한 코드입니다.

 

#!/usr/bin/env python3
#!/usr/bin/env python2

import numpy as np
import cv2
import glob
import argparse


# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)


def calibrate(dirpath, prefix, image_format, square_size, width=9, height=6):
    """ Apply camera calibration operation for images in the given directory path. """
    # prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(8,6,0)
    objp = np.zeros((height*width, 3), np.float32)
    objp[:, :2] = np.mgrid[0:width, 0:height].T.reshape(-1, 2)

    objp = objp * square_size

    # Arrays to store object points and image points from all the images.
    objpoints = []  # 3d point in real world space
    imgpoints = []  # 2d points in image plane.

    if dirpath[-1:] == '/':
        dirpath = dirpath[:-1]

    images = glob.glob(dirpath+'/' + prefix + '*.' + image_format)

    for fname in images:
        img = cv2.imread(fname)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # Find the chess board corners
        ret, corners = cv2.findChessboardCorners(gray, (width, height), None)

        # If found, add object points, image points (after refining them)
        if ret:
            objpoints.append(objp)

            corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
            imgpoints.append(corners2)

            # Draw and display the corners
            img = cv2.drawChessboardCorners(img, (width, height), corners2, ret)

    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

    return [ret, mtx, dist, rvecs, tvecs]

def save_coefficients(mtx, dist, path):
    """ Save the camera matrix and the distortion coefficients to given path/file. """
    cv_file = cv2.FileStorage(path, cv2.FILE_STORAGE_WRITE)
    cv_file.write("K", mtx)
    cv_file.write("D", dist)
    # note you *release* you don't close() a FileStorage object
    cv_file.release()

def load_coefficients(path):
    """ Loads camera matrix and distortion coefficients. """
    # FILE_STORAGE_READ
    cv_file = cv2.FileStorage(path, cv2.FILE_STORAGE_READ)

    # note we also have to specify the type to retrieve other wise we only get a
    # FileNode object back instead of a matrix
    camera_matrix = cv_file.getNode("K").mat()
    dist_matrix = cv_file.getNode("D").mat()

    cv_file.release()
    return [camera_matrix, dist_matrix]

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Camera calibration')
    parser.add_argument('--image_dir', type=str, required=True, help='image directory path')  # 캘리브레이션 할 이미지의 위치
    parser.add_argument('--image_format', type=str, required=True,  help='image format, png/jpg') # 이미지의 저장형식
    parser.add_argument('--prefix', type=str, required=True, help='image prefix')  # 이미지의 이름
    parser.add_argument('--square_size', type=float, required=False, help='chessboard square size')  # 체스판의 사이즈(required가 false이면 default값이 들가거나 help라고 뜨면 써주면 됩니다. 
    parser.add_argument('--width', type=int, required=False, help='chessboard width size, default is 9') # 체스판의 너비
    parser.add_argument('--height', type=int, required=False, help='chessboard height size, default is 6') #체스판의 높이
    parser.add_argument('--save_file', type=str, required=True, help='YML file to save calibration matrices') #캘리브레이션 결과를 저장할 파일

    args = parser.parse_args()
    ret, mtx, dist, rvecs, tvecs = calibrate(args.image_dir, args.prefix, args.image_format, args.square_size, args.width, args.height)
    save_coefficients(mtx, dist, args.save_file)
    print("Calibration is finished. RMS: ", ret)

* 위 코드에서 오류가 뜨면 한글주석을 제거하고 실행해 보세요

 

위코드를 실행시키면

 

yehjin@yehjin-900X3L:~$ rosrun marker camera_calibration.py 
usage: camera_calibration.py [-h] --image_dir IMAGE_DIR --image_format
                             IMAGE_FORMAT --prefix PREFIX
                             [--square_size SQUARE_SIZE] [--width WIDTH]
                             [--height HEIGHT] --save_file SAVE_FILE
camera_calibration.py: error: the following arguments are required: --image_dir, --image_format, --prefix, --save_file

 

이렇게 뜹니다. 이것은 입력해줘야하는 input값들이 없어서 그런건데 젤 마지막줄이 해결방법을 제시해 주는 부분입니다.

이렇게 쓰면 되는거죠

 

yehjin@yehjin-900X3L:~$ rosrun marker camera_calibration.py --image_dir ~/catkin_ws/src/marker/src/image --image_format png --prefix left* --square_size 25 --width 8 --height 6 --save_file ~/catkin_ws/src/marker/src/image/ost3.yaml

 

오류가 뜬다면 left* 에서 *을 제거하고 다시해보세요

 

calibration roswiki를 이용하여 카메라를 이용해서 calibration한 결과

 

image_width: 640
image_height: 480
camera_name: narrow_stereo
camera_matrix:
  rows: 3
  cols: 3
  data: [ 586.9111 ,    0.     ,  309.6689 ,
            0.     ,  592.78916,  233.67894,
            0.     ,    0.     ,    1.     ]
camera_model: plumb_bob
distortion_coefficients:
  rows: 1
  cols: 5
  data: [0.090829, -0.204671, -0.001057, -0.000050, 0.000000]
rectification_matrix:
  rows: 3
  cols: 3
  data: [ 1.,  0.,  0.,
          0.,  1.,  0.,
          0.,  0.,  1.]
projection_matrix:
  rows: 3
  cols: 4
  data: [ 591.24005,    0.     ,  308.97831,    0.     ,
            0.     ,  597.47736,  232.8488 ,    0.     ,
            0.     ,    0.     ,    1.     ,    0.     ]

 

이미 저장된 이미지를 이용해서 위 code 를 사용하여 calibration한 결과

 

%YAML:1.0
---
K: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 5.7494769297367748e+02, 0., 3.0445999169574372e+02, 0.,
       5.8099846172481693e+02, 2.3035481242963945e+02, 0., 0., 1. ]
D: !!opencv-matrix
   rows: 1
   cols: 5
   dt: d
   data: [ 2.4236958514376992e-02, 8.2918441234635779e-02,
       -1.8400808936841081e-03, -1.8722329579970692e-03,
       -3.7845474348278413e-01 ]

 

각 행렬에서 e부분을 없애기 위해 다시 계산해보면

 

%YAML:1.0
---
K: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 574.947693,       0. ,   304.4599917,
                0.,    580.9984617, 230.3548124, 
                0.,          0.,         1. ]
D: !!opencv-matrix
   rows: 1
   cols: 5
   dt: d
   data: [ 0.02423695851, 0.08291844123, -0.00184, -000.1872232957, -0.00378454 ]

 

패키지를 이용하여 한 것과 파이썬 코드를 이용하여 calibration한 결과, 값이 조금 다르네요...사진이 흐릿해서 그런가..

이 게시물은 제가 한 것을 기록한 것으로 성공한 사례가 아닌 실패한 사례입니다.

주의하시기 바랍니다!

 

1. 카메라 캘리브레이션

저는 realsense d435i를 이용하여 camera calibration을 진행하였습니다.

제가 진행한 calibration관련 게시물입니다.

2021.05.21 - [ROS] - Realsense로 camera calibration하기(2)

 

2. opencv 버전확인하기

 

$ pkg-config --modversion opencv

 

3. 버전 4와 충돌일어나지않게 이전 opencv 지우기

(여기서 부터 잘못됐던것 같습니다ㅠㅠ 그냥 있는 버전 쓸걸 왜 지워가지고..)

 

$ sudo apt-get purge  libopencv* python-opencv
$ sudo apt-get autoremove

 

4. 기존 설치된 패키지 업데이트하기

 

$ sudo apt-get update
$ sudo apt-get upgrade

 

6. opencv 컴파일전 필요한 패키지 설치하기

 

$ sudo apt-get install build-essential cmake
$ sudo apt-get install pkg-config
$ sudo apt-get install libjpeg-dev libtiff5-dev libpng-dev
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libxvidcore-dev libx264-dev libxine2-dev
$ sudo apt-get install libv4l-dev v4l-utils
$ sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev 
$ sudo apt-get install libqt4-dev 
$ sudo apt-get install mesa-utils libgl1-mesa-dri libqt4-opengl-dev 
$ sudo apt-get install libatlas-base-dev gfortran libeigen3-dev
$ sudo apt-get install python2.7-dev python3-dev python-numpy python3-numpy

 

7. opencv 설정과 컴파일 및 설치하기

 

$ mkdir opencv
$ cd opencv
$ wget -O opencv.zip https://github.com/opencv/opencv/archive/4.2.0.zip
$ unzip opencv.zip
$ wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.2.0.zip
$ unzip opencv_contrib.zip
$ ls -d */
$ cd opencv-4.2.0/
$ mkdir build
$ cd build

 

$ cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D WITH_TBB=OFF \ -D WITH_IPP=OFF \ -D WITH_1394=OFF \ -D BUILD_WITH_DEBUG_INFO=OFF \ -D BUILD_DOCS=OFF \ -D INSTALL_C_EXAMPLES=ON \ -D INSTALL_PYTHON_EXAMPLES=ON \ -D BUILD_EXAMPLES=OFF \ -D BUILD_TESTS=OFF \ -D BUILD_PERF_TESTS=OFF \ -D WITH_QT=OFF \ -D WITH_GTK-ON \ -D WITH_OPENGL=ON \ -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.2.0/modules \ -D WITH_V4L=ON \ -D WITH_FFMPEG=ON \ -D WITH_XINE=ON \ -D BUILD_NEW_PYTHON_SUPPORT=ON \ -D OPENCV_GENERATE_PKGCONFIG=ON ../

 

위 코드를 이용하여 cmake설정을 해줘도 되고 $ ccmake .. 을 쳐서 직접 입력을 해도됩니다. 저는 설정이 제대로 되지않아 ccmake ..을 이용하여 직접 바꿨습니다. 다 입력을 하고 키보드 c 와 g 를 눌러줍니다. c 는 configure 을 의미하고 g 는 generate 를 의미합니다. ccmake .. 이 뭐였지...

 

컴파일을 하기전 사용중인 컴퓨터의 cpu 코어수 확인하기

 

yehjin@yehjin-900X3L:~$ cat /proc/cpuinfo | grep processor
processor	: 0
processor	: 1
processor	: 2
processor	: 3

아래 명령어는 전체 개수만을 알려주는 명령어입니다.
yehjin@yehjin-900X3L:~$ cat /proc/cpuinfo | grep processor | wc -l
4

 

컴파일 시작하기

 

yehjin@yehjin-900X3L:~/opencv/opencv-4.2.0/build$ time make -j4

 

컴파일 성공했을때

 

[100%] Linking CXX executable ../../bin/opencv_test_video
[100%] Built target opencv_test_video
[100%] Linking CXX shared module ../../lib/cv2.so
[100%] Built target opencv_python2
[100%] Linking CXX shared module ../../lib/python3/cv2.cpython-36m-x86_64-linux-gnu.so
[100%] Built target opencv_python3

real	34m31.021s
user	99m37.873s
sys	4m16.715s

 

컴파일 결과물 설치

 

$ sudo make install

 

yehjin@yehjin-900X3L:~/opencv/opencv-4.2.0/build$ cat /etc/ld.so.conf.d/*
/usr/lib/x86_64-linux-gnu/libfakeroot
# libc default configuration
/usr/local/lib
# Multiarch support
/usr/local/lib/x86_64-linux-gnu
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu

 

yehjin@yehjin-900X3L:~/opencv/opencv-4.2.0/build$ sudo ldconfig

opencv 설치 확인

 

$ pkg-config --modversion opencv

 

터미널에서 버전을 확인하려고 했을때 안뜰수도있습니다. sudo apt-get 명령어를 통해서 설치한 것이 아니면 안뜰가능성이 있다고 합니다.

파이썬에서 아래와 같이 나오면 opencv가 깔려있는것입니다.

 

yehjin@yehjin-900X3L:~$ python2
Python 2.7.17 (default, Feb 27 2021, 15:10:58) 
[GCC 7.5.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.2.0'

ctrl+D를 하면 파이썬을 빠져나올수있습니다.

 

g++에러

 

yehjin@yehjin-900X3L:~$ g++ -o facedetect /usr/local/share/opencv4/samples/cpp/facedetect.cpp $(pkg-config opencv4 --libs --cflags)
Package opencv4 was not found in the pkg-config search path.
Perhaps you should add the directory containing `opencv4.pc'
to the PKG_CONFIG_PATH environment variable
No package 'opencv4' found
g++: error: /usr/local/share/opencv4/samples/cpp/facedetect.cpp: No such file or directory
g++: fatal error: no input files
compilation terminated.

 

ros 환경에서 파이썬을 실행해도되지만 opencv를 설치하는 과정이 까다롭기때문에 설치가 완료됐어도 없다고 오류가 뜰수있습니다.  그럴때는 ros환경에서 실행시키는 것이 아니라 코드가 있는 폴더로 이동하여 python으로 실행시키면 됩니다.

 

yehjin@yehjin-900X3L:~/catkin_ws/src/marker/src$ python aruco_marker_detection.py 

 

opencv 로 yaml python파일을 load하기

 

import cv2
fs = cv2.FileStorage("./calib_asus_chess/cam_calib_asus.yml", cv2.FILE_STORAGE_READ)
fn = fs.getNode("camera_matrix")
print(fn.mat())

 

코드를 입력하여 실행해보았을때 오류가 떠서 실행되지않습니다. 먼저 노트북의 웹캠이 작동하는지 보았는데 /dev/video0자체가 없더라구요

realsense를 꽂고 실행시킨후 ls /dev/video*를 해도 없다고 뜹니다

lsusb로 연결은 된것을 확인했는데 왜 dev에는 없는건지 모르겠습니다.

 

$ sudo apt-get install cheese
$ cheese

 

하면 된다고 하는데 사진이 없다고 뜹니다.

 

marker라는 패키지를 만들어서 python코드를 실행시키려고 했봤습니다.

 

 

위 코드처럼 터미널에서 오류가 떠서 실행되지않습니다.

cvtColor오류는 이미지를 불러들이는 path가 잘못돼서 그렇다고 하는데 코드에서 path가

cap = cv2.VideoCapture() 이부분이라고 생각하는데 아닌것같아서 잘못된곳을 못찾겠습니다.

 

원래 사이트에서 코드를 조금 고쳤는데 함수를 track(matrix_coefficients, distortion_coefficients) 이렇게 쓰는게 아닌가요...? 왜 실행이 안되는 걸까요. 저거는 그냥 함수부분 자체문제가 있다는 뜻이었습니다... 저 함수를 사용하는데는 문제가 없는거 같아요

 

 

계속 path가 문제라고 하길래 video를 받아오지 못하면 empty frame이라고 출력하도록 했는데 역시 path문제가 맞았습니다....

 

제가 저장한 calibration파일에서 행렬을 못불러오는거같아서 직접 입력을 했는데 행렬이 여전히 들어가지는 못해요.

이 문제는 print를 통해 해결을 했습니다.

 

카메라를 불러오는데 문제가 있었기 때문에 연결이 문제인가했는데

 

 

usb에 연결됐다고는 떠도 실시간 영상을 불러오지는 못하더라구요. 코드자체도 애초에 webcam을 받아오라는 코드였는데 webcam만 따로 켜보려고해도 켜지지않았습니다. 이걸로 일주일 넘게 고민했는데 알고보니 하드웨어 오류...

다른 노트북에서 하니까 webcam이 잘 켜지더라구요 코드문제인줄알았는데 아니였네요..

진작 하드웨어인지 의심해볼걸 그랬어요

 

 

ros에서 python을 실행시키는게 python [파일이름] 이었는데 저는 그걸모르고 python에 들어가서 하는거랑 ros에서 하는거랑 다른건줄 알았네요. 근데 왜 쟤는 파일이 없다고 할까요ㅎㅎㅎ

 

다른 컴퓨터에서 해봤는데 카메라는 되는데 이제 함수부분이 문제네요....

 

* 포트 보는방법

 

 

코드에 포트번호를 입력할때 Bus 옆에 번호를 넣으면 됩니다.

 

왜 함수에 대한 잘못된 인수라고 뜰까요? 어떤 형식으로 값을 넣어야되는지 모르겠습니다.

 

 

변수이름만 넣어도 안되고 배열로 지정하고 넣어도 안되고 어떤 형식으로 적어야 할까요...

저거는 들어가는 변수의 개수가 더 많아서 그런거였습니다. 뒤에 cameraMatrix, distCoeff부분을 지우니까 됐습니다.  카메라는 작동하는데 이제는 마크 자체를 인식을 못하네요.

 

realsense로 해보려고 했는데 videocapture가 웹캠에 사용되는 거라서 realsense로는 되지않기때문에 카메라를 웹캠으로 바꿨습니다. 예전에 차선인식할때 realsense로 해봤던거 같은데 그때 어떻게 했지...

 

id: dictionary 에 속한 마커들 중 사용할 마커의 id 입니다. DICT_6X6_250의 경우 0부터 249까지의 id를 지정할수있습니다.

 

마크를 인식하기는 하는데 하자마자 카메라가 꺼졌습니다. 왜그런가 했더니 웹캠으로 다시 camera calibration을 해야한다고 합니다. 사진크기가 이전에 realsense와 달라서 불러온 matrix가 문제가 있는거 아닌가 하는 것입니다.

웹캠으로는 어떻게 하지.......

 

제 노트북에서 realsense로 영상을 받아오는게 안됐다고 위에서 말씀드렸는데요.

카메라 usb port색에 따라서 버전이 다른데요 포트 부분이 파란색은 3.0 흰색은 2.0이라고 합니다.

노트북에 포트가 2.0이라서 realsense의 3.0포트가 맞지않아서 코드를 통해 실시간 영상을 불러오는게 안될수도 있다고 합니다.

 

realsense camera로 마커인식하는 것은 다음에 다시 도전하겠습니다...일단 webcam으로 먼저 해볼게요..

 

 

*참고

[출처] OpenCV 2.4 제거 후 3.x 설치|작성자 Breaker

https://webnautes.tistory.com/1186

https://webisfree.com/2020-08-11/[linux]-cpu%EC%9D%98-core-%EA%B0%9C%EC%88%98-%ED%99%95%EC%9D%B8%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

calibration 코드 참고 : https://aliyasineser.medium.com/opencv-camera-calibration-e9a48bdd1844

marker 코드 참고 : https://aliyasineser.medium.com/aruco-marker-tracking-with-opencv-8cb844c26628

marker 코드 참고2 : https://m.blog.naver.com/cjsal95/221330088063

3 : http://www.gisdeveloper.co.kr/?p=6317

https://answers.opencv.org/question/31207/how-do-i-load-an-opencv-generated-yaml-file-in-python/

marker mean : https://webnautes.tistory.com/1040

camera calibration code : https://stackoverflow.com/questions/34588464/python-how-to-capture-image-from-webcam-on-click-using-opencv

+ Recent posts