본문 바로가기

OpenCV

OpenCV GUI에서 마우스와 트랙바

반응형

마우스 포인터는 그래픽 사용자 인터페이스(GUI)의 핵심 구성 요소입니다. 마우스 포인터가 없다면 GUI와의 상호 작용을 상상할 수 없습니다. 자, 이제 OpenCV의 마우스 및 트랙바 내장 함수를 자세히 살펴보겠습니다. 마우스를 사용하여 이미지에 주석을 달고, 트랙바를 사용하여 이미지 크기를 조절하는 방법도 보여드리겠습니다.

 

 

 

이 게시물은 다음 게시물로 구성된 OpenCV 시작하기 시리즈의 일부입니다 .

 

Table of Content

 

마우스를 사용하여 이미지에 주석 달기

트랙바를 사용하여 이미지 크기 조정

요약

 

아래 이미지를 통해 OpenCV에서 마우스 포인터와 트랙바 기능을 사용하는 방법을 보여드리겠습니다.

 

 

OpenCV GUI에서 마우스와 트랙바에 대한 입력 이미지입니다.

 

 

마우스를 사용하여 이미지에 주석 달기

 

OpenCV는 왼쪽 클릭 및 오른쪽 클릭과 같은 다양한 마우스 동작을 감지하는 마우스 이벤트 감지 기능을 제공합니다. 이 첫 번째 예제에서는 마우스를 사용하여 명명된 창에 표시된 이미지에 사각형을 렌더링하는 방법을 보여줍니다.

 

코드는 다음과 같습니다.

 

파이썬:

 

# Import packages
import cv2
 
# Lists to store the bounding box coordinates
top_left_corner=[]
bottom_right_corner=[]
 
# function which will be called on mouse input
def drawRectangle(action, x, y, flags, *userdata):
  # Referencing global variables 
  global top_left_corner, bottom_right_corner
  # Mark the top left corner when left mouse button is pressed
  if action == cv2.EVENT_LBUTTONDOWN:
    top_left_corner = [(x,y)]
    # When left mouse button is released, mark bottom right corner
  elif action == cv2.EVENT_LBUTTONUP:
    bottom_right_corner = [(x,y)]    
    # Draw the rectangle
    cv2.rectangle(image, top_left_corner[0], bottom_right_corner[0], (0,255,0),2, 8)
    cv2.imshow("Window",image)
 
# Read Images
image = cv2.imread("../Input/sample.jpg")
# Make a temporary image, will be useful to clear the drawing
temp = image.copy()
# Create a named window
cv2.namedWindow("Window")
# highgui function called when mouse events occur
cv2.setMouseCallback("Window", drawRectangle)
 
k=0
# Close the window when key q is pressed
while k!=113:
  # Display the image
  cv2.imshow("Window", image)
  k = cv2.waitKey(0)
  # If c is pressed, clear the window, using the dummy image
  if (k == 99):
    image= temp.copy()
    cv2.imshow("Window", image)
 
cv2.destroyAllWindows()

 

C++:

 

// Import packages
#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>
 
//Using namespace to nullify use of cv::function(); syntax
using namespace cv;
using namespace std;
 
// Points to store the bounding box coordinates
Point top_left_corner, bottom_right_corner;
// image image
Mat image;
 
// function which will be called on mouse input
void drawRectangle(int action, int x, int y, int flags, void *userdata)
{
  // Mark the top left corner when left mouse button is pressed
  if( action == EVENT_LBUTTONDOWN )
  {
    top_left_corner = Point(x,y);
  }
  // When left mouse button is released, mark bottom right corner
  else if( action == EVENT_LBUTTONUP)
  {
    bottom_right_corner = Point(x,y);
    // Draw rectangle
    rectangle(image, top_left_corner, bottom_right_corner, Scalar(0,255,0), 2, 8 );
    // Display image
    imshow("Window", image);
  }
   
}
 
// Main function
int main()
{
  image = imread("../../Input/sample.jpg");
  // Make a temporary image, which will be used to clear the image
  Mat temp = image.clone();
  // Create a named window
  namedWindow("Window");
  // highgui function called when mouse events occur
  setMouseCallback("Window", drawRectangle);
 
  int k=0;
  // loop until q character is pressed
  while(k!=113)
  {
    imshow("Window", image );
    k= waitKey(0);
    // If c is pressed, clear the window, using the dummy image
    if(k == 99)
    {
      temp.copyTo(image);
    }
  }
  destroyAllWindows();
  return 0;
}

 

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

 

Windows에 OpenCV 설치

MacOS에 OpenCV 설치

Ubuntu에 OpenCV 설치

 

먼저 필요한 패키지를 가져옵니다.

 

파이썬:

 

# Import packages

import cv2

 

C++:

 

// Import packages
#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>
 
// Using namespace to nullify use of cv::function(); syntax
using namespace cv;
using namespace std;

 

 

다음으로, 사각형을 그리는 데 사용할 점을 저장할 두 개의 리스트를 초기화합니다. C++에서는 이미지 데이터를 저장하기 위한 행렬도 초기화합니다(Python에서는 필수가 아님).

 

파이썬:

 

# Lists to store the points

top_left_corner=[ ]

bottom_right_corner=[]

 

C++:

 

// Points to store the center of the circle and a point on the circumference

Point top_left_corner, bottom_right_corner;

// image

Mat image;

 

먼저, 지정된 창에 표시된 이미지에 사각형을 그리는 특수 '콜백' 함수를 정의합니다. 특정 사용자 인터페이스 이벤트가 감지될 때만 호출되는 이러한 유형의 함수는 '콜백' 함수로 알려지게 되었습니다. 여기서 이 함수는 마우스 이벤트와 연관되어 있으므로 MouseCallback 함수로 정의합니다. 함수 이름은 원하는 대로 지정할 수 있습니다. 이 경우 drawRectangle()이라는 이름을 사용했습니다. 이 함수 이름을 마우스 이벤트와 연결하도록 등록할 예정이므로 이렇게 명명해도 문제없습니다. 함수에 입력 인수를 명시할 필요는 없습니다. 사용자가 마우스로 상호작용할 때 자동으로 채워집니다. 

 

이 함수를 특정 마우스 이벤트와 연결하는 방법을 알아보겠습니다.아래와 같이 특정 마우스 이벤트에 따라 사각형을 그리는 로직을 만듭니다.사용 가능한 이벤트 목록은 여기에 설명되어 있습니다 .사용자가 마우스를 표시된 이미지 위에 올려놓고 상호작용할 때마다 마우스 이벤트 유형과 이벤트 플래그가 마우스 x 및 y 좌표와 함께 기록됩니다.이러한 정보가 처리를 위해 함수에 전달됩니다. *userdata콜백 함수에 추가 입력을 제공할 수 있는 선택적 인수입니다(이 예제에서는 필요하지 않습니다). LEFTBUTTONDOWN 및 LEFTBUTTONUP 작업 이 트리거되면 해당 변수에 좌표를 저장하고 이를 사용하여 사각형을 그립니다.

 

이미지에 주석을 다는 것에 익숙하지 않다면 이 게시물을 참조하세요 .

 

파이썬:

 

def drawRectangle(action, x, y, flags, *userdata):
  # Referencing global variables 
  global top_left_corner, bottom_right_corner
  # Mark the top left corner, when left mouse button is pressed
  if action == cv2.EVENT_LBUTTONDOWN:
    top_left_corner = [(x,y)]
    # When left mouse button is released, mark bottom right corner
  elif action == cv2.EVENT_LBUTTONUP:
    bottom_right_corner = [(x,y)]    
    # Draw the rectangle
    cv2.rectangle(image, top_left_corner[0], bottom_right_corner[0], (0,255,0),2,8)
    cv2.imshow("Window",image)

 

C++:

 

void drawRectangle(int action, int x, int y, int flags, void *userdata)
{
  // Mark the top left corner when left mouse button is pressed
  if( action == EVENT_LBUTTONDOWN )
  {
    top_left_corner = Point(x,y);
  }
  // When left mouse button is released, mark bottom right corner
  else if( action == EVENT_LBUTTONUP)
  {
    bottom_right_corner = Point(x,y);
    rectangle(image, top_left_corner, bottom_right_corner, Scalar(0,255,0), 2, 8 );
    imshow("Window", image);
  }
}

 

이 마우스 콜백 함수를 정의한 후 다음 작업을 수행합니다.

 

  • 디스크에서 샘플 이미지를 읽으려면 다음을 사용하세요.imread()
  • C++의 경우 copy()또는 clone() 를 사용하여 이미지 사본을 저장합니다.
  • 이름이 지정된 창 만들기

 

setMouseCallback()을 호출하여 위에서 정의한 마우스 콜백 함수를 등록하고, 지정된 창에서 발생하는 마우스 이벤트에 대해 (drawRectangle())을 호출합니다.

 

setMouseCallback() 함수의 일반적인 구문은 아래와 같으며, 여기에 문서화되어 있습니다.

 

파이썬:

 

cv2.setMouseCallback(winname, onMouse, userdata)

 

C++:

 

void cv::setMouseCallback(const String & winname, MouseCallback onMouse, void * userdata = 0);

 

인수

 

  • winname: 창의 이름
  • onMouse: 마우스 이벤트에 대한 콜백 함수
  • userdata: 콜백에 전달되는 선택적 인수

 

파이썬:

 

# Read Images
image = cv2.imread("../Input/sample.jpg")
# Make a temporary image, will be useful to clear the drawing
temp = image.copy()
# Create a named window.
cv2.namedWindow("Window")
# highgui function called when mouse events occur
cv2.setMouseCallback("Window", drawRectangle)

 

C++:

 

image = imread("../Input/sample.jpg");
// Make a temp image, which will be used to clear the image
Mat temp = image.clone();
// Create a named window
namedWindow("Window");
// highgui function called when mouse events occur
setMouseCallback("Window", drawRectangle);

 

마지막 단계에서는 사용자가 명명된 창과 상호 작용할 수 있도록 디스플레이 루프를 만들어야 합니다. 따라서 아래 코드에서는 다음을 수행합니다.

 

  • 사용자가 'q' 키(ASCII 코드: 113)를 눌러 애플리케이션 스크립트를 종료할 때까지 이미지를 계속 표시하는 while 루프를 생성하십시오.
  • 루프 내에서 사용자가 이전에 추가한 모든 주석을 지울 수 있는 기능을 제공하십시오. 사용자는 지정된 창 내 이미지를 원본 이미지 읽기 시 생성된 복사본으로 재설정할 수 있습니다. 이는 키보드 입력 'c'(ASCII 코드: 99)를 감지함으로써 간단히 구현됩니다.  
  • 사용자가 루프를 종료하면 destroyAllWindows()를 사용하여 창을 파괴합니다. 

 

해당 기능의 사용법에 익숙하지 않다면 여기에서waitKey() '시작하기' 시리즈의 첫 번째 게시물을 살펴보세요 .

 

파이썬:

 

k=0
while k!=113:
  cv2.imshow("Window", image)
  k = cv2.waitKey(0)
  if (k == 99):
    image= temp.copy()
    cv2.imshow("Window", image)
cv2.destroyAllWindows()

 

C++:

 

int k = 0;
while(k!=113)
{
  imshow("Window", image );
  k= waitKey(0);
  if(k == 99)
  {
    temp.copyTo(image);
  }
}
destroyAllWindows();

 

이 코드를 실행하면 아래와 같이 사용자가 이미지에 하나 이상의 사각형을 그릴 수 있습니다. 이미지에 사각형을 그리는 것은 마우스 포인터 사용법을 간단히 보여준 것일 뿐입니다. 이 코드의 진정한 힘은 사용자와 이미지의 상호작용을 감지하고 애플리케이션에 필요한 모든 기능을 제공할 수 있다는 것입니다.

 

마우스를 사용하여 주석을 단 이미지 속 사각형을 보여주는 이미지입니다.

 

 

마우스를 사용하여 사각형으로 이미지에 주석을 달아 출력합니다.

 

트랙바를 사용하여 이미지 크기 조정

 

이제 트랙바를 사용하여 이미지 크기를 조정하는 방법을 보여드리겠습니다. 다음 코드를 살펴보세요.

 

파이썬:

 

# Import dependancies
import cv2
 
maxScaleUp = 100
scaleFactor = 1
windowName = "Resize Image"
trackbarValue = "Scale"
 
# read the image
image = cv2.imread("../Input/sample.jpg")
 
# Create a window to display results and  set the flag to Autosize
cv2.namedWindow(windowName, cv2.WINDOW_AUTOSIZE)
 
# Callback functions
def scaleImage(*args):
    # Get the scale factor from the trackbar 
    scaleFactor = 1+ args[0]/100.0
    # Resize the image
    scaledImage = cv2.resize(image, None, fx=scaleFactor, fy = scaleFactor, interpolation = cv2.INTER_LINEAR)
    cv2.imshow(windowName, scaledImage)
 
# Create trackbar and associate a callback function
cv2.createTrackbar(trackbarValue, windowName, scaleFactor, maxScaleUp, scaleImage)
 
# Display the image
cv2.imshow(windowName, image)
c = cv2.waitKey(0)
cv2.destroyAllWindows()

 

C++:

 

// Import Packages
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
 
// Using namespace to nullify use of cv::function(); syntax
using namespace std;
using namespace cv;
 
int maxScaleUp = 100;
int scaleFactor = 1;
 
string windowName = "Resize Image";
string trackbarValue = "Scale";
 
// Callback functions
void scaleImage(int, void*)
{
  // Read the image
  Mat image = imread("../../Input/sample.jpg");
 
    // Get the Scale factor from the trackbar
    double scaleFactorDouble = 1 + scaleFactor/100.0;
     
  // Set the factor to 1 if becomes 0
    if (scaleFactorDouble == 0)
  {
        scaleFactorDouble = 1;
    }
     
    Mat scaledImage;
    // Resize the image
    resize(image, scaledImage, Size(), scaleFactorDouble, scaleFactorDouble, INTER_LINEAR);
    // Display the image
    imshow(windowName, scaledImage);
}
 
int main()
{
// load an image
Mat image = imread("../../Input/sample.jpg");
 
// Create a window to display results and set the flag to Autosize
namedWindow(windowName, WINDOW_AUTOSIZE);
 
// Create Trackbars and associate a callback function
createTrackbar(trackbarValue, windowName, &scaleFactor, maxScaleUp, scaleImage);
scaleImage(25,0);
 
// Display image
imshow(windowName, image);
waitKey(0);
destroyAllWindows();
return 0;
}

 

OpenCV에서 이미지 크기 조정하는 방법을 이미 배우셨으니, 자세한 내용을 다시 살펴보시려면 이 게시물을 참조하세요 . 여기에서는 OpenCV의 트랙바 함수를 사용하여 사용자 지정 콜백 함수를 만드는 방법을 중점적으로 살펴보겠습니다. 이 예제는 위에서 설명한 마우스 포인터 예제와 매우 유사하므로, 주로 트랙바와 관련된 세부 사항을 살펴보겠습니다.

 

아래와 같이 패키지를 가져오는 것으로 시작합니다.

 

파이썬:

 

# Import dependencies

import cv2

 

C++:

 

// Import Packages
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
 
// Using namespace to nullify use of cv::function(); syntax
 
using namespace std;
using namespace cv;

 

다음으로, 몇 가지 변수와 문자열을 초기화합니다. 이 변수와 문자열은 트랙바를 생성하고 콜백 함수를 구현하는 데 필요합니다.

 

  • scaleFactor 이미지 크기 조정을 위해 정의하려는 콜백 함수에서 사용됩니다.
  • maxScaleUp트랙바 위치가 기록하는 최대값입니다. 트랙바 위치를 사용하여 백분율로 크기를 직접 조정할 수 있으므로 최대값을 100으로 설정하는 것이 가장 좋습니다.

 

파이썬:

 

maxScaleUp = 100
scaleFactor = 1
windowName = "Resize Image"
trackbarValue = "Scale"

 

C++:

 

int maxScaleUp = 100;
int scaleFactor = 1;
 
string windowName = "Resize Image";
string trackbarValue = "Scale";

 

 

이제 imread()를 사용하여 샘플 이미지를 읽고, 이름이 지정된 창도 생성해 보겠습니다. namedWindow() 함수에서 WINDOW_AUTOSIZE 플래그를 전달합니다. 이는 이미지 크기를 조정할 수 있게 해주므로 중요합니다.

 

 

파이썬:

 

# load an image
image = cv2.imread("../Input/sample.jpg")
 
# Create a window to display results
cv2.namedWindow(windowName, cv2.WINDOW_AUTOSIZE)

 

C++:

 

// load an image
Mat image = imread("../Input/sample.jpg");
 
// Create a window to display results and set the flag to Autosize
namedWindow(windowName, WINDOW_AUTOSIZE);

 

이제 콜백 함수에 대해 이야기할 준비가 되었습니다. 이 함수는 사용자가 트랙바와 상호 작용할 때 호출됩니다. 트랙바 콜백 함수를 정의하는 것은 마우스 콜백 함수를 정의하는 것과 매우 유사합니다. TrackbarCallback 함수 시그니처를 준수한 다음 해당 콜백 함수를 트랙바에 연결하기만 하면 됩니다.

 

  • Python과 C++에 대해 아래와 같이 함수 서명으로 콜백 함수를 정의합니다.
  • 이전과 마찬가지로 함수 이름을 원하는 대로 지정하세요. 이 경우에는 . 라고 지정했습니다 scaleImage().
  • Python 코드에서 args[0]0~100 사이의 값으로 트랙바 위치를 검색합니다.
  • 트랙바 위치에 기반하여 스케일 팩터를 계산하고, 해당 스케일 팩터를 resize() 함수에 입력하여 이미지 크기를 조정합니다.
  • 파이썬 코드에서는 이미지의 데이터 유형을 명시할 필요가 없습니다. 그러나 C++에서는 이를 Mat으로 초기화해야 합니다. 

 

코드는 다음과 같습니다.

 

파이썬:

 

def scaleImage(*args):
     
    # Get the scale factor from the trackbar 
    scaleFactor = 1+ args[0]/100.0
     
    # Resize the image
    scaledImage = cv2.resize(image, None, fx=scaleFactor, fy =    scaleFactor, interpolation = cv2.INTER_LINEAR)
    cv2.imshow(windowName, scaledImage)

 

C++:

 

void scaleImage(int, void*)
{
  Mat image = imread("../Input/sample.jpg");
 
    // Get the Scale factor from the trackbar
    double scaleFactorDouble = 1 + scaleFactor/100.0;
     
    Mat scaledImage;
     
    // Resize the image
    resize(image, scaledImage, Size(), scaleFactorDouble, scaleFactorDouble, INTER_LINEAR);
    imshow(windowName, scaledImage);
}

 

콜백 함수를 사용하는 트랙바를 만들려면 여기에 createTrackbar() 설명된 대로 함수를 호출해야 합니다 . 아래 코드에서 해당 구문을 확인하세요.

 

파이썬:

 

cv2.createTrackbar( trackbarName, windowName, value, count, onChange)

 

C++:

 

int cv::createTrackbar (const String & trackbarname, const String & winname, int * value, int count, TrackbarCallback onChange = 0, void * userdata = 0)

 

인수

 

  • trackbarname: 생성된 트랙바의 이름입니다.
  • winname: 생성된 트랙바의 부모 창 이름입니다.
  • value: 슬라이더의 기본 위치입니다. 선택 사항입니다.
  • count: 슬라이더가 어느 값까지 이동할 것인가.
  • onChange: 콜백 함수.
  • userdata: 콜백 함수에 전달되는 사용자 데이터입니다. 전역 변수를 사용하지 않고도 트랙바 이벤트를 처리하는 데 사용할 수 있습니다.

 

아래 코드에서 구현된 것을 살펴보세요.

 

파이썬:

 

cv2.createTrackbar(trackbarValue, windowName, scaleFactor, maxScaleUp, scaleImage)

 

C++:

 

createTrackbar(trackbarValue, windowName, &scaleFactor, maxScaleUp, scaleImage);

scaleImage(25,0);

 

imshow()마지막으로, 지정된 창에 이미지를 표시하기 위해 호출합니다 . 그 뒤에 waitKey(0)인수 0을 지정하면 창을 무한정 표시합니다.

 

파이썬:

 

cv2.imshow(windowName, image)

cv2.waitKey(0)

cv2.destroyAllWindows()

 

C++:

 

imshow(windowName, image);

waitKey(0);

destroyAllWindows();

 

트랙바가 구현된 이름이 지정된 창의 모습은 다음과 같습니다.

 

 

OpenCV 트랙바를 사용하여 이미지 크기를 조정하는 방법을 보여주는 이미지입니다.

 

OpenCV 트랙바를 사용하여 이미지 크기를 조정한 결과입니다.

 

요약

 

사용자가 시작한 마우스 이벤트와 연결할 수 있는 콜백 함수를 만드는 법을 배웠을 뿐만 아니라, setMouseCallback()과 createTrackbar()를 사용하여 이를 등록하는 방법도 익혔습니다. 이러한 기본 구성 요소들을 활용하면 다양한 흥미로운 애플리케이션을 만들 수 있습니다. 트랙바를 사용해 표시된 이미지의 밝기 강도를 변경해 보는 건 어떨까요! 

 

 

반응형

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