내맘대로 공부기록.

[ C++ ]

[ openCV | C++ ] 기본기. 이미지에 도형 추가 / 라벨링 하는 방법

fwanggus 2021. 2. 4. 00:32

이미지에 도형을 추가하거나 라벨링을 하는 순서는 아래와 같다.

  1. 이미지 또는 영상에서 사물(얼굴) 인식 기능을 구현한다.
  2. 인식된 부분에 테두리를 표시하여 정확도를 표시하거나, 해당 물체가 어떤 물체인지 텍스트로 표기한다.

이런 라벨링 작업들은 수작업으로 처리하지 않아도 되는 경우도 있으며, 용도에 맞게 해당 요소들을 이미지에 다시 뿌려줘야 하는 경우도 있다.

 

그래서, 수작업이 필요할 경우 어떤 원리에 의해 이미지에 도형 또는 텍스를 표시할 수 있는지 정리해보았다.

 

 


 

이미지 준비 ✅

흰색 이미지를 만들어서 작업했다. 

// Mat variableName(width, height, type?, Color)
Mat img(512,512,CV_8UC3, Scalar(255,255,255));

흰색의 이미지가 만들어졌다. 진짜 그냥 흰색 이미지라 첨부하진 않았다. 

 

원형 추가 🟡

circle() 함수를 호출해서, 이미지 소스에 적용한다. 

// circle(originalImgSrc, centerPoint, Radius, ColorOfCircle, Thickness)
circle(img, Point(256,256),  155, Scalar(255,0,255), 3);

 

원형 도형 출력

 

위 사진에서 이미 눈치를 챗겠지만, 원형만 추가해서 첨부하자니 이미지 위치 구별(중앙에 잘 와있는지 보기 위한 테두리)이 잘 안돼서 사각형(빨간색)을  미리 추가해버렸다.

 

사각형 추가 🟦

사각형도 원형과 거의 비슷하다. rectangle() 함수를 호출해서 그릴 수 있다. 직관적이어서 openCV는 배우기 쉬운 것 같다.

사각형 양 끝 코너 포인트 좌표를 입력하는 대신 Rect 객체를 가지고 있다면, 포인트 대신 해당 객체 변수로 사각형을 정의할 수 도 있다. 자세한 내용은 공식 문서를 참고하자.

// rectangle(originalImgSrc, TopLeftPoint, BottomRightPoint, Color, Thickness)
rectangle(img, Point(30,30), Point(150,145), Scalar(255,0,100),3);

 

파란색 사각형 출력

 

파란색 사각형이 정상적으로 출력되었다. 

사각형 테두리를 두께가 아닌 모두 채움으로 하고 싶을 경우에는 두께 수치 대신 FILLED를 입력하면 채워진다.

rectangle(img, Point(30,30), Point(150,145), Scalar(255,0,100),FILLED);

 

테두리 채움 효과

 

 

라인 추가 📏

라인은 말 그대로 라인이다. line() 함수 그냥 호출하면 끝이다. 너무 쉬워서 당황스럽네요.

// line(OriginalImgSrc, Point1, Point2, Color, Thickness)
line(img, Point(155,256), Point(300,256), Scalar(0,255,0),5);

 

원의 중심을 통과하는 선 출력

 

라인의 경우에는, Thickness 인수 다음으로 lineType을 지정할 수 있다. 연결된 4점, 8점 직선 그리고 antialiased line을 제공한다. antialiased line 옵션의 경우 아래와 같은 것(image link)을 말한다. 자글자글하지 않고 부드러운 라인을 말하는 듯하다.

 

 

Normal line VS Antialised line 

 

 

텍스트 표시 ✏️

텍스트는 인식된 물체에 대해서, 인식 정확도 또는 어떤 물체인지 라벨링을 할 때 매우 유용한 기능으로 자주 사용될 것 같다.

//putText(originalImgSrc, string, stringPosition_bottomLeft, font, sizeScale, Color, Thickness)
putText(img, "Hello My World", Point(137,262), FONT_HERSHEY_DUPLEX, 1 , Scalar(200,10,0), 2);

 

텍스트 추가 완료

 

여기서 주의해야 할 점은 텍스트의 좌표를 지정하는 부분이다.

입력하는 포인트 좌표는 텍스트의 왼쪽 아래 가장자리를 나타낸다. 그래서, 해당 좌표를 Point(0,0)으로 지정하게 되면 좌표는 기본적으로 이미지의 왼쪽 상단을 참조하여 계산되기 때문에, 텍스트의 왼쪽 아래 꼭짓점이 원본 이미지의 왼쪽 상단 모서리에 붙어버린다.

결과적으로는 텍스트는 출력되지만, 위치상 이미지 픽셀 범위를 벗어나 버리기 때문에 보이지 않게 된다. 

 

putText(img, "Hello My World", Point(0,0), FONT_HERSHEY_DUPLEX, 1 , Scalar(200,10,0), 2);

 

텍스트를 Point(0,0) 으로 위치 시킴.

 

결과에서 알 수 있듯이, 텍스트의 y 아래 부분이 살짝 보인다. 참고 하자.

 


 

전체 코드 📚

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
//img processing header
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main(){

    Mat img(512,512,CV_8UC3, Scalar(255,255,255));
    circle(img, Point(256,256),  155, Scalar(255,0,255), 3);
    rectangle(img, Point(3,3), Point(509,509), Scalar(0,0,255),3);
    rectangle(img, Point(30,30), Point(150,145), Scalar(255,0,100),FILLED);
    line(img, Point(155,256), Point(300,256), Scalar(0,255,0),5);
    putText(img, "Hello My World", Point(0,0), FONT_HERSHEY_DUPLEX, 1 , Scalar(200,10,0), 2);

    imshow("Image", img);
    imwrite("result/image_base.png", img);
    waitKey(0);

    return 0;
}
반응형