본문 바로가기

OpenCV

OpenCV 이미지에 글씨 쓰기 - LearnOpenCV

반응형

 

이미지와 동영상에 주석을 달면 여러 가지 목적을 달성할 수 있으며, OpenCV를 사용하면 프로세스가 간단하고 쉬워집니다. 사용 방법을 확인하세요:

 

  • 데모에 정보 추가
  • 객체 감지 시 객체 주위에 경계 상자 그리기
  • 이미지 분할을 위해 다양한 색상으로 픽셀 강조 표시

 

 

 

이미지에 주석을 다는 방법을 배우면 비디오 프레임에 주석을 다는 것도 마찬가지로 쉬워 보일 것입니다. 비디오의 각 프레임이 이미지로 표현되기 때문입니다. 여기서는 기하학적 모양과 텍스트로 이미지에 주석을 다는 방법을 보여드리겠습니다.

 

여기의 모든 예제에서 사용할 이미지입니다. 

 

먼저, 이미지에 주석을 달기 위해 이 코드를 잠깐 살펴보세요. 코드의 각 줄은 여러분이 완전히 이해할 수 있도록 자세히 설명될 것입니다.

 

파이썬: 

 

# Import dependencies
import cv2

# Read Images
img = cv2.imread('sample.jpg')

# Display Image
cv2.imshow('Original Image',img)
cv2.waitKey(0)

# Print error message if image is null
if img is None:
    print('Could not read image')

# Draw line on image from point A to B
imageLine = img.copy()
pointA = (200,80)
pointB = (450,80)
cv2.line(imageLine, pointA, pointB, (255, 255, 0), thickness=3, lineType=cv2.LINE_AA)
cv2.imshow('Image Line', imageLine)
cv2.waitKey(0)

 

C++

 

// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>

// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;

int main()
{
    // Read Images
    Mat img = imread("sample.jpg");
    
    // Display Image
    imshow("Original Image", img);
    waitKey();

    // Print Error message if image is null
    if (img.empty())
        {
            cout << "Could not read image" << endl;
        }

    // Draw line on image
    Mat imageLine = img.clone();
    Point pointA(200,80);
    Point pointB(450,80);
    line(imageLine, pointA, pointB, Scalar(255, 255, 0), 3, 8, 0);
    imshow("Lined Image", imageLine);
    waitKey();
}

 

시스템에 이미 OpenCV가 있다고 가정합니다. OpenCV를 설치해야 하는 경우 아래의 관련 링크를 방문하세요.

  1. Windows에 OpenCV 설치
  2. MacOS에 OpenCV 설치
  3. Ubuntu에 OpenCV 설치 

 

아래에 표시된 대로 OpenCV를 가져오는 것으로 시작합니다.

 

참고: C++의 경우 일반적으로 cv::function()을 사용합니다. cv 네임스페이스(namespace cv 사용)를 사용하기로 했기 때문에 OpenCV 함수에 직접 액세스할 수 있습니다. 함수 이름 앞에 cv::를 붙일 필요가 없습니다. 코드 다운로드는 원문 참고.

 

파이썬:

 

# Import dependencies

import cv2 

 

C++

 

// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>

// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;

 

 

아래 코드에서 imread()를 사용하여 이미지를 읽고 imshow()를 사용하여 표시합니다. C++ 코드에는 몇 가지 추가 단계가 필요합니다. imread() 함수를 사용하여 이미지를 읽기 전에 main 함수를 만들고 이미지에 대한 행렬을 정의합니다.

이미지를 표시하려면 imshow() 함수를 사용합니다.

파이썬:

 

# Read the image
img = cv2.imread('sample.jpg')

#Display the input image
cv2.imshow('Original Image',img)
cv2.waitKey(0)

 

C++:

 

int main()
{
   // Read Image
   Mat img = imread("sample.jpg");

   // Display the Image
   imshow("Original Image", img);
   waitKey();

   // Print Error message if image is null
   if (img.empty())
       {
           cout << "Could not read image" << endl;
       }

 

 

 

다음으로 OpenCV의 다양한 그리기 함수를 사용하여 이미지에 주석을 다는 방법을 설명합니다. 각 함수에는 여러 가지 선택적 인수가 제공됩니다. 자세히 알아보려면 OpenCV 설명서 페이지를 참조하세요.

선 그리기

이 첫 번째 예에서는 OpenCV의 line() 함수를 사용하여 이미지에 색상 선으로 주석을 달겠습니다. line() 함수를 호출하기 전에 다음을 사용하여 원본 이미지의 복사본을 만듭니다:

  • Python의 copy() 함수
  • C++의 clone() 함수

복사본은 이미지에 대한 변경 사항이 원본 이미지에 영향을 미치지 않도록 합니다. C++에서는 먼저 원본 이미지의 사본에 대한 행렬을 만듭니다.

line() 함수의 구문은 다음과 같습니다:

 

line(image, start_point, end_point, color, thickness)

 

  • 첫 번째 인수는 이미지입니다.
  • 다음 두 인수는 선의 시작점과 끝점입니다.

A(x1, y1) 지점에서 B(x2, y2) 지점까지 선을 그립니다. 여기서 A와 B는 이미지의 두 점을 나타냅니다. 이미지의 왼쪽 상단 모서리를 보면 xy 좌표계의 원점이 있습니다.

  • x축은 수평 방향 또는 이미지의 열을 나타냅니다.
  • y축은 수직 방향 또는 이미지의 행을 나타냅니다.

아래 코드에서 볼 수 있듯이:

  • 시작점과 끝점을 지정하여 이미지에 수평으로 250픽셀 길이의 선을 그립니다.
  • 색상을 파란색과 녹색의 혼합으로 정하고 두께를 3으로 지정합니다.

다른 선택적 인수를 알아보려면 여기에서 OpenCV 설명서 페이지를 방문하세요.

파이썬:

 

#Make copy of the image
imageLine = img.copy()
# Draw the image from point A to B
pointA = (200,80)
pointB = (450,80)
cv2.line(imageLine, pointA, pointB, (255, 255, 0), thickness=3))
cv2.imshow('Image Line', imageLine)
cv2.waitKey(0)

 

 

C++:

 

// Make copy of the image
   Mat imageLine = img.clone();
   // Draw the image from point A to B
   Point pointA(200,80);
   Point pointB(450,80);
   line(imageLine, PointA, PointB, Scalar(255, 255, 0), 3, 8, 0);
   imshow("Lined Image", line_image);
   waitKey();

 

 

아래 이미지에서 결과를 확인하세요.

 

선으로 그려진 출력 이미지.

 

원 그리기

다음으로 OpenCV의 circle() 함수를 사용하여 이미지에 원으로 주석을 달아 보겠습니다. 구문을 살펴보세요:

 

circle(image, center_coordinates, radius, color, thickness)

 

  • OpenCV의 모든 그리기 함수와 마찬가지로 첫 번째 인수는 이미지입니다.
  • 다음 두 인수는 원의 중심과 반지름에 대한 좌표를 정의합니다.
  • 마지막 두 인수는 선의 색상과 두께를 지정합니다.

이 예에서 개 얼굴 주위에 빨간색 원으로 이미지에 주석을 달았습니다. 그런 다음 imshow() 함수를 사용하여 주석이 달린 이미지를 표시합니다.

파이썬:

 

# Make a copy of image
imageCircle = img.copy()
# define the center of circle
circle_center = (415,190)
# define the radius of the circle
radius =100
#  Draw a circle using the circle() Function
cv2.circle(imageCircle, circle_center, radius, (0, 0, 255), thickness=3, lineType=cv2.LINE_AA) 
# Display the result
cv2.imshow("Image Circle",imageCircle)
cv2.waitKey(0)

 

C++:

 

// Make a copy of image
   Mat circle_image = img.clone();
   // define the center of circle
   Point circle_center(415,190);
   // define the radius of circle
   int radius = 100;
   // Draw a circle using the circle() Function
   circle(circle_image, circle_center, radius, Scalar(0, 0, 255), 3, 8, 0);
   // Display the result
   imshow("Circle on Image", circle_image);
   waitKey();

 

 

 

 

채워진 원 그리기

방금 이미지에 빨간색 원으로 주석을 달았습니다. 지금 이 원을 단색으로 채우고 싶다면 어떨까요? 간단합니다. 아래 코드에 표시된 대로 두께 인수를 -1로 변경하기만 하면 됩니다.

파이썬:

 

# make a copy of the original image
imageFilledCircle = img.copy()
# define center of the circle 
circle_center = (415,190)
# define the radius of the circle
radius =100
# draw the filled circle on input image
cv2.circle(imageFilledCircle, circle_center, radius, (255, 0, 0), thickness=-1, lineType=cv2.LINE_AA)
# display the output image 
cv2.imshow('Image with Filled Circle',imageFilledCircle)
cv2.waitKey(0)

 

C++:

 

// make a copy of the original image
   Mat Filled_circle_image = img.clone();
   // define the center of circle
   Point circle_center(415,190);
   // define the radius of the circle
   int radius = 100;
   //Draw a Filled Circle using the circle() Function
   circle(Filled_circle_image, circle_center, radius, Scalar(255, 0, 0), -1, 8, 0);
   // display the output image
   imshow("Circle on Image", circle_image);
   waitKey();

 

 

 

사각형 그리기

이제 OpenCV의 rectangle() 함수를 사용하여 이미지에 사각형을 그립니다. 구문을 확인하세요.


rectangle(image, start_point, end_point, color, thickness)

 

rectangle() 함수에서 직사각형 모서리의 시작점(좌측 상단)과 끝점(우측 하단)을 제공합니다.

지금 이 예제 코드를 살펴보고 강아지 얼굴에 빨간색 직사각형으로 이미지에 주석을 달아보세요.

파이썬:

 

# make a copy of the original image
imageRectangle = img.copy()
# define the starting and end points of the rectangle
start_point =(300,115)
end_point =(475,225)
# draw the rectangle
cv2.rectangle(imageRectangle, start_point, end_point, (0, 0, 255), thickness= 3, lineType=cv2.LINE_8) 
# display the output
cv2.imshow('imageRectangle', imageRectangle)
cv2.waitKey(0)

 

C++:

 

// make a copy of the original image
   Mat rect_image = image.clone();
   // Define the starting and end points for the rectangle
   Point start_point(300,115);
   Point end_point(475,225);
   // Draw a rectangle using the rectangle() function
   rectangle(rect_image, start_point, end_point, Scalar(0,0,255), 3, 8, 0);
   imshow("Rectangle on Image", rect_image);
   waitKey();

 

 

 

타원 그리기

OpenCV의 ellipse() 함수를 사용하여 이미지에 타원을 그릴 수도 있습니다. ellipse() 함수의 구문은 원의 구문과 매우 유사합니다. 다만 반지름 대신 다음을 지정해야 합니다:

  • 타원의 장축과 단축 길이
  • 회전 각도
  • 타원의 시작 및 종료 각도
  • - 이러한 각도를 사용하면 호의 일부만 그릴 수 있습니다.

 

ellipse(image, centerCoordinates, axesLength, angle, startAngle, endAngle, color, thickness)

 

아래 예제 코드에서 이미지에 주석을 달 수 있습니다:

  • 수평 파란색 타원
  • 수직 빨간색 타원

다시 볼 수 있듯이 OpenCV의 그리기 함수는 매우 유사하여 마스터하기 쉽습니다. 또한, 많은 기본 기하학적 모양의 위치와 방향을 자유롭게 정의할 수 있도록 선택적 인수를 제공합니다.

파이썬:

 

# make a copy of the original image
imageEllipse = img.copy()
# define the center point of ellipse
ellipse_center = (415,190)
# define the major and minor axes of the ellipse
axis1 = (100,50)
axis2 = (125,50)
# draw the ellipse
#Horizontal
cv2.ellipse(imageEllipse, center, axis1, 0, 0, 360, (255, 0, 0), thickness=3)
#Vertical
cv2.ellipse(imageEllipse, center, axis2, 90, 0, 360, (0, 0, 255), thickness=3)
# display the output
cv2.imshow('ellipse Image',imageEllipse)
cv2.waitKey(0)

 

C++:

 

// make a copy of the original image
   Mat imageEllipse = img.clone();
   // define the center point of ellipse
   Point ellipse_center(415,190);
   // define the major and minor axes of the ellipse
   Point axis1(100, 50);
   Point axis2(125, 50);
   // Draw an ellipse using the ellipse() function
   //Horizontal
   ellipse(imageEllipse, ellipse_center, axis1, 0, 0, 360, Scalar(255, 0, 0), 3, 8, 0);
   // Vertical
   ellipse(imageEllipse, ellipse_center, axis2, 90, 0, 360, Scalar(0, 0, 255), 3, 8, 0);
   // display the output
   imshow("Ellipses on Image", imageEllipse);
   waitKey();

 

 

 

 

반타원 그리기

이 예제에서는 이전 코드를 수정하여 다음을 수행합니다:

  1. 파란색 타원의 절반만 그리기
  2. 수직 빨간색 타원을 반만 채워진 수평 빨간색 타원으로 변경

이를 위해 다음과 같이 변경합니다:

  • 파란색 타원의 endAngle을 180도로 설정
  • 빨간색 타원의 방향을 90에서 0으로 변경
  • 빨간색 타원의 시작 및 종료 각도를 각각 0과 180으로 지정
  • 빨간색 타원의 두께를 음수로 지정

파이썬:

 

# make a copy of the original image
halfEllipse = img.copy()
# define the center of half ellipse
ellipse_center = (415,190)
# define the axis point
axis1 = (100,50)
# draw the Incomplete/Open ellipse, just a outline
cv2.ellipse(halfEllipse, ellipse_center, axis1, 0, 180, 360, (255, 0, 0), thickness=3)
# if you want to draw a Filled ellipse, use this line of code
cv2.ellipse(halfEllipse, ellipse_center, axis1, 0, 0, 180, (0, 0, 255), thickness=-2)
# display the output
cv2.imshow('halfEllipse',halfEllipse)
cv2.waitKey(0)

 

C++:

 

//make a copy of the original image
   Mat halfEllipse = image.clone();
   // define the center of half ellipse
   Point ellipse_center(415,190);
   //define the axis point
   Point axis1(100, 50);
   // draw the Half Ellipse, just the outline
   ellipse(halfEllipse, ellipse_center, axis1, 0, 180, 360, Scalar(255, 0, 0), 3, 8, 0);
   // if you want to draw a Filled ellipse, use this line of code
   ellipse(halfEllipse, ellipse_center, axis1, 0, 0, 180, Scalar(0, 0, 255), -2, 8, 0);
   // display the output
   imshow("Half-Ellipses on Image", halfEllipse);
   waitKey();

 

아래의 결과를 확인하세요:

 

 

 

 

텍스트 추가

마지막으로 이미지에 텍스트 주석을 달아 보겠습니다. 이를 위해 OpenCV의 putText() 함수를 사용합니다. 구문과 인수를 살펴보겠습니다.

 

putText(image, text, org, font, fontScale, color)

 

  • 평소처럼 첫 번째 인수는 입력 이미지입니다.
  • 다음 인수는 이미지에 주석을 달 실제 텍스트 문자열입니다.
  • 세 번째 인수는 텍스트 문자열의 왼쪽 상단 모서리에 대한 시작 위치를 지정합니다.
  • 다음 두 인수는 글꼴 스타일과 크기를 지정합니다.

- OpenCV는 Hershey 글꼴 컬렉션의 여러 글꼴 스타일과 기울임꼴 글꼴도 지원합니다. 다음 목록을 확인하세요.

 

- FONT_HERSHEY_SIMPLEX = 0,

- FONT_HERSHEY_PLAIN = 1,

- FONT_HERSHEY_DUPLEX = 2,

- FONT_HERSHEY_COMPLEX = 3,

- FONT_HERSHEY_TRIPLEX = 4,

- FONT_HERSHEY_COMPLEX_SMALL = 5,

- FONT_HERSHEY_SCRIPT_SIMPLEX = 6,

- FONT_HERSHEY_SCRIPT_COMPLEX = 7,

- FONT_ITALIC = 16

  • 글꼴 크기는 글꼴의 기본 크기를 늘리거나 줄이는 데 사용되는 부동 소수점 값입니다. 이미지의 해상도에 따라 적절한 글꼴 크기를 선택하세요.
  • 마지막 필수 인수는 BGR 트리플릿으로 지정된 색상입니다.

이 코드를 살펴보면 이러한 인수가 이미지에 텍스트 문자열을 표시하는 데 어떻게 구현되는지 알 수 있습니다.

파이썬:

 

# make a copy of the original image
imageText = img.copy()
#let's write the text you want to put on the image
text = 'I am a Happy dog!'
#org: Where you want to put the text
org = (50,350)
# write the text on the input image
cv2.putText(imageText, text, org, fontFace = cv2.FONT_HERSHEY_COMPLEX, fontScale = 1.5, color = (250,225,100))))
# display the output image with text over it
cv2.imshow("Image Text",imageText)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

C++:

 

// make a copy of the original image
   Mat imageText = img.clone();
   // Write text using putText() function
   putText(imageText, "I am a Happy dog!", Point(50,350), FONT_HERSHEY_COMPLEX, 1.5, Scalar(250,225,100));
   imshow("Text on Image", imageText);
   waitKey(0);

 

최종 결과가 나왔습니다!

 

 

 

Streamlit을 사용한 웹 애플리케이션

OpenCV를 사용하여 이미지에 주석을 달 수 있는 간단한 웹 애플리케이션을 만들었습니다. 여기에서 탐색할 수 있습니다.

요약

기하학적 모양과 텍스트로 이미지에 주석을 달면 강력한 커뮤니케이션 방법이 됩니다. 이미지에 대한 정보를 확대하는 데 도움이 됩니다. 이미지는 다양한 컴퓨터 비전 알고리즘으로 처리된 후 거의 항상 오버레이 결과에 주석이 달립니다(예: 경계 상자는 객체 감지 모델에서 감지한 객체 주위에 그려짐).

여기에서 기하학적 모양과 텍스트로 이미지에 주석을 달기가 얼마나 쉬운지 확인했습니다. 그리기 함수도 입력 인수가 비슷합니다. 주석의 위치와 크기를 지정하는 방법만 약간 다를 수 있습니다.

또한 원하는 색상으로 모양을 채우는 방법도 배웠습니다. 특정 방향과 길이의 타원과 호를 그렸습니다.

마지막으로 텍스트로 이미지에 주석을 다는 방법을 확인했습니다.

이 게시물에서 논의한 모든 코드는 이 링크에서 찾을 수 있습니다 → OpenCV Colab Notebook을 사용한 이미지 주석달기.

 

원문 튜토리얼 참고

 

 

 

 

반응형

더욱 좋은 정보를 제공하겠습니다.~ ^^